Skip to content

Commit

Permalink
bitcoin 0.31
Browse files Browse the repository at this point in the history
  • Loading branch information
kayabaNerve committed Oct 31, 2023
1 parent 2958f19 commit 34bcb9e
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 91 deletions.
50 changes: 35 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions coins/bitcoin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ rand_core = { version = "0.6", default-features = false }

sha2 = { version = "0.10", default-features = false }

secp256k1 = { version = "0.27", default-features = false }
bitcoin = { version = "0.30", default-features = false, features = ["no-std"] }
secp256k1 = { version = "0.28", default-features = false }
bitcoin = { version = "0.31", default-features = false, features = ["no-std"] }

k256 = { version = "^0.13.1", default-features = false, features = ["arithmetic", "bits"] }

Expand Down
2 changes: 1 addition & 1 deletion coins/bitcoin/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl ReceivedOutput {

/// The value of this output.
pub fn value(&self) -> u64 {
self.output.value
self.output.value.to_sat()
}

/// Read a ReceivedOutput from a generic satisfying Read.
Expand Down
39 changes: 26 additions & 13 deletions coins/bitcoin/src/wallet/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use bitcoin::{
sighash::{TapSighashType, SighashCache, Prevouts},
absolute::LockTime,
script::{PushBytesBuf, ScriptBuf},
OutPoint, Sequence, Witness, TxIn, TxOut, Transaction, Address,
transaction::{Version, Transaction},
OutPoint, Sequence, Witness, TxIn, Amount, TxOut, Address,
};

use crate::{
Expand Down Expand Up @@ -62,7 +63,7 @@ impl SignableTransaction {
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
let mut tx = Transaction {
version: 2,
version: Version(2),
lock_time: LockTime::ZERO,
input: vec![
TxIn {
Expand All @@ -82,13 +83,16 @@ impl SignableTransaction {
.iter()
// 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
.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(),
};
if let Some(change) = change {
// 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)
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()
}
Expand All @@ -103,8 +107,8 @@ impl SignableTransaction {

/// Returns the fee this transaction will use.
pub fn fee(&self) -> u64 {
self.prevouts.iter().map(|prevout| prevout.value).sum::<u64>() -
self.tx.output.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.to_sat()).sum::<u64>()
}

/// Create a new SignableTransaction.
Expand Down Expand Up @@ -139,7 +143,7 @@ impl SignableTransaction {
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 tx_ins = inputs
.iter()
Expand All @@ -154,15 +158,18 @@ impl SignableTransaction {
let payment_sat = payments.iter().map(|payment| payment.1).sum::<u64>();
let mut tx_outs = payments
.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<_>>();

// Add the OP_RETURN output
if let Some(data) = data {
tx_outs.push(TxOut {
value: 0,
value: Amount::ZERO,
script_pubkey: ScriptBuf::new_op_return(
&PushBytesBuf::try_from(data)
PushBytesBuf::try_from(data)
.expect("data didn't fit into PushBytes depsite being checked"),
),
})
Expand Down Expand Up @@ -209,7 +216,8 @@ impl SignableTransaction {
let fee_with_change = fee_per_weight * weight_with_change;
if let Some(value) = input_sat.checked_sub(payment_sat + fee_with_change) {
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;
needed_fee = fee_with_change;
}
Expand All @@ -225,7 +233,12 @@ impl 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,
prevouts: inputs.drain(..).map(|input| input.output).collect(),
needed_fee,
Expand Down Expand Up @@ -256,7 +269,7 @@ impl SignableTransaction {
}
for payment in &tx.output {
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![];
Expand Down
15 changes: 9 additions & 6 deletions coins/bitcoin/tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use bitcoin_serai::{
blockdata::opcodes::all::OP_RETURN,
script::{PushBytesBuf, Instruction, Instructions, Script},
address::NetworkChecked,
OutPoint, TxOut, Transaction, Network, Address,
OutPoint, Amount, TxOut, Transaction, Network, Address,
},
wallet::{
tweak_keys, address_payload, ReceivedOutput, Scanner, TransactionError, SignableTransaction,
Expand Down Expand Up @@ -58,7 +58,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint)
rpc
.rpc_call::<Vec<String>>(
"generatetoaddress",
serde_json::json!([100, Address::p2sh(Script::empty(), Network::Regtest).unwrap()]),
serde_json::json!([100, Address::p2sh(Script::new(), Network::Regtest).unwrap()]),
)
.await
.unwrap();
Expand All @@ -70,7 +70,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint)

assert_eq!(outputs.len(), 1);
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!(
ReceivedOutput::read::<&[u8]>(&mut outputs[0].serialize().as_ref()).unwrap(),
Expand Down Expand Up @@ -296,21 +296,24 @@ async_sequential! {

// Make sure the payments were properly created
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 );
}

// Make sure the change is correct
assert_eq!(needed_fee, u64::try_from(tx.weight()).unwrap() * FEE);
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);

let change_amount =
input_value - payments.iter().map(|payment| payment.1).sum::<u64>() - needed_fee;
assert_eq!(
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
Expand Down
2 changes: 1 addition & 1 deletion processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ frost-schnorrkel = { path = "../crypto/schnorrkel" }
sp-application-crypto = { git = "https://github.com/serai-dex/substrate", default-features = false }

# 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 }
bitcoin-serai = { path = "../coins/bitcoin", optional = true }

Expand Down
23 changes: 13 additions & 10 deletions processor/src/networks/bitcoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use bitcoin_serai::bitcoin::{
sighash::{EcdsaSighashType, SighashCache},
script::{PushBytesBuf, Builder},
absolute::LockTime,
Sequence, Script, Witness, TxIn,
Sequence, Script, Witness, TxIn, Amount as BAmount,
transaction::Version,
};

use serai_client::{
Expand Down Expand Up @@ -106,7 +107,7 @@ impl OutputTrait<Bitcoin> for Output {

fn key(&self) -> ProjectivePoint {
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 {
panic!("last item in v1 Taproot script wasn't bytes")
};
Expand Down Expand Up @@ -177,10 +178,11 @@ impl TransactionTrait<Bitcoin> for Transaction {
hash.reverse();
value += network.rpc.get_transaction(&hash).await.unwrap().output
[usize::try_from(output.vout).unwrap()]
.value;
.value
.to_sat();
}
for output in &self.output {
value -= output.value;
value -= output.value.to_sat();
}
value
}
Expand Down Expand Up @@ -331,9 +333,10 @@ impl Bitcoin {
input_tx.reverse();
in_value += self.get_transaction(&input_tx).await?.output
[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());
}
}
Expand Down Expand Up @@ -708,7 +711,7 @@ impl Network for Bitcoin {
.rpc
.rpc_call::<Vec<String>>(
"generatetoaddress",
serde_json::json!([1, BAddress::p2sh(Script::empty(), BitcoinNetwork::Regtest).unwrap()]),
serde_json::json!([1, BAddress::p2sh(Script::new(), BitcoinNetwork::Regtest).unwrap()]),
)
.await
.unwrap();
Expand All @@ -734,16 +737,16 @@ impl Network for Bitcoin {

let tx = self.get_block(new_block).await.unwrap().txdata.swap_remove(0);
let mut tx = Transaction {
version: 2,
version: Version(2),
lock_time: LockTime::ZERO,
input: vec![TxIn {
previous_output: OutPoint { txid: tx.txid(), vout: 0 },
script_sig: Script::empty().into(),
script_sig: Script::new().into(),
sequence: Sequence(u32::MAX),
witness: Witness::default(),
}],
output: vec![TxOut {
value: tx.output[0].value - 10000,
value: tx.output[0].value - BAmount::from_sat(10000),
script_pubkey: address.0.script_pubkey(),
}],
};
Expand Down
2 changes: 1 addition & 1 deletion substrate/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ serai-runtime = { path = "../runtime", version = "0.1" }
sp-core = { git = "https://github.com/serai-dex/substrate" }
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 }
monero-serai = { path = "../../coins/monero", version = "0.1.4-alpha", optional = true }
Expand Down
Loading

0 comments on commit 34bcb9e

Please sign in to comment.