mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 21:49:26 +00:00
Merge branch 'develop' into HEAD
This commit is contained in:
@@ -36,7 +36,7 @@ async-lock = "3"
|
||||
|
||||
simple-request = { path = "../../common/request", version = "0.1", optional = true }
|
||||
|
||||
bitcoin = { version = "0.31", optional = true }
|
||||
bitcoin = { version = "0.32", optional = true }
|
||||
|
||||
ciphersuite = { path = "../../crypto/ciphersuite", version = "0.4", optional = true }
|
||||
monero-serai = { path = "../../coins/monero", version = "0.1.4-alpha", optional = true }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use core::str::FromStr;
|
||||
use core::{str::FromStr, fmt};
|
||||
|
||||
use scale::{Encode, Decode};
|
||||
|
||||
@@ -6,38 +6,46 @@ use bitcoin::{
|
||||
hashes::{Hash as HashTrait, hash160::Hash},
|
||||
PubkeyHash, ScriptHash,
|
||||
network::Network,
|
||||
WitnessVersion, WitnessProgram,
|
||||
address::{Error, Payload, NetworkChecked, Address as BAddressGeneric},
|
||||
WitnessVersion, WitnessProgram, ScriptBuf,
|
||||
address::{AddressType, NetworkChecked, Address as BAddress},
|
||||
};
|
||||
|
||||
type BAddress = BAddressGeneric<NetworkChecked>;
|
||||
|
||||
#[derive(Clone, Eq, Debug)]
|
||||
pub struct Address(BAddress);
|
||||
pub struct Address(ScriptBuf);
|
||||
|
||||
impl PartialEq for Address {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// Since Serai defines the Bitcoin-address specification as a variant of the payload alone,
|
||||
// define equivalency as the payload alone
|
||||
self.0.payload() == other.0.payload()
|
||||
// Since Serai defines the Bitcoin-address specification as a variant of the script alone,
|
||||
// define equivalency as the script alone
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Address> for ScriptBuf {
|
||||
fn from(addr: Address) -> ScriptBuf {
|
||||
addr.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Address {
|
||||
type Err = Error;
|
||||
fn from_str(str: &str) -> Result<Address, Error> {
|
||||
type Err = ();
|
||||
fn from_str(str: &str) -> Result<Address, ()> {
|
||||
Address::new(
|
||||
BAddressGeneric::from_str(str)
|
||||
.map_err(|_| Error::UnrecognizedScript)?
|
||||
.require_network(Network::Bitcoin)?,
|
||||
BAddress::from_str(str)
|
||||
.map_err(|_| ())?
|
||||
.require_network(Network::Bitcoin)
|
||||
.map_err(|_| ())?
|
||||
.script_pubkey(),
|
||||
)
|
||||
.ok_or(Error::UnrecognizedScript)
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for Address {
|
||||
fn to_string(&self) -> String {
|
||||
self.0.to_string()
|
||||
impl fmt::Display for Address {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
BAddress::<NetworkChecked>::from_script(&self.0, Network::Bitcoin)
|
||||
.map_err(|_| fmt::Error)?
|
||||
.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,55 +62,52 @@ enum EncodedAddress {
|
||||
impl TryFrom<Vec<u8>> for Address {
|
||||
type Error = ();
|
||||
fn try_from(data: Vec<u8>) -> Result<Address, ()> {
|
||||
Ok(Address(BAddress::new(
|
||||
Network::Bitcoin,
|
||||
match EncodedAddress::decode(&mut data.as_ref()).map_err(|_| ())? {
|
||||
EncodedAddress::P2PKH(hash) => {
|
||||
Payload::PubkeyHash(PubkeyHash::from_raw_hash(Hash::from_byte_array(hash)))
|
||||
}
|
||||
EncodedAddress::P2SH(hash) => {
|
||||
Payload::ScriptHash(ScriptHash::from_raw_hash(Hash::from_byte_array(hash)))
|
||||
}
|
||||
EncodedAddress::P2WPKH(hash) => {
|
||||
Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V0, hash).unwrap())
|
||||
}
|
||||
EncodedAddress::P2WSH(hash) => {
|
||||
Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V0, hash).unwrap())
|
||||
}
|
||||
EncodedAddress::P2TR(key) => {
|
||||
Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V1, key).unwrap())
|
||||
}
|
||||
},
|
||||
)))
|
||||
Ok(Address(match EncodedAddress::decode(&mut data.as_ref()).map_err(|_| ())? {
|
||||
EncodedAddress::P2PKH(hash) => {
|
||||
ScriptBuf::new_p2pkh(&PubkeyHash::from_raw_hash(Hash::from_byte_array(hash)))
|
||||
}
|
||||
EncodedAddress::P2SH(hash) => {
|
||||
ScriptBuf::new_p2sh(&ScriptHash::from_raw_hash(Hash::from_byte_array(hash)))
|
||||
}
|
||||
EncodedAddress::P2WPKH(hash) => {
|
||||
ScriptBuf::new_witness_program(&WitnessProgram::new(WitnessVersion::V0, &hash).unwrap())
|
||||
}
|
||||
EncodedAddress::P2WSH(hash) => {
|
||||
ScriptBuf::new_witness_program(&WitnessProgram::new(WitnessVersion::V0, &hash).unwrap())
|
||||
}
|
||||
EncodedAddress::P2TR(key) => {
|
||||
ScriptBuf::new_witness_program(&WitnessProgram::new(WitnessVersion::V1, &key).unwrap())
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_to_vec(addr: &Address) -> Result<Vec<u8>, ()> {
|
||||
let parsed_addr =
|
||||
BAddress::<NetworkChecked>::from_script(&addr.0, Network::Bitcoin).map_err(|_| ())?;
|
||||
Ok(
|
||||
(match addr.0.payload() {
|
||||
Payload::PubkeyHash(hash) => EncodedAddress::P2PKH(*hash.as_raw_hash().as_byte_array()),
|
||||
Payload::ScriptHash(hash) => EncodedAddress::P2SH(*hash.as_raw_hash().as_byte_array()),
|
||||
Payload::WitnessProgram(program) => match program.version() {
|
||||
WitnessVersion::V0 => {
|
||||
let program = program.program();
|
||||
if program.len() == 20 {
|
||||
let mut buf = [0; 20];
|
||||
buf.copy_from_slice(program.as_ref());
|
||||
EncodedAddress::P2WPKH(buf)
|
||||
} else if program.len() == 32 {
|
||||
let mut buf = [0; 32];
|
||||
buf.copy_from_slice(program.as_ref());
|
||||
EncodedAddress::P2WSH(buf)
|
||||
} else {
|
||||
Err(())?
|
||||
}
|
||||
}
|
||||
WitnessVersion::V1 => {
|
||||
let program_ref: &[u8] = program.program().as_ref();
|
||||
EncodedAddress::P2TR(program_ref.try_into().map_err(|_| ())?)
|
||||
}
|
||||
_ => Err(())?,
|
||||
},
|
||||
(match parsed_addr.address_type() {
|
||||
Some(AddressType::P2pkh) => {
|
||||
EncodedAddress::P2PKH(*parsed_addr.pubkey_hash().unwrap().as_raw_hash().as_byte_array())
|
||||
}
|
||||
Some(AddressType::P2sh) => {
|
||||
EncodedAddress::P2SH(*parsed_addr.script_hash().unwrap().as_raw_hash().as_byte_array())
|
||||
}
|
||||
Some(AddressType::P2wpkh) => {
|
||||
let program = parsed_addr.witness_program().ok_or(())?;
|
||||
let program = program.program().as_bytes();
|
||||
EncodedAddress::P2WPKH(program.try_into().map_err(|_| ())?)
|
||||
}
|
||||
Some(AddressType::P2wsh) => {
|
||||
let program = parsed_addr.witness_program().ok_or(())?;
|
||||
let program = program.program().as_bytes();
|
||||
EncodedAddress::P2WSH(program.try_into().map_err(|_| ())?)
|
||||
}
|
||||
Some(AddressType::P2tr) => {
|
||||
let program = parsed_addr.witness_program().ok_or(())?;
|
||||
let program = program.program().as_bytes();
|
||||
EncodedAddress::P2TR(program.try_into().map_err(|_| ())?)
|
||||
}
|
||||
_ => Err(())?,
|
||||
})
|
||||
.encode(),
|
||||
@@ -116,20 +121,8 @@ impl From<Address> for Vec<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Address> for BAddress {
|
||||
fn from(addr: Address) -> BAddress {
|
||||
addr.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<BAddress> for Address {
|
||||
fn as_ref(&self) -> &BAddress {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Address {
|
||||
pub fn new(address: BAddress) -> Option<Self> {
|
||||
pub fn new(address: ScriptBuf) -> Option<Self> {
|
||||
let res = Self(address);
|
||||
if try_to_vec(&res).is_ok() {
|
||||
return Some(res);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use core::str::FromStr;
|
||||
use core::{str::FromStr, fmt};
|
||||
|
||||
use scale::{Encode, Decode};
|
||||
|
||||
@@ -24,9 +24,9 @@ impl FromStr for Address {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for Address {
|
||||
fn to_string(&self) -> String {
|
||||
self.0.to_string()
|
||||
impl fmt::Display for Address {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,12 @@ macro_rules! serai_test {
|
||||
"--rpc-cors".to_string(),
|
||||
"all".to_string(),
|
||||
])
|
||||
.replace_env(HashMap::from([("RUST_LOG".to_string(), "runtime=debug".to_string())]))
|
||||
.replace_env(
|
||||
HashMap::from([
|
||||
("RUST_LOG".to_string(), "runtime=debug".to_string()),
|
||||
("KEY".to_string(), " ".to_string()),
|
||||
])
|
||||
)
|
||||
.set_publish_all_ports(true)
|
||||
.set_handle(handle)
|
||||
.set_start_policy(StartPolicy::Strict)
|
||||
|
||||
@@ -14,7 +14,9 @@ async fn dht() {
|
||||
TestBodySpecification::with_image(
|
||||
Image::with_repository("serai-dev-serai").pull_policy(PullPolicy::Never),
|
||||
)
|
||||
.replace_env([("SERAI_NAME".to_string(), name.to_string())].into())
|
||||
.replace_env(
|
||||
[("SERAI_NAME".to_string(), name.to_string()), ("KEY".to_string(), " ".to_string())].into(),
|
||||
)
|
||||
.set_publish_all_ports(true)
|
||||
.set_handle(handle(name))
|
||||
.set_start_policy(StartPolicy::Strict)
|
||||
|
||||
@@ -102,7 +102,10 @@ async fn validator_set_rotation() {
|
||||
"local".to_string(),
|
||||
format!("--{name}"),
|
||||
])
|
||||
.replace_env(HashMap::from([("RUST_LOG=runtime".to_string(), "debug".to_string())]))
|
||||
.replace_env(HashMap::from([
|
||||
("RUST_LOG".to_string(), "runtime=debug".to_string()),
|
||||
("KEY".to_string(), " ".to_string()),
|
||||
]))
|
||||
.set_publish_all_ports(true)
|
||||
.set_handle(handle(name))
|
||||
.set_start_policy(StartPolicy::Strict)
|
||||
|
||||
Reference in New Issue
Block a user