Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bitcoin 0.31 #412

Merged
merged 1 commit into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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