bitcoin 0.31

This commit is contained in:
Luke Parker 2023-10-30 04:45:20 -04:00
parent 2958f196fc
commit 34bcb9eb01
12 changed files with 122 additions and 91 deletions

50
Cargo.lock generated
View file

@ -440,6 +440,12 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
[[package]]
name = "bech32"
version = "0.10.0-beta"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea"
[[package]] [[package]]
name = "beef" name = "beef"
version = "0.5.2" version = "0.5.2"
@ -496,24 +502,28 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]] [[package]]
name = "bitcoin" name = "bitcoin"
version = "0.30.1" version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e99ff7289b20a7385f66a0feda78af2fc119d28fb56aea8886a9cd0a4abdd75" checksum = "5973a027b341b462105675962214dfe3c938ad9afd395d84b28602608bdcec7b"
dependencies = [ dependencies = [
"bech32", "bech32 0.10.0-beta",
"bitcoin-private", "bitcoin-internals",
"bitcoin_hashes", "bitcoin_hashes",
"core2 0.3.3", "core2 0.3.3",
"hex-conservative",
"hex_lit", "hex_lit",
"secp256k1", "secp256k1",
"serde", "serde",
] ]
[[package]] [[package]]
name = "bitcoin-private" name = "bitcoin-internals"
version = "0.1.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "bitcoin-serai" name = "bitcoin-serai"
@ -538,12 +548,13 @@ dependencies = [
[[package]] [[package]]
name = "bitcoin_hashes" name = "bitcoin_hashes"
version = "0.12.0" version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b"
dependencies = [ dependencies = [
"bitcoin-private", "bitcoin-internals",
"core2 0.3.3", "core2 0.3.3",
"hex-conservative",
"serde", "serde",
] ]
@ -1050,7 +1061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979"
dependencies = [ dependencies = [
"base64 0.21.5", "base64 0.21.5",
"bech32", "bech32 0.9.1",
"bs58", "bs58",
"digest 0.10.7", "digest 0.10.7",
"generic-array 0.14.7", "generic-array 0.14.7",
@ -3274,6 +3285,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hex-conservative"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2"
dependencies = [
"core2 0.3.3",
]
[[package]] [[package]]
name = "hex-literal" name = "hex-literal"
version = "0.4.1" version = "0.4.1"
@ -8044,9 +8064,9 @@ dependencies = [
[[package]] [[package]]
name = "secp256k1" name = "secp256k1"
version = "0.27.0" version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5"
dependencies = [ dependencies = [
"bitcoin_hashes", "bitcoin_hashes",
"rand", "rand",
@ -8056,9 +8076,9 @@ dependencies = [
[[package]] [[package]]
name = "secp256k1-sys" name = "secp256k1-sys"
version = "0.8.1" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" checksum = "09e67c467c38fd24bd5499dc9a18183b31575c12ee549197e3e20d57aa4fe3b7"
dependencies = [ dependencies = [
"cc", "cc",
] ]

View file

@ -17,8 +17,8 @@ rand_core = { version = "0.6", default-features = false }
sha2 = { version = "0.10", default-features = false } sha2 = { version = "0.10", default-features = false }
secp256k1 = { version = "0.27", default-features = false } secp256k1 = { version = "0.28", default-features = false }
bitcoin = { version = "0.30", default-features = false, features = ["no-std"] } bitcoin = { version = "0.31", default-features = false, features = ["no-std"] }
k256 = { version = "^0.13.1", default-features = false, features = ["arithmetic", "bits"] } k256 = { version = "^0.13.1", default-features = false, features = ["arithmetic", "bits"] }

View file

@ -83,7 +83,7 @@ impl ReceivedOutput {
/// The value of this output. /// The value of this output.
pub fn value(&self) -> u64 { pub fn value(&self) -> u64 {
self.output.value self.output.value.to_sat()
} }
/// Read a ReceivedOutput from a generic satisfying Read. /// Read a ReceivedOutput from a generic satisfying Read.

View file

@ -16,7 +16,8 @@ use bitcoin::{
sighash::{TapSighashType, SighashCache, Prevouts}, sighash::{TapSighashType, SighashCache, Prevouts},
absolute::LockTime, absolute::LockTime,
script::{PushBytesBuf, ScriptBuf}, script::{PushBytesBuf, ScriptBuf},
OutPoint, Sequence, Witness, TxIn, TxOut, Transaction, Address, transaction::{Version, Transaction},
OutPoint, Sequence, Witness, TxIn, Amount, TxOut, Address,
}; };
use crate::{ use crate::{
@ -62,7 +63,7 @@ impl SignableTransaction {
fn calculate_weight(inputs: usize, payments: &[(Address, u64)], change: Option<&Address>) -> u64 { fn calculate_weight(inputs: usize, payments: &[(Address, u64)], change: Option<&Address>) -> u64 {
// Expand this a full transaction in order to use the bitcoin library's weight function // Expand this a full transaction in order to use the bitcoin library's weight function
let mut tx = Transaction { let mut tx = Transaction {
version: 2, version: Version(2),
lock_time: LockTime::ZERO, lock_time: LockTime::ZERO,
input: vec![ input: vec![
TxIn { TxIn {
@ -82,13 +83,16 @@ impl SignableTransaction {
.iter() .iter()
// The payment is a fixed size so we don't have to use it here // The payment is a fixed size so we don't have to use it here
// The script pub key is not of a fixed size and does have to be used here // The script pub key is not of a fixed size and does have to be used here
.map(|payment| TxOut { value: payment.1, script_pubkey: payment.0.script_pubkey() }) .map(|payment| TxOut {
value: Amount::from_sat(payment.1),
script_pubkey: payment.0.script_pubkey(),
})
.collect(), .collect(),
}; };
if let Some(change) = change { if let Some(change) = change {
// Use a 0 value since we're currently unsure what the change amount will be, and since // Use a 0 value since we're currently unsure what the change amount will be, and since
// the value is fixed size (so any value could be used here) // the value is fixed size (so any value could be used here)
tx.output.push(TxOut { value: 0, script_pubkey: change.script_pubkey() }); tx.output.push(TxOut { value: Amount::ZERO, script_pubkey: change.script_pubkey() });
} }
u64::try_from(tx.weight()).unwrap() u64::try_from(tx.weight()).unwrap()
} }
@ -103,8 +107,8 @@ impl SignableTransaction {
/// Returns the fee this transaction will use. /// Returns the fee this transaction will use.
pub fn fee(&self) -> u64 { pub fn fee(&self) -> u64 {
self.prevouts.iter().map(|prevout| prevout.value).sum::<u64>() - self.prevouts.iter().map(|prevout| prevout.value.to_sat()).sum::<u64>() -
self.tx.output.iter().map(|prevout| prevout.value).sum::<u64>() self.tx.output.iter().map(|prevout| prevout.value.to_sat()).sum::<u64>()
} }
/// Create a new SignableTransaction. /// Create a new SignableTransaction.
@ -139,7 +143,7 @@ impl SignableTransaction {
Err(TransactionError::TooMuchData)?; Err(TransactionError::TooMuchData)?;
} }
let input_sat = inputs.iter().map(|input| input.output.value).sum::<u64>(); let input_sat = inputs.iter().map(|input| input.output.value.to_sat()).sum::<u64>();
let offsets = inputs.iter().map(|input| input.offset).collect(); let offsets = inputs.iter().map(|input| input.offset).collect();
let tx_ins = inputs let tx_ins = inputs
.iter() .iter()
@ -154,15 +158,18 @@ impl SignableTransaction {
let payment_sat = payments.iter().map(|payment| payment.1).sum::<u64>(); let payment_sat = payments.iter().map(|payment| payment.1).sum::<u64>();
let mut tx_outs = payments let mut tx_outs = payments
.iter() .iter()
.map(|payment| TxOut { value: payment.1, script_pubkey: payment.0.script_pubkey() }) .map(|payment| TxOut {
value: Amount::from_sat(payment.1),
script_pubkey: payment.0.script_pubkey(),
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// Add the OP_RETURN output // Add the OP_RETURN output
if let Some(data) = data { if let Some(data) = data {
tx_outs.push(TxOut { tx_outs.push(TxOut {
value: 0, value: Amount::ZERO,
script_pubkey: ScriptBuf::new_op_return( script_pubkey: ScriptBuf::new_op_return(
&PushBytesBuf::try_from(data) PushBytesBuf::try_from(data)
.expect("data didn't fit into PushBytes depsite being checked"), .expect("data didn't fit into PushBytes depsite being checked"),
), ),
}) })
@ -209,7 +216,8 @@ impl SignableTransaction {
let fee_with_change = fee_per_weight * weight_with_change; let fee_with_change = fee_per_weight * weight_with_change;
if let Some(value) = input_sat.checked_sub(payment_sat + fee_with_change) { if let Some(value) = input_sat.checked_sub(payment_sat + fee_with_change) {
if value >= DUST { if value >= DUST {
tx_outs.push(TxOut { value, script_pubkey: change.script_pubkey() }); tx_outs
.push(TxOut { value: Amount::from_sat(value), script_pubkey: change.script_pubkey() });
weight = weight_with_change; weight = weight_with_change;
needed_fee = fee_with_change; needed_fee = fee_with_change;
} }
@ -225,7 +233,12 @@ impl SignableTransaction {
} }
Ok(SignableTransaction { Ok(SignableTransaction {
tx: Transaction { version: 2, lock_time: LockTime::ZERO, input: tx_ins, output: tx_outs }, tx: Transaction {
version: Version(2),
lock_time: LockTime::ZERO,
input: tx_ins,
output: tx_outs,
},
offsets, offsets,
prevouts: inputs.drain(..).map(|input| input.output).collect(), prevouts: inputs.drain(..).map(|input| input.output).collect(),
needed_fee, needed_fee,
@ -256,7 +269,7 @@ impl SignableTransaction {
} }
for payment in &tx.output { for payment in &tx.output {
transcript.append_message(b"output_script", payment.script_pubkey.as_bytes()); transcript.append_message(b"output_script", payment.script_pubkey.as_bytes());
transcript.append_message(b"output_amount", payment.value.to_le_bytes()); transcript.append_message(b"output_amount", payment.value.to_sat().to_le_bytes());
} }
let mut sigs = vec![]; let mut sigs = vec![];

View file

@ -23,7 +23,7 @@ use bitcoin_serai::{
blockdata::opcodes::all::OP_RETURN, blockdata::opcodes::all::OP_RETURN,
script::{PushBytesBuf, Instruction, Instructions, Script}, script::{PushBytesBuf, Instruction, Instructions, Script},
address::NetworkChecked, address::NetworkChecked,
OutPoint, TxOut, Transaction, Network, Address, OutPoint, Amount, TxOut, Transaction, Network, Address,
}, },
wallet::{ wallet::{
tweak_keys, address_payload, ReceivedOutput, Scanner, TransactionError, SignableTransaction, tweak_keys, address_payload, ReceivedOutput, Scanner, TransactionError, SignableTransaction,
@ -58,7 +58,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint)
rpc rpc
.rpc_call::<Vec<String>>( .rpc_call::<Vec<String>>(
"generatetoaddress", "generatetoaddress",
serde_json::json!([100, Address::p2sh(Script::empty(), Network::Regtest).unwrap()]), serde_json::json!([100, Address::p2sh(Script::new(), Network::Regtest).unwrap()]),
) )
.await .await
.unwrap(); .unwrap();
@ -70,7 +70,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint)
assert_eq!(outputs.len(), 1); assert_eq!(outputs.len(), 1);
assert_eq!(outputs[0].outpoint(), &OutPoint::new(block.txdata[0].txid(), 0)); assert_eq!(outputs[0].outpoint(), &OutPoint::new(block.txdata[0].txid(), 0));
assert_eq!(outputs[0].value(), block.txdata[0].output[0].value); assert_eq!(outputs[0].value(), block.txdata[0].output[0].value.to_sat());
assert_eq!( assert_eq!(
ReceivedOutput::read::<&[u8]>(&mut outputs[0].serialize().as_ref()).unwrap(), ReceivedOutput::read::<&[u8]>(&mut outputs[0].serialize().as_ref()).unwrap(),
@ -296,21 +296,24 @@ async_sequential! {
// Make sure the payments were properly created // Make sure the payments were properly created
for ((output, scanned), payment) in tx.output.iter().zip(outputs.iter()).zip(payments.iter()) { for ((output, scanned), payment) in tx.output.iter().zip(outputs.iter()).zip(payments.iter()) {
assert_eq!(output, &TxOut { script_pubkey: payment.0.script_pubkey(), value: payment.1 }); assert_eq!(
output,
&TxOut { script_pubkey: payment.0.script_pubkey(), value: Amount::from_sat(payment.1) },
);
assert_eq!(scanned.value(), payment.1 ); assert_eq!(scanned.value(), payment.1 );
} }
// Make sure the change is correct // Make sure the change is correct
assert_eq!(needed_fee, u64::try_from(tx.weight()).unwrap() * FEE); assert_eq!(needed_fee, u64::try_from(tx.weight()).unwrap() * FEE);
let input_value = output.value() + offset_output.value(); let input_value = output.value() + offset_output.value();
let output_value = tx.output.iter().map(|output| output.value).sum::<u64>(); let output_value = tx.output.iter().map(|output| output.value.to_sat()).sum::<u64>();
assert_eq!(input_value - output_value, needed_fee); assert_eq!(input_value - output_value, needed_fee);
let change_amount = let change_amount =
input_value - payments.iter().map(|payment| payment.1).sum::<u64>() - needed_fee; input_value - payments.iter().map(|payment| payment.1).sum::<u64>() - needed_fee;
assert_eq!( assert_eq!(
tx.output[2], tx.output[2],
TxOut { script_pubkey: change_addr.script_pubkey(), value: change_amount }, TxOut { script_pubkey: change_addr.script_pubkey(), value: Amount::from_sat(change_amount) },
); );
// This also tests send_raw_transaction and get_transaction, which the RPC test can't // This also tests send_raw_transaction and get_transaction, which the RPC test can't

View file

@ -42,7 +42,7 @@ frost-schnorrkel = { path = "../crypto/schnorrkel" }
sp-application-crypto = { git = "https://github.com/serai-dex/substrate", default-features = false } sp-application-crypto = { git = "https://github.com/serai-dex/substrate", default-features = false }
# Bitcoin # Bitcoin
secp256k1 = { version = "0.27", features = ["global-context", "rand-std"], optional = true } secp256k1 = { version = "0.28", features = ["global-context", "rand-std"], optional = true }
k256 = { version = "^0.13.1", optional = true } k256 = { version = "^0.13.1", optional = true }
bitcoin-serai = { path = "../coins/bitcoin", optional = true } bitcoin-serai = { path = "../coins/bitcoin", optional = true }

View file

@ -35,7 +35,8 @@ use bitcoin_serai::bitcoin::{
sighash::{EcdsaSighashType, SighashCache}, sighash::{EcdsaSighashType, SighashCache},
script::{PushBytesBuf, Builder}, script::{PushBytesBuf, Builder},
absolute::LockTime, absolute::LockTime,
Sequence, Script, Witness, TxIn, Sequence, Script, Witness, TxIn, Amount as BAmount,
transaction::Version,
}; };
use serai_client::{ use serai_client::{
@ -106,7 +107,7 @@ impl OutputTrait<Bitcoin> for Output {
fn key(&self) -> ProjectivePoint { fn key(&self) -> ProjectivePoint {
let script = &self.output.output().script_pubkey; let script = &self.output.output().script_pubkey;
assert!(script.is_v1_p2tr()); assert!(script.is_p2tr());
let Instruction::PushBytes(key) = script.instructions_minimal().last().unwrap().unwrap() else { let Instruction::PushBytes(key) = script.instructions_minimal().last().unwrap().unwrap() else {
panic!("last item in v1 Taproot script wasn't bytes") panic!("last item in v1 Taproot script wasn't bytes")
}; };
@ -177,10 +178,11 @@ impl TransactionTrait<Bitcoin> for Transaction {
hash.reverse(); hash.reverse();
value += network.rpc.get_transaction(&hash).await.unwrap().output value += network.rpc.get_transaction(&hash).await.unwrap().output
[usize::try_from(output.vout).unwrap()] [usize::try_from(output.vout).unwrap()]
.value; .value
.to_sat();
} }
for output in &self.output { for output in &self.output {
value -= output.value; value -= output.value.to_sat();
} }
value value
} }
@ -331,9 +333,10 @@ impl Bitcoin {
input_tx.reverse(); input_tx.reverse();
in_value += self.get_transaction(&input_tx).await?.output in_value += self.get_transaction(&input_tx).await?.output
[usize::try_from(input.previous_output.vout).unwrap()] [usize::try_from(input.previous_output.vout).unwrap()]
.value; .value
.to_sat();
} }
let out = tx.output.iter().map(|output| output.value).sum::<u64>(); let out = tx.output.iter().map(|output| output.value.to_sat()).sum::<u64>();
fees.push((in_value - out) / tx.weight().to_wu()); fees.push((in_value - out) / tx.weight().to_wu());
} }
} }
@ -708,7 +711,7 @@ impl Network for Bitcoin {
.rpc .rpc
.rpc_call::<Vec<String>>( .rpc_call::<Vec<String>>(
"generatetoaddress", "generatetoaddress",
serde_json::json!([1, BAddress::p2sh(Script::empty(), BitcoinNetwork::Regtest).unwrap()]), serde_json::json!([1, BAddress::p2sh(Script::new(), BitcoinNetwork::Regtest).unwrap()]),
) )
.await .await
.unwrap(); .unwrap();
@ -734,16 +737,16 @@ impl Network for Bitcoin {
let tx = self.get_block(new_block).await.unwrap().txdata.swap_remove(0); let tx = self.get_block(new_block).await.unwrap().txdata.swap_remove(0);
let mut tx = Transaction { let mut tx = Transaction {
version: 2, version: Version(2),
lock_time: LockTime::ZERO, lock_time: LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { txid: tx.txid(), vout: 0 }, previous_output: OutPoint { txid: tx.txid(), vout: 0 },
script_sig: Script::empty().into(), script_sig: Script::new().into(),
sequence: Sequence(u32::MAX), sequence: Sequence(u32::MAX),
witness: Witness::default(), witness: Witness::default(),
}], }],
output: vec![TxOut { output: vec![TxOut {
value: tx.output[0].value - 10000, value: tx.output[0].value - BAmount::from_sat(10000),
script_pubkey: address.0.script_pubkey(), script_pubkey: address.0.script_pubkey(),
}], }],
}; };

View file

@ -26,7 +26,7 @@ serai-runtime = { path = "../runtime", version = "0.1" }
sp-core = { git = "https://github.com/serai-dex/substrate" } sp-core = { git = "https://github.com/serai-dex/substrate" }
subxt = { version = "0.29", default-features = false, features = ["jsonrpsee-ws"], optional = true } subxt = { version = "0.29", default-features = false, features = ["jsonrpsee-ws"], optional = true }
bitcoin = { version = "0.30", optional = true } bitcoin = { version = "0.31", optional = true }
ciphersuite = { path = "../../crypto/ciphersuite", version = "0.4", optional = true } ciphersuite = { path = "../../crypto/ciphersuite", version = "0.4", optional = true }
monero-serai = { path = "../../coins/monero", version = "0.1.4-alpha", optional = true } monero-serai = { path = "../../coins/monero", version = "0.1.4-alpha", optional = true }

View file

@ -5,10 +5,9 @@ use scale::{Encode, Decode};
use bitcoin::{ use bitcoin::{
hashes::{Hash as HashTrait, hash160::Hash}, hashes::{Hash as HashTrait, hash160::Hash},
PubkeyHash, ScriptHash, PubkeyHash, ScriptHash,
network::constants::Network, network::Network,
address::{ WitnessVersion, WitnessProgram,
Error, WitnessVersion, Payload, WitnessProgram, NetworkChecked, Address as BAddressGeneric, address::{Error, Payload, NetworkChecked, Address as BAddressGeneric},
},
}; };
type BAddress = BAddressGeneric<NetworkChecked>; type BAddress = BAddressGeneric<NetworkChecked>;
@ -18,28 +17,20 @@ pub struct Address(pub BAddress);
impl PartialEq for Address { impl PartialEq for Address {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.0.payload == other.0.payload // 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()
} }
} }
impl FromStr for Address { impl FromStr for Address {
type Err = Error; type Err = Error;
fn from_str(str: &str) -> Result<Address, Error> { fn from_str(str: &str) -> Result<Address, Error> {
let mut original_address = BAddressGeneric::from_str(str)?; Ok(Address(
// Standardize the network BAddressGeneric::from_str(str)
original_address.network = Network::Bitcoin; .map_err(|_| Error::UnrecognizedScript)?
let address = original_address .require_network(Network::Bitcoin)?,
.clone() ))
.require_network(Network::Bitcoin)
.expect("network wasn't mainnet despite overriding network");
// Also check this isn't caching the string internally
if BAddressGeneric::from_str(&address.to_string())? != original_address {
// TODO: Make this an error?
panic!("Address::from_str(address.to_string()) != address for Bitcoin");
}
Ok(Address(address))
} }
} }
@ -90,7 +81,7 @@ impl TryInto<Vec<u8>> for Address {
type Error = (); type Error = ();
fn try_into(self) -> Result<Vec<u8>, ()> { fn try_into(self) -> Result<Vec<u8>, ()> {
Ok( Ok(
(match self.0.payload { (match self.0.payload() {
Payload::PubkeyHash(hash) => EncodedAddress::P2PKH(*hash.as_raw_hash().as_byte_array()), 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::ScriptHash(hash) => EncodedAddress::P2SH(*hash.as_raw_hash().as_byte_array()),
Payload::WitnessProgram(program) => match program.version() { Payload::WitnessProgram(program) => match program.version() {

View file

@ -51,7 +51,7 @@ async fn mint_and_burn_test() {
secp256k1::{SECP256K1, SecretKey}, secp256k1::{SECP256K1, SecretKey},
PrivateKey, PublicKey, PrivateKey, PublicKey,
consensus::Encodable, consensus::Encodable,
network::constants::Network, network::Network,
address::Address, address::Address,
}; };
@ -263,8 +263,9 @@ async fn mint_and_burn_test() {
sighash::{EcdsaSighashType, SighashCache}, sighash::{EcdsaSighashType, SighashCache},
script::{PushBytesBuf, Script, ScriptBuf, Builder}, script::{PushBytesBuf, Script, ScriptBuf, Builder},
absolute::LockTime, absolute::LockTime,
transaction::{Version, Transaction},
address::Payload, address::Payload,
Sequence, Witness, OutPoint, TxIn, TxOut, Transaction, Network, Sequence, Witness, OutPoint, TxIn, Amount, TxOut, Network,
}; };
let private_key = let private_key =
@ -278,17 +279,17 @@ async fn mint_and_burn_test() {
rpc.get_block(&rpc.get_block_hash(1).await.unwrap()).await.unwrap().txdata.swap_remove(0); rpc.get_block(&rpc.get_block_hash(1).await.unwrap()).await.unwrap().txdata.swap_remove(0);
#[allow(clippy::inconsistent_digit_grouping)] #[allow(clippy::inconsistent_digit_grouping)]
let mut tx = Transaction { let mut tx = Transaction {
version: 2, version: Version(2),
lock_time: LockTime::ZERO, lock_time: LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { txid: tx.txid(), vout: 0 }, previous_output: OutPoint { txid: tx.txid(), vout: 0 },
script_sig: Script::empty().into(), script_sig: Script::new().into(),
sequence: Sequence(u32::MAX), sequence: Sequence(u32::MAX),
witness: Witness::default(), witness: Witness::default(),
}], }],
output: vec![ output: vec![
TxOut { TxOut {
value: 1_100_000_00, value: Amount::from_sat(1_100_000_00),
script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked( script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(
XOnlyPublicKey::from_slice(&bitcoin_key_pair.1[1 ..]).unwrap(), XOnlyPublicKey::from_slice(&bitcoin_key_pair.1[1 ..]).unwrap(),
)) ))
@ -296,16 +297,16 @@ async fn mint_and_burn_test() {
}, },
TxOut { TxOut {
// change = amount spent - fee // change = amount spent - fee
value: tx.output[0].value - 1_100_000_00 - 1_000_00, value: Amount::from_sat(tx.output[0].value.to_sat() - 1_100_000_00 - 1_000_00),
script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked( script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(
XOnlyPublicKey::from_slice(&public_key.inner.serialize()[1 ..]).unwrap(), XOnlyPublicKey::from_slice(&public_key.inner.serialize()[1 ..]).unwrap(),
)) ))
.script_pubkey(), .script_pubkey(),
}, },
TxOut { TxOut {
value: 0, value: Amount::ZERO,
script_pubkey: ScriptBuf::new_op_return( script_pubkey: ScriptBuf::new_op_return(
&PushBytesBuf::try_from(Shorthand::transfer(None, serai_addr).encode()).unwrap(), PushBytesBuf::try_from(Shorthand::transfer(None, serai_addr).encode()).unwrap(),
), ),
}, },
], ],
@ -447,7 +448,7 @@ async fn mint_and_burn_test() {
// Create a random Bitcoin/Monero address // Create a random Bitcoin/Monero address
let bitcoin_addr = { let bitcoin_addr = {
use bitcoin_serai::bitcoin::{network::constants::Network, key::PublicKey, address::Address}; use bitcoin_serai::bitcoin::{network::Network, key::PublicKey, address::Address};
// Uses Network::Bitcoin since it doesn't actually matter, Serai strips it out // Uses Network::Bitcoin since it doesn't actually matter, Serai strips it out
// TODO: Move Serai to Payload from Address // TODO: Move Serai to Payload from Address
Address::p2pkh( Address::p2pkh(
@ -555,9 +556,9 @@ async fn mint_and_burn_test() {
.unwrap(); .unwrap();
let tx_fee = 1_100_000_00 - let tx_fee = 1_100_000_00 -
block.txdata[1].output.iter().map(|output| output.value).sum::<u64>(); block.txdata[1].output.iter().map(|output| output.value.to_sat()).sum::<u64>();
assert_eq!(received_output.value, 1_000_000_00 - tx_fee); assert_eq!(received_output.value.to_sat(), 1_000_000_00 - tx_fee);
found = true; found = true;
} }
} else { } else {

View file

@ -251,7 +251,7 @@ impl Coordinator {
match self.network { match self.network {
NetworkId::Bitcoin => { NetworkId::Bitcoin => {
use bitcoin_serai::{ use bitcoin_serai::{
bitcoin::{consensus::Encodable, network::constants::Network, Script, Address}, bitcoin::{consensus::Encodable, network::Network, Script, Address},
rpc::Rpc, rpc::Rpc,
}; };
@ -260,7 +260,7 @@ impl Coordinator {
rpc rpc
.rpc_call::<Vec<String>>( .rpc_call::<Vec<String>>(
"generatetoaddress", "generatetoaddress",
serde_json::json!([1, Address::p2sh(Script::empty(), Network::Regtest).unwrap()]), serde_json::json!([1, Address::p2sh(Script::new(), Network::Regtest).unwrap()]),
) )
.await .await
.unwrap(); .unwrap();

View file

@ -233,28 +233,28 @@ impl Wallet {
sighash::{EcdsaSighashType, SighashCache}, sighash::{EcdsaSighashType, SighashCache},
script::{PushBytesBuf, Script, ScriptBuf, Builder}, script::{PushBytesBuf, Script, ScriptBuf, Builder},
address::Payload, address::Payload,
OutPoint, Sequence, Witness, TxIn, TxOut, OutPoint, Sequence, Witness, TxIn, Amount, TxOut,
absolute::LockTime, absolute::LockTime,
Transaction, transaction::{Version, Transaction},
}; };
const AMOUNT: u64 = 100000000; const AMOUNT: u64 = 100000000;
let mut tx = Transaction { let mut tx = Transaction {
version: 2, version: Version(2),
lock_time: LockTime::ZERO, lock_time: LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { txid: input_tx.txid(), vout: 0 }, previous_output: OutPoint { txid: input_tx.txid(), vout: 0 },
script_sig: Script::empty().into(), script_sig: Script::new().into(),
sequence: Sequence(u32::MAX), sequence: Sequence(u32::MAX),
witness: Witness::default(), witness: Witness::default(),
}], }],
output: vec![ output: vec![
TxOut { TxOut {
value: input_tx.output[0].value - AMOUNT - 10000, value: Amount::from_sat(input_tx.output[0].value.to_sat() - AMOUNT - 10000),
script_pubkey: input_tx.output[0].script_pubkey.clone(), script_pubkey: input_tx.output[0].script_pubkey.clone(),
}, },
TxOut { TxOut {
value: AMOUNT, value: Amount::from_sat(AMOUNT),
script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked( script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(
XOnlyPublicKey::from_slice(&to[1 ..]).unwrap(), XOnlyPublicKey::from_slice(&to[1 ..]).unwrap(),
)) ))
@ -265,9 +265,9 @@ impl Wallet {
if let Some(instruction) = instruction { if let Some(instruction) = instruction {
tx.output.push(TxOut { tx.output.push(TxOut {
value: 0, value: Amount::ZERO,
script_pubkey: ScriptBuf::new_op_return( script_pubkey: ScriptBuf::new_op_return(
&PushBytesBuf::try_from( PushBytesBuf::try_from(
Shorthand::Raw(RefundableInInstruction { origin: None, instruction }).encode(), Shorthand::Raw(RefundableInInstruction { origin: None, instruction }).encode(),
) )
.unwrap(), .unwrap(),