Skip to content

Commit

Permalink
Update bitcoin and deps (#220)
Browse files Browse the repository at this point in the history
* Update bitcoin and deps

* fixup! Update bitcoin and deps

* Update RPC tests with unreleased bitcoincore-rpc crate

* Update changelog
  • Loading branch information
h4sh3d authored Mar 10, 2022
1 parent 21fcd5f commit 29c41e4
Show file tree
Hide file tree
Showing 18 changed files with 152 additions and 148 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Update bitcoin dependency to `0.28.0-rc.1`, aligns sub-dependencies to match new bitcoin version ([#220](https://github.com/farcaster-project/farcaster-core/pull/220))

## [0.4.4] - 2022-02-27

### Changed
Expand Down
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,23 @@ tiny-keccak = { version = "2", features = ["keccak"] }

bincode = { version = "1.3.3", optional = true }
curve25519-dalek = "3.0.2"
ecdsa_fun = { version = "0.6", default-features = false, features = ["all"], optional = true }
ecdsa_fun = { version = "0.7", default-features = false, features = ["all"], optional = true }
rand = { version = "0.8.4", optional = true }
rand_alt = { package = "rand", version = "0.7.3", features = ["std"] }
rand_chacha = { version = "0.3.1", optional = true }
secp256kfun = { version = "0.6", default-features = false, features = ["std", "serde", "libsecp_compat"], optional = true }
secp256kfun = { version = "0.7", default-features = false, features = ["std", "serde", "libsecp_compat"], optional = true }
sha2 = { version = "0.9", optional = true }
sha3 = "0.9.1"

# blockchain specific
bitcoin = "0.27"
bitcoin = "0.28.0-rc.1"
monero = { version = "0.16" }

[dev-dependencies]
bitcoincore-rpc = "0.14"
bitcoincore-rpc = { git = "https://github.com/romanz/rust-bitcoincore-rpc", rev = "cf505ae02ecd19eaf20465ec09910e724a4ede7e" }
lazy_static = "1.4"
rand_core = { version = "^0.6.3", features = ["getrandom"] }
secp256k1 = { version = "0.20", features = ["rand-std"] }
secp256k1 = { version = "0.21", features = ["rand-std"] }
serde_yaml = "0.8"

[package.metadata.docs.rs]
Expand Down
15 changes: 8 additions & 7 deletions src/bitcoin/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl<S: Strategy> Fee for Bitcoin<S> {
strategy: &FeeStrategy<SatPerVByte>,
politic: FeePriority,
) -> Result<Amount, FeeStrategyError> {
if tx.global.unsigned_tx.output.len() != 1 {
if tx.unsigned_tx.output.len() != 1 {
return Err(FeeStrategyError::new(
transaction::Error::MultiUTXOUnsuported,
));
Expand All @@ -137,7 +137,7 @@ impl<S: Strategy> Fee for Bitcoin<S> {
// FIXME This does not account for witnesses
// currently the fees are wrong
// Get the transaction weight
let weight = tx.global.unsigned_tx.get_weight() as u64;
let weight = tx.unsigned_tx.get_weight() as u64;

// Compute the fee amount to set in total
let fee_amount = match strategy {
Expand All @@ -150,7 +150,7 @@ impl<S: Strategy> Fee for Bitcoin<S> {
.ok_or(FeeStrategyError::AmountOfFeeTooHigh)?;

// Apply the fee on the first output
tx.global.unsigned_tx.output[0].value = input_sum
tx.unsigned_tx.output[0].value = input_sum
.checked_sub(fee_amount)
.ok_or(FeeStrategyError::NotEnoughAssets)?
.as_sat();
Expand All @@ -164,18 +164,18 @@ impl<S: Strategy> Fee for Bitcoin<S> {
tx: &PartiallySignedTransaction,
strategy: &FeeStrategy<SatPerVByte>,
) -> Result<bool, FeeStrategyError> {
if tx.global.unsigned_tx.output.len() != 1 {
if tx.unsigned_tx.output.len() != 1 {
return Err(FeeStrategyError::new(
transaction::Error::MultiUTXOUnsuported,
));
}

let input_sum = get_available_input_sat(tx)?.as_sat();
let output_sum = tx.global.unsigned_tx.output[0].value;
let output_sum = tx.unsigned_tx.output[0].value;
let fee = input_sum
.checked_sub(output_sum)
.ok_or(FeeStrategyError::AmountOfFeeTooHigh)?;
let weight = tx.global.unsigned_tx.get_weight() as u64;
let weight = tx.unsigned_tx.get_weight() as u64;

let effective_sat_per_vbyte = SatPerVByte::from_sat(
weight
Expand All @@ -196,6 +196,7 @@ mod tests {
for s in [
"0.0001 BTC/vByte",
"100 satoshi/vByte",
"100 satoshis/vByte",
"10 satoshi/vByte",
"1 satoshi/vByte",
]
Expand All @@ -205,7 +206,7 @@ mod tests {
assert!(parse.is_ok());
}
// MUST fail
for s in ["100 satoshis/vByte", "1 satoshi", "100 vByte"].iter() {
for s in ["1 satoshi", "100 vByte"].iter() {
let parse = SatPerVByte::from_str(s);
assert!(parse.is_err());
}
Expand Down
58 changes: 26 additions & 32 deletions src/bitcoin/segwitv0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@ use crate::script::{DataLock, DataPunishableLock, DoubleKeys, ScriptPath};

use bitcoin::blockdata::opcodes;
use bitcoin::blockdata::script::{Builder, Instruction, Script};
use bitcoin::blockdata::transaction::SigHashType;
use bitcoin::blockdata::transaction::EcdsaSigHashType;
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
use bitcoin::secp256k1::{
key::{PublicKey, SecretKey},
Message, Secp256k1, Signature, Signing,
};
use bitcoin::util::bip143::SigHashCache;
use bitcoin::secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1, SecretKey, Signing};
use bitcoin::util::sighash::SigHashCache;

use ecdsa_fun::adaptor::EncryptedSignature;

Expand Down Expand Up @@ -84,8 +81,8 @@ impl From<BitcoinSegwitV0> for Btc {
}

pub struct CoopLock {
a: bitcoin::util::key::PublicKey,
b: bitcoin::util::key::PublicKey,
a: PublicKey,
b: PublicKey,
}

impl CoopLock {
Expand All @@ -95,9 +92,9 @@ impl CoopLock {
..
} = data;
Builder::new()
.push_key(&bitcoin::util::ecdsa::PublicKey::new(*alice))
.push_key(&bitcoin::util::key::PublicKey::new(*alice))
.push_opcode(opcodes::all::OP_CHECKSIGVERIFY)
.push_key(&bitcoin::util::ecdsa::PublicKey::new(*bob))
.push_key(&bitcoin::util::key::PublicKey::new(*bob))
.push_opcode(opcodes::all::OP_CHECKSIG)
.into_script()
}
Expand Down Expand Up @@ -126,7 +123,7 @@ impl CoopLock {
_ => Err(Error::MissingPublicKey),
},
)?;
let a = bitcoin::util::key::PublicKey::from_slice(bytes).map_err(Error::new)?;
let a = PublicKey::from_slice(bytes).map_err(Error::new)?;
// Checksig verify
ints.next()
.ok_or(Error::WrongTemplate("Missing opcode"))
Expand All @@ -144,7 +141,7 @@ impl CoopLock {
Err(e) => Err(Error::new(e)),
_ => Err(Error::MissingPublicKey),
})?;
let b = bitcoin::util::key::PublicKey::from_slice(bytes).map_err(Error::new)?;
let b = PublicKey::from_slice(bytes).map_err(Error::new)?;
// Checksig
ints.next()
.ok_or(Error::WrongTemplate("Missing opcode"))
Expand All @@ -165,7 +162,7 @@ impl CoopLock {
Ok(Self { a, b })
}

pub fn get_pubkey(&self, swap_role: SwapRole) -> &bitcoin::util::key::PublicKey {
pub fn get_pubkey(&self, swap_role: SwapRole) -> &PublicKey {
match swap_role {
SwapRole::Alice => &self.a,
SwapRole::Bob => &self.b,
Expand All @@ -174,9 +171,9 @@ impl CoopLock {
}

pub struct PunishLock {
alice: bitcoin::util::key::PublicKey,
bob: bitcoin::util::key::PublicKey,
punish: bitcoin::util::key::PublicKey,
alice: PublicKey,
bob: PublicKey,
punish: PublicKey,
}

impl PunishLock {
Expand All @@ -188,15 +185,15 @@ impl PunishLock {
} = data;
Builder::new()
.push_opcode(opcodes::all::OP_IF)
.push_key(&bitcoin::util::ecdsa::PublicKey::new(*alice))
.push_key(&bitcoin::util::key::PublicKey::new(*alice))
.push_opcode(opcodes::all::OP_CHECKSIGVERIFY)
.push_key(&bitcoin::util::ecdsa::PublicKey::new(*bob))
.push_key(&bitcoin::util::key::PublicKey::new(*bob))
.push_opcode(opcodes::all::OP_CHECKSIG)
.push_opcode(opcodes::all::OP_ELSE)
.push_int(timelock.as_u32().into())
.push_opcode(opcodes::all::OP_CSV)
.push_opcode(opcodes::all::OP_DROP)
.push_key(&bitcoin::util::ecdsa::PublicKey::new(*failure))
.push_key(&bitcoin::util::key::PublicKey::new(*failure))
.push_opcode(opcodes::all::OP_CHECKSIG)
.push_opcode(opcodes::all::OP_ENDIF)
.into_script()
Expand Down Expand Up @@ -234,7 +231,7 @@ impl PunishLock {
_ => Err(Error::MissingPublicKey),
},
)?;
let alice = bitcoin::util::key::PublicKey::from_slice(bytes).map_err(Error::new)?;
let alice = PublicKey::from_slice(bytes).map_err(Error::new)?;
// Checksig verify
ints.next()
.ok_or(Error::WrongTemplate("Missing opcode"))
Expand All @@ -252,7 +249,7 @@ impl PunishLock {
Err(e) => Err(Error::new(e)),
_ => Err(Error::MissingPublicKey),
})?;
let bob = bitcoin::util::key::PublicKey::from_slice(bytes).map_err(Error::new)?;
let bob = PublicKey::from_slice(bytes).map_err(Error::new)?;
// Checksig
ints.next()
.ok_or(Error::WrongTemplate("Missing opcode"))
Expand Down Expand Up @@ -296,7 +293,7 @@ impl PunishLock {
Err(e) => Err(Error::new(e)),
_ => Err(Error::MissingPublicKey),
})?;
let punish = bitcoin::util::key::PublicKey::from_slice(bytes).map_err(Error::new)?;
let punish = PublicKey::from_slice(bytes).map_err(Error::new)?;
// Checksig
ints.next()
.ok_or(Error::WrongTemplate("Missing opcode"))
Expand Down Expand Up @@ -325,11 +322,7 @@ impl PunishLock {
Ok(Self { alice, bob, punish })
}

pub fn get_pubkey(
&self,
swap_role: SwapRole,
script_path: ScriptPath,
) -> Option<&bitcoin::util::key::PublicKey> {
pub fn get_pubkey(&self, swap_role: SwapRole, script_path: ScriptPath) -> Option<&PublicKey> {
match script_path {
ScriptPath::Success => match swap_role {
SwapRole::Alice => Some(&self.alice),
Expand Down Expand Up @@ -452,10 +445,11 @@ pub fn signature_hash(
txin: TxInRef,
script: &Script,
value: u64,
sighash_type: SigHashType,
sighash_type: EcdsaSigHashType,
) -> Sha256dHash {
SigHashCache::new(txin.transaction)
.signature_hash(txin.index, script, value, sighash_type)
.segwit_signature_hash(txin.index, script, value, sighash_type)
.expect("encoding works")
.as_hash()
}

Expand All @@ -467,7 +461,7 @@ pub fn sign_input<C>(
txin: TxInRef,
script: &Script,
value: u64,
sighash_type: SigHashType,
sighash_type: EcdsaSigHashType,
secret_key: &bitcoin::secp256k1::SecretKey,
) -> Result<Signature, bitcoin::secp256k1::Error>
where
Expand All @@ -477,7 +471,7 @@ where
let sighash = signature_hash(txin, script, value, sighash_type);
// Makes signature.
let msg = Message::from_slice(&sighash[..])?;
let mut sig = context.sign(&msg, secret_key);
let mut sig = context.sign_ecdsa(&msg, secret_key);
sig.normalize_s();
Ok(sig)
}
Expand All @@ -493,7 +487,7 @@ pub fn sign_hash(
let context = Secp256k1::new();
// Makes signature.
let msg = Message::from_slice(&sighash[..])?;
let mut sig = context.sign(&msg, secret_key);
let mut sig = context.sign_ecdsa(&msg, secret_key);
sig.normalize_s();
Ok(sig)
}
Expand Down
35 changes: 20 additions & 15 deletions src/bitcoin/segwitv0/buy.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::marker::PhantomData;

use bitcoin::blockdata::transaction::{SigHashType, TxIn, TxOut};
use bitcoin::secp256k1::Signature;
use bitcoin::blockdata::transaction::{TxIn, TxOut};
use bitcoin::blockdata::witness::Witness;
use bitcoin::secp256k1::ecdsa::Signature;
use bitcoin::util::ecdsa::EcdsaSig;
use bitcoin::util::psbt::PartiallySignedTransaction;
use bitcoin::Address;

Expand Down Expand Up @@ -37,7 +39,11 @@ impl SubTransaction for Buy {
.ok_or(FError::MissingSignature)?
.clone();

psbt.inputs[0].final_script_witness = Some(vec![bob_sig, alice_sig, script.into_bytes()]);
psbt.inputs[0].final_script_witness = Some(Witness::from_vec(vec![
bob_sig.to_vec(),
alice_sig.to_vec(),
script.into_bytes(),
]));

Ok(())
}
Expand All @@ -58,7 +64,7 @@ impl Buyable<Bitcoin<SegwitV0>, MetadataOutput> for Tx<Buy> {
previous_output: output_metadata.out_point,
script_sig: bitcoin::Script::default(),
sequence: 0,
witness: vec![],
witness: Witness::new(),
}],
output: vec![TxOut {
value: output_metadata.tx_out.value,
Expand All @@ -72,7 +78,6 @@ impl Buyable<Bitcoin<SegwitV0>, MetadataOutput> for Tx<Buy> {
// Set the input witness data and sighash type
psbt.inputs[0].witness_utxo = Some(output_metadata.tx_out);
psbt.inputs[0].witness_script = output_metadata.script_pubkey;
psbt.inputs[0].sighash_type = Some(SigHashType::All);

Ok(Tx {
psbt,
Expand All @@ -81,25 +86,25 @@ impl Buyable<Bitcoin<SegwitV0>, MetadataOutput> for Tx<Buy> {
}

fn verify_template(&self, destination_target: Address) -> Result<(), FError> {
(self.psbt.global.unsigned_tx.version == 2)
(self.psbt.unsigned_tx.version == 2)
.then(|| 0)
.ok_or(FError::WrongTemplate("Tx version is not 2"))?;
(self.psbt.global.unsigned_tx.lock_time == 0)
(self.psbt.unsigned_tx.lock_time == 0)
.then(|| 0)
.ok_or(FError::WrongTemplate("LockTime is not set to 0"))?;
(self.psbt.global.unsigned_tx.input.len() == 1)
(self.psbt.unsigned_tx.input.len() == 1)
.then(|| 0)
.ok_or(FError::WrongTemplate("Number of inputs is not 1"))?;
(self.psbt.global.unsigned_tx.output.len() == 1)
(self.psbt.unsigned_tx.output.len() == 1)
.then(|| 0)
.ok_or(FError::WrongTemplate("Number of outputs is not 1"))?;

let txin = &self.psbt.global.unsigned_tx.input[0];
let txin = &self.psbt.unsigned_tx.input[0];
(txin.sequence == 0)
.then(|| 0)
.ok_or(FError::WrongTemplate("Sequence is not set to 0"))?;

let txout = &self.psbt.global.unsigned_tx.output[0];
let txout = &self.psbt.unsigned_tx.output[0];
let script_pubkey = destination_target.script_pubkey();
(txout.script_pubkey == script_pubkey)
.then(|| 0)
Expand All @@ -110,9 +115,9 @@ impl Buyable<Bitcoin<SegwitV0>, MetadataOutput> for Tx<Buy> {

fn extract_witness(tx: bitcoin::Transaction) -> Signature {
let TxIn { witness, .. } = &tx.input[0];
let bytes: &[u8] = witness[0].as_ref();
// Remove SIGHASH type at the end of the signature
Signature::from_der(&bytes[..bytes.len() - 1])
.expect("Validated transaction on-chain, signature and witness position is correct.")
let witness_bytes = witness.to_vec();
let ecdsa_sig = EcdsaSig::from_slice(witness_bytes[0].as_ref())
.expect("Validated transaction on-chain, signature and witness position is correct.");
ecdsa_sig.sig
}
}
Loading

0 comments on commit 29c41e4

Please sign in to comment.