diff --git a/Cargo.lock b/Cargo.lock index c021f8596..2596cd695 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -622,13 +622,15 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.29.2" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" +checksum = "b36f4c848f6bd9ff208128f08751135846cc23ae57d66ab10a22efff1c675f3c" dependencies = [ "bech32", - "bitcoin_hashes 0.11.0", - "secp256k1 0.24.3", + "bitcoin-private", + "bitcoin_hashes 0.12.0", + "hex_lit", + "secp256k1 0.27.0", "serde", ] @@ -681,6 +683,12 @@ dependencies = [ "spin 0.7.1", ] +[[package]] +name = "bitcoin-private" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" + [[package]] name = "bitcoin_hashes" version = "0.7.6" @@ -689,18 +697,20 @@ checksum = "b375d62f341cef9cd9e77793ec8f1db3fc9ce2e4d57e982c8fe697a2c16af3b6" [[package]] name = "bitcoin_hashes" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" dependencies = [ + "bitcoin-private", "serde", ] [[package]] name = "bitcoincore-rpc" -version = "0.16.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=bde02d7fbf031df7d3a49946ec0e7f1abde34e58#bde02d7fbf031df7d3a49946ec0e7f1abde34e58" +version = "0.17.0" +source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=7bd815f1e1ae721404719ee8e6867064b7c68494#7bd815f1e1ae721404719ee8e6867064b7c68494" dependencies = [ + "bitcoin-private", "bitcoincore-rpc-json", "jsonrpc", "log", @@ -710,10 +720,11 @@ dependencies = [ [[package]] name = "bitcoincore-rpc-json" -version = "0.16.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=bde02d7fbf031df7d3a49946ec0e7f1abde34e58#bde02d7fbf031df7d3a49946ec0e7f1abde34e58" +version = "0.17.0" +source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=7bd815f1e1ae721404719ee8e6867064b7c68494#7bd815f1e1ae721404719ee8e6867064b7c68494" dependencies = [ - "bitcoin 0.29.2", + "bitcoin 0.30.0", + "bitcoin-private", "serde", "serde_json", ] @@ -4239,6 +4250,12 @@ dependencies = [ "proc-macro-hack", ] +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "hkdf" version = "0.12.3" @@ -5012,9 +5029,9 @@ dependencies = [ [[package]] name = "jsonrpc" -version = "0.13.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8d6b3f301ba426b30feca834a2a18d48d5b54e5065496b5c1b05537bee3639" +checksum = "8128f36b47411cd3f044be8c1f5cc0c9e24d1d1bfdc45f0a57897b32513053f2" dependencies = [ "base64 0.13.1", "serde", @@ -12471,9 +12488,18 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ - "bitcoin_hashes 0.11.0", - "rand 0.8.5", "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "bitcoin_hashes 0.12.0", + "rand 0.8.5", + "secp256k1-sys 0.8.1", "serde", ] @@ -12494,6 +12520,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -15136,7 +15171,7 @@ dependencies = [ "parity-scale-codec", "rocksdb", "runtime", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "serde", "serde_json", "serial_test 0.9.0", diff --git a/bitcoin/Cargo.toml b/bitcoin/Cargo.toml index dd203384a..e4a0195ea 100644 --- a/bitcoin/Cargo.toml +++ b/bitcoin/Cargo.toml @@ -13,7 +13,7 @@ light-client = [] [dependencies] thiserror = "1.0" -bitcoincore-rpc = { git = "https://github.com/rust-bitcoin/rust-bitcoincore-rpc", rev = "bde02d7fbf031df7d3a49946ec0e7f1abde34e58" } +bitcoincore-rpc = { git = "https://github.com/rust-bitcoin/rust-bitcoincore-rpc", rev = "7bd815f1e1ae721404719ee8e6867064b7c68494" } hex = "0.4.2" async-trait = "0.1.40" tokio = { version = "1.0", features = ["full"] } diff --git a/bitcoin/src/electrs/error.rs b/bitcoin/src/electrs/error.rs index e208f55b9..39bef49b8 100644 --- a/bitcoin/src/electrs/error.rs +++ b/bitcoin/src/electrs/error.rs @@ -1,6 +1,6 @@ use bitcoincore_rpc::bitcoin::{ - consensus::encode::Error as BitcoinEncodeError, hashes::hex::Error as HexError, - util::address::Error as BitcoinAddressError, + address::Error as BitcoinAddressError, consensus::encode::Error as BitcoinEncodeError, + hashes::hex::Error as HexError, }; use reqwest::{Error as ReqwestError, StatusCode}; use serde_json::Error as SerdeJsonError; diff --git a/bitcoin/src/electrs/mod.rs b/bitcoin/src/electrs/mod.rs index 8acfd707e..7973d77b8 100644 --- a/bitcoin/src/electrs/mod.rs +++ b/bitcoin/src/electrs/mod.rs @@ -1,12 +1,13 @@ mod error; mod types; +use bitcoincore_rpc::bitcoin::ScriptBuf; pub use error::Error; pub use types::*; use crate::{ deserialize, opcodes, serialize, Address, Block, BlockHash, BlockHeader, Builder as ScriptBuilder, FromHex, - Network, OutPoint, Script, SignedAmount, ToHex, Transaction, Txid, H256, + Network, OutPoint, SignedAmount, Transaction, Txid, H256, }; use futures::future::{join_all, try_join}; use reqwest::{Client, Url}; @@ -185,7 +186,7 @@ impl ElectrsClient { .collect::, Error>>() } - pub(crate) async fn get_script_pubkey(&self, outpoint: OutPoint) -> Result { + pub(crate) async fn get_script_pubkey(&self, outpoint: OutPoint) -> Result { let tx: TransactionValue = self .get_and_decode(&format!("/tx/{txid}", txid = outpoint.txid)) .await?; @@ -215,7 +216,7 @@ impl ElectrsClient { let txid = self .cli .post(url) - .body(serialize(&tx).to_hex()) + .body(hex::encode(serialize(&tx))) .send() .await? .error_for_status()? @@ -232,7 +233,7 @@ impl ElectrsClient { let mut transactions: Vec = self .get_and_decode(&format!( "/scripthash/{scripthash}/txs/chain/{last_seen_txid}", - scripthash = script_hash.to_hex() + scripthash = hex::encode(&script_hash) )) .await?; let page_size = transactions.len(); @@ -257,7 +258,7 @@ impl ElectrsClient { ) -> Result, Error> { let script = ScriptBuilder::new() .push_opcode(opcodes::OP_RETURN) - .push_slice(data.as_bytes()) + .push_slice(&data.as_fixed_bytes()) .into_script(); let script_hash = { @@ -302,11 +303,11 @@ mod tests { async fn test_electrs(url: &str, script_hex: &str, expected_txid: &str) { let script_bytes = Vec::from_hex(script_hex).unwrap(); let script_hash = Sha256Hash::hash(&script_bytes); - let expected_txid = Txid::from_hex(expected_txid).unwrap(); + let expected_txid = Txid::from_str(expected_txid).unwrap(); let electrs_client = ElectrsClient::new(Some(url.to_owned()), Network::Bitcoin).unwrap(); let txs = electrs_client - .get_txs_by_scripthash(script_hash.to_vec()) + .get_txs_by_scripthash(script_hash.to_byte_array().to_vec()) .await .unwrap(); assert!(txs.iter().any(|tx| tx.txid.eq(&expected_txid))); diff --git a/bitcoin/src/electrs/types.rs b/bitcoin/src/electrs/types.rs index aa81be13d..5320a3c61 100644 --- a/bitcoin/src/electrs/types.rs +++ b/bitcoin/src/electrs/types.rs @@ -1,4 +1,5 @@ -use crate::{BlockHash, Script, Txid}; +use crate::{BlockHash, Txid}; +use bitcoincore_rpc::bitcoin::ScriptBuf; use serde::Deserialize; // https://github.com/Blockstream/electrs/blob/adedee15f1fe460398a7045b292604df2161adc0/src/util/transaction.rs#L17-L26 @@ -19,7 +20,7 @@ pub struct TxInValue { pub txid: Txid, pub vout: u32, pub prevout: Option, - pub scriptsig: Script, + pub scriptsig: ScriptBuf, pub scriptsig_asm: String, #[serde(skip_serializing_if = "Option::is_none")] pub witness: Option>, @@ -34,7 +35,7 @@ pub struct TxInValue { // https://github.com/Blockstream/electrs/blob/adedee15f1fe460398a7045b292604df2161adc0/src/rest.rs#L239-L270 #[derive(Deserialize)] pub struct TxOutValue { - pub scriptpubkey: Script, + pub scriptpubkey: ScriptBuf, pub scriptpubkey_asm: String, pub scriptpubkey_type: String, #[serde(skip_serializing_if = "Option::is_none")] diff --git a/bitcoin/src/error.rs b/bitcoin/src/error.rs index eadde1b63..6835732f7 100644 --- a/bitcoin/src/error.rs +++ b/bitcoin/src/error.rs @@ -1,10 +1,11 @@ use crate::{BitcoinError, BitcoinLightError, ElectrsError}; use bitcoincore_rpc::{ bitcoin::{ + address::Error as AddressError, consensus::encode::Error as BitcoinEncodeError, hashes::{hex::Error as HashHexError, Error as HashesError}, + key::Error as KeyError, secp256k1::Error as Secp256k1Error, - util::{address::Error as AddressError, key::Error as KeyError}, }, jsonrpc::{error::RpcError, Error as JsonRpcError}, }; @@ -74,6 +75,8 @@ pub enum Error { MissingBitcoinFeeInfo, #[error("FailedToConstructWalletName")] FailedToConstructWalletName, + #[error("AddressError: {0}")] + AddressError(#[from] AddressError), } impl Error { diff --git a/bitcoin/src/iter.rs b/bitcoin/src/iter.rs index 0e7a5c090..6bbd137d7 100644 --- a/bitcoin/src/iter.rs +++ b/bitcoin/src/iter.rs @@ -193,8 +193,8 @@ async fn get_best_block_info(rpc: &DynBitcoinCoreApi) -> Result<(u32, BlockHash) mod tests { use super::*; use crate::*; - use bitcoincore_rpc::bitcoin::PackedLockTime; - pub use bitcoincore_rpc::bitcoin::{Address, Amount, Network, PublicKey, TxMerkleNode}; + use bitcoincore_rpc::bitcoin::{absolute::Height, block::Version, locktime::absolute::LockTime, CompactTarget}; + pub use bitcoincore_rpc::bitcoin::{Address, Amount, Network, PublicKey}; use sp_core::H256; mockall::mock! { @@ -282,7 +282,7 @@ mod tests { fn dummy_tx(value: i32) -> Transaction { Transaction { version: value, - lock_time: PackedLockTime(1), + lock_time: LockTime::Blocks(Height::ZERO), input: vec![], output: vec![], } @@ -292,8 +292,8 @@ mod tests { Block { txdata: transactions.into_iter().map(dummy_tx).collect(), header: BlockHeader { - version: 4, - bits: 0, + version: Version::from_consensus(4), + bits: CompactTarget::from_consensus(0), nonce: 0, time: 0, prev_blockhash: next_hash, diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index 698d99248..536ec32aa 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -13,26 +13,27 @@ mod iter; use async_trait::async_trait; use backoff::{backoff::Backoff, future::retry, ExponentialBackoff}; -use bitcoincore_rpc::{bitcoin::consensus::encode::serialize_hex, bitcoincore_rpc_json::ScanningDetails}; pub use bitcoincore_rpc::{ + bitcoin as bitcoin_primitives, bitcoin::{ + absolute::LockTime, + address, + address::Payload, + block::Header as BlockHeader, blockdata::{opcodes::all as opcodes, script::Builder}, consensus, consensus::encode::{deserialize, serialize}, - hash_types::BlockHash, - hashes::{ - self, - hex::{FromHex, ToHex}, - sha256, Hash, - }, - secp256k1, + ecdsa::Signature as EcdsaSig, + hash_types::{BlockHash, TxMerkleNode, WPubkeyHash}, + hashes::{self, hex::FromHex, sha256, Hash}, + key, + merkle_tree::PartialMerkleTree, + psbt, secp256k1, secp256k1::{constants::PUBLIC_KEY_SIZE, SecretKey}, - util::{ - self, address::Payload, key, merkleblock::PartialMerkleTree, psbt, psbt::serialize::Serialize, - uint::Uint256, - }, - Address, Amount, Block, BlockHeader, Network, OutPoint, PrivateKey, PubkeyHash, PublicKey, Script, ScriptHash, - SignedAmount, Transaction, TxIn, TxMerkleNode, TxOut, Txid, VarInt, WPubkeyHash, WScriptHash, + sighash::NonStandardSighashType, + util::{self}, + Address, Amount, Block, Network, OutPoint, PrivateKey, PubkeyHash, PublicKey, Script, ScriptHash, SignedAmount, + Transaction, TxIn, TxOut, Txid, VarInt, WScriptHash, }, bitcoincore_rpc_json::{ CreateRawTransactionInput, FundRawTransactionOptions, GetBlockchainInfoResult, GetTransactionResult, @@ -42,6 +43,7 @@ pub use bitcoincore_rpc::{ jsonrpc::{self, error::RpcError, Error as JsonRpcError}, Auth, Client, Error as BitcoinError, RpcApi, }; +use bitcoincore_rpc::{bitcoin::consensus::encode::serialize_hex, bitcoincore_rpc_json::ScanningDetails}; pub use electrs::{ElectrsClient, Error as ElectrsError}; pub use error::{BitcoinRpcError, ConversionError, Error}; pub use iter::{reverse_stream_transactions, stream_blocks, stream_in_chain_transactions}; @@ -228,17 +230,8 @@ impl LockedTransaction { } } -fn parse_bitcoin_network(src: &str) -> Result { - match src { - "main" => Ok(Network::Bitcoin), - "test" => Ok(Network::Testnet), - "regtest" => Ok(Network::Regtest), - _ => Err(Error::InvalidBitcoinNetwork), - } -} - struct ConnectionInfo { - chain: String, + chain: Network, version: usize, } @@ -286,7 +279,7 @@ async fn connect(rpc: &Client, connection_timeout: Duration) -> Result return Err(err), } @@ -424,7 +417,7 @@ impl BitcoinCore { if let Some(request_id) = request_id { // add the op_return data - bitcoind will add op_return and the length automatically - outputs.insert("data".to_string(), serde_json::Value::from(request_id.to_hex())); + outputs.insert("data".to_string(), serde_json::Value::from(hex::encode(request_id))); } let args = [ @@ -526,8 +519,13 @@ impl BitcoinCore { if self.auto_mine { log::debug!("Auto-mining!"); - self.rpc - .generate_to_address(1, &self.rpc.get_new_address(None, Some(AddressType::Bech32))?)?; + self.rpc.generate_to_address( + 1, + &self + .rpc + .get_new_address(None, Some(AddressType::Bech32))? + .require_network(self.network)?, + )?; } Ok(txid) @@ -535,8 +533,13 @@ impl BitcoinCore { #[cfg(feature = "regtest-manual-mining")] pub fn mine_blocks(&self, block_num: u64, maybe_address: Option
) -> BlockHash { - let address = - maybe_address.unwrap_or_else(|| self.rpc.get_new_address(None, Some(AddressType::Bech32)).unwrap()); + let address = maybe_address.unwrap_or_else(|| { + self.rpc + .get_new_address(None, Some(AddressType::Bech32)) + .unwrap() + .require_network(self.network) + .unwrap() + }); self.rpc .generate_to_address(block_num, &address) .unwrap() @@ -709,7 +712,14 @@ impl BitcoinCoreApi for BitcoinCore { let addresses = groupings .into_iter() .flatten() - .filter_map(|group| group.get(0).and_then(|v| v.as_str()).map(Address::from_str)?.ok()) + .filter_map(|group| { + group + .get(0) + .and_then(|v| v.as_str()) + .map(Address::from_str)? + .and_then(|x| x.require_network(self.network)) + .ok() + }) .collect::>(); Ok(addresses) } @@ -762,14 +772,18 @@ impl BitcoinCoreApi for BitcoinCore { /// Gets a new address from the wallet async fn get_new_address(&self) -> Result { - Ok(self.rpc.get_new_address(None, Some(AddressType::Bech32))?) + Ok(self + .rpc + .get_new_address(None, Some(AddressType::Bech32))? + .require_network(self.network)?) } /// Gets a new public key for an address in the wallet async fn get_new_public_key(&self) -> Result { let address = self .rpc - .get_new_address(Some(DERIVATION_KEY_LABEL), Some(AddressType::Bech32))?; + .get_new_address(Some(DERIVATION_KEY_LABEL), Some(AddressType::Bech32))? + .require_network(self.network)?; let address_info = self.rpc.get_address_info(&address)?; let public_key = address_info.pubkey.ok_or(Error::MissingPublicKey)?; Ok(public_key) @@ -899,10 +913,7 @@ impl BitcoinCoreApi for BitcoinCore { .extract_return_to_self_address(&address.payload)? .map(|(idx, payload)| { existing_transaction.output.remove(idx); - Address { - payload, - network: self.network(), - } + Address::new(self.network(), payload) }); let raw_tx = serialize_hex(&existing_transaction); @@ -923,8 +934,13 @@ impl BitcoinCoreApi for BitcoinCore { if self.auto_mine { log::debug!("Auto-mining!"); - self.rpc - .generate_to_address(1, &self.rpc.get_new_address(None, Some(AddressType::Bech32))?)?; + self.rpc.generate_to_address( + 1, + &self + .rpc + .get_new_address(None, Some(AddressType::Bech32))? + .require_network(self.network)?, + )?; } Ok(txid) @@ -1080,13 +1096,7 @@ impl BitcoinCoreApi for BitcoinCore { // to get from weight to vsize we divide by 4, but round up by first adding 3 // Note that we can not rely on tx.get_size() since it doesn't 'discount' witness bytes - let vsize = tx - .weight() - .checked_add(3) - .ok_or(Error::ArithmeticError)? - .checked_div(4) - .ok_or(Error::ArithmeticError)? - .try_into()?; + let vsize = tx.weight().to_vbytes_ceil(); let fee = get_tx_result .fee @@ -1097,7 +1107,7 @@ impl BitcoinCoreApi for BitcoinCore { log::debug!("fee: {fee}, size: {vsize}"); - let fee_rate = fee.checked_div(vsize).ok_or(Error::ArithmeticError)?; + let fee_rate = fee.checked_div(vsize.try_into()?).ok_or(Error::ArithmeticError)?; Ok(SatPerVbyte(fee_rate.try_into()?)) } @@ -1195,7 +1205,7 @@ mod tests { let script_hash = Sha256Hash::hash(&raw); let expected = "6ed3928fdcf7375b9622746eb46f8e97a2832a0c43000e3d86774fecb74ee67e"; - let expected = Sha256Hash::from_hex(expected).unwrap(); + let expected = Sha256Hash::from_slice(&hex::decode(expected).unwrap()).unwrap(); assert_eq!(expected, script_hash); } diff --git a/bitcoin/src/light/error.rs b/bitcoin/src/light/error.rs index 7340b8cbd..6bcdc9792 100644 --- a/bitcoin/src/light/error.rs +++ b/bitcoin/src/light/error.rs @@ -1,7 +1,7 @@ use crate::{ - psbt::Error as PsbtError, secp256k1::Error as Secp256k1Error, util::address::Error as AddressError, ElectrsError, + address::Error as AddressError, psbt::Error as PsbtError, secp256k1::Error as Secp256k1Error, ElectrsError, }; -use bitcoincore_rpc::bitcoin::util::sighash::Error as SighashError; +use bitcoincore_rpc::bitcoin::sighash::Error as SighashError; use std::sync::PoisonError; use thiserror::Error; diff --git a/bitcoin/src/light/mod.rs b/bitcoin/src/light/mod.rs index 69f5abe68..9b94ef711 100644 --- a/bitcoin/src/light/mod.rs +++ b/bitcoin/src/light/mod.rs @@ -2,7 +2,7 @@ mod error; mod wallet; pub use crate::{Error as BitcoinError, *}; -use bitcoincore_rpc::bitcoin::{blockdata::constants::WITNESS_SCALE_FACTOR, secp256k1::Scalar}; +use bitcoincore_rpc::bitcoin::secp256k1::Scalar; pub use error::Error; use async_trait::async_trait; @@ -257,10 +257,7 @@ impl BitcoinCoreApi for BitcoinLight { .extract_return_to_self_address(&address.payload)? .map(|(idx, payload)| { existing_transaction.output.remove(idx); - Address { - payload, - network: self.network(), - } + Address::new(self.network(), payload) }); // clear the witnesses for fee estimation @@ -335,7 +332,7 @@ impl BitcoinCoreApi for BitcoinLight { async fn fee_rate(&self, txid: Txid) -> Result { let tx = self.get_transaction(&txid, None).await?; - let vsize = tx.weight().div_ceil(WITNESS_SCALE_FACTOR) as u64; + let vsize = tx.weight().to_vbytes_ceil(); let recipients_sum = tx.output.iter().map(|tx_out| tx_out.value).sum::(); let inputs = try_join_all(tx.input.iter().map(|input| async move { diff --git a/bitcoin/src/light/wallet.rs b/bitcoin/src/light/wallet.rs index d02a5ef0f..d86cb9970 100644 --- a/bitcoin/src/light/wallet.rs +++ b/bitcoin/src/light/wallet.rs @@ -2,17 +2,15 @@ use super::{electrs::ElectrsClient, error::Error}; use crate::{ electrs::Utxo, hashes::Hash, - json::bitcoin::EcdsaSighashType, + json::bitcoin::sighash::EcdsaSighashType, opcodes, psbt, psbt::PartiallySignedTransaction, secp256k1::{All, Message, Secp256k1, SecretKey}, - Address, Builder as ScriptBuilder, Network, OutPoint, PrivateKey, Script, Transaction, TxIn, TxOut, Txid, VarInt, - H256, + Address, Builder as ScriptBuilder, EcdsaSig, LockTime, Network, NonStandardSighashType, OutPoint, PrivateKey, + Script, Transaction, TxIn, TxOut, Txid, VarInt, H256, }; use bitcoincore_rpc::bitcoin::{ - blockdata::{constants::WITNESS_SCALE_FACTOR, transaction::NonStandardSighashType}, - util::sighash::SighashCache, - EcdsaSig, PackedLockTime, PublicKey, Sequence, Witness, + blockdata::constants::WITNESS_SCALE_FACTOR, sighash::SighashCache, PublicKey, Sequence, Witness, }; use futures::{stream, Stream, StreamExt}; use std::{ @@ -79,7 +77,7 @@ fn dummy_sign_input(txin: &mut TxIn, public_key: PublicKey) { }; // update input (only works with segwit for now) - txin.witness = Witness::from_vec(vec![dummy_signature.to_vec(), public_key.to_bytes()]); + txin.witness = Witness::from_slice(&[dummy_signature.to_vec(), public_key.to_bytes()]); } // https://github.com/bitcoin/bitcoin/blob/e9035f867a36a430998e3811385958229ac79cf5/src/consensus/validation.h#L156 @@ -118,7 +116,7 @@ fn calculate_maximum_signed_tx_size(psbt: &PartiallySignedTransaction, wallet: & } // GetVirtualTransactionSize = GetVirtualTransactionSize(GetTransactionWeight(tx)) - get_virtual_transaction_size(tx.weight() as u64) + tx.weight().to_vbytes_ceil() } struct FeeRate { @@ -191,17 +189,6 @@ impl SelectCoins { } } -// https://github.com/bitcoindevkit/bdk/blob/061f15af004ce16ea107cfcbe86e0120be22eaa8/src/wallet/signer.rs#L818 -fn p2wpkh_script_code(script: &Script) -> Script { - ScriptBuilder::new() - .push_opcode(opcodes::OP_DUP) - .push_opcode(opcodes::OP_HASH160) - .push_slice(&script[2..]) - .push_opcode(opcodes::OP_EQUALVERIFY) - .push_opcode(opcodes::OP_CHECKSIG) - .into_script() -} - // https://github.com/bitcoin/bitcoin/blob/e9262ea32a6e1d364fb7974844fadc36f931f8c6/src/policy/policy.cpp#L26 fn get_dust_threshold(tx_out: &TxOut, dust_relay_fee_in: &FeeRate) -> u64 { let mut n_size = tx_out.get_serialize_size(); @@ -435,14 +422,14 @@ impl Wallet { value: 0, script_pubkey: ScriptBuilder::new() .push_opcode(opcodes::OP_RETURN) - .push_slice(op_return.as_bytes()) + .push_slice(op_return.as_fixed_bytes()) .into_script(), }) } Transaction { version: 2, - lock_time: PackedLockTime::ZERO, + lock_time: LockTime::ZERO, input: Default::default(), output, } @@ -464,11 +451,10 @@ impl Wallet { // NOTE: we don't support signing p2sh, p2pkh, p2wsh inputs // since the Vault is assumed to only receive p2wpkh payments - let script_code = if prev_out.script_pubkey.is_v0_p2wpkh() { - Ok(p2wpkh_script_code(&prev_out.script_pubkey)) - } else { - Err(Error::InvalidPrevOut) - }?; + let script_code = prev_out + .script_pubkey + .p2wpkh_script_code() + .ok_or(Error::InvalidPrevOut)?; let mut sig_hasher = SighashCache::new(&psbt.unsigned_tx); let sig_hash = sig_hasher.segwit_signature_hash(index, &script_code, prev_out.value, sighash_ty)?; @@ -476,7 +462,7 @@ impl Wallet { let private_key = self.get_priv_key(&prev_out.script_pubkey)?; let sig = self .secp - .sign_ecdsa(&Message::from_slice(&sig_hash.into_inner()[..])?, &private_key.inner); + .sign_ecdsa(&Message::from_slice(&sig_hash.to_byte_array()[..])?, &private_key.inner); let final_signature = EcdsaSig { sig, @@ -484,7 +470,7 @@ impl Wallet { }; // https://github.com/bitcoin/bitcoin/blob/607d5a46aa0f5053d8643a3e2c31a69bfdeb6e9f/src/script/sign.cpp#L125 - psbt_input.final_script_witness = Some(Witness::from_vec(vec![ + psbt_input.final_script_witness = Some(Witness::from_slice(&[ final_signature.to_vec(), private_key.public_key(&self.secp).to_bytes(), ])); @@ -498,11 +484,7 @@ impl Wallet { mod tests { use super::*; use crate::{deserialize, serialize}; - use bitcoincore_rpc::bitcoin::{ - consensus::Encodable, - hashes::hex::{FromHex, ToHex}, - Sequence, Txid, - }; + use bitcoincore_rpc::bitcoin::{consensus::Encodable, hashes::hex::FromHex, ScriptBuf, Sequence, Txid}; use std::str::FromStr; #[test] @@ -551,7 +533,7 @@ mod tests { assert_serialize_size(&tx.output[1]); // OP_RETURN assert_serialize_size(&tx.output[2]); // change - assert_eq!(get_virtual_transaction_size(tx.weight() as u64), 184); + assert_eq!(get_virtual_transaction_size(tx.weight().to_wu()), 184); Ok(()) } @@ -572,7 +554,7 @@ mod tests { ) .unwrap(); let tx: Transaction = deserialize(&signed_tx_bytes)?; - assert_eq!(get_virtual_transaction_size(tx.weight() as u64), 252); + assert_eq!(get_virtual_transaction_size(tx.weight().to_wu()), 252); Ok(()) } @@ -580,16 +562,16 @@ mod tests { async fn test_calculate_fees() -> Result<(), Box> { let tx = Transaction { version: 2, - lock_time: PackedLockTime::ZERO, + lock_time: LockTime::ZERO, input: vec![TxIn { // value: 100000 previous_output: OutPoint { txid: Txid::from_str("0243dee566c0bf1b887416caa0e625b447c793786f1e6a5fc9c24f0d583f4c07")?, vout: 0, }, - script_sig: Script::new(), + script_sig: ScriptBuf::new(), sequence: Sequence(4294967293), - witness: Witness::from_vec(vec![ + witness: Witness::from_slice(&[ hex::decode("3044022025f214b6b3f1a0b9e1110367e260ca2ff8c614272b284839be77e06607d5f8f9022056404808a029bc0fee409ca4de812e0289b092d32299340fdaa13232f367d0f801")?, hex::decode("0251bc49a18fc5af7662d04faa1929d44b7155ec723cc7f590efbf4e0fe18b14c6")?, ]), @@ -597,27 +579,30 @@ mod tests { output: vec![ TxOut { value: 0, - script_pubkey: Script::from_str("6a20f66966cde9d87d08cc58e6378cde0a57b21dd21a9688f2723aad4b184c56005b")? + script_pubkey: ScriptBuf::from_hex("6a20f66966cde9d87d08cc58e6378cde0a57b21dd21a9688f2723aad4b184c56005b")? }, TxOut { value: 700, - script_pubkey: Script::from_str("0014810b092d165f424556b1c33fd343871a0cf4d36b")? + script_pubkey: ScriptBuf::from_hex("0014810b092d165f424556b1c33fd343871a0cf4d36b")? }, TxOut { value: 99116, - script_pubkey: Script::from_str("00146b980ce352f5389938fae6ecd905d4c8af25b8d6")? + script_pubkey: ScriptBuf::from_hex("00146b980ce352f5389938fae6ecd905d4c8af25b8d6")? } ], }; assert_eq!(tx.size(), 265); - assert_eq!(tx.weight(), 733); + assert_eq!(tx.weight().to_wu(), 733); // vsize [vB] = weight [wu] / 4 - assert_eq!(tx.weight().div_ceil(WITNESS_SCALE_FACTOR), 184); - assert_eq!(get_virtual_transaction_size(tx.weight() as u64), 184); + assert_eq!(tx.weight().to_wu().div_ceil(WITNESS_SCALE_FACTOR as u64), 184); + assert_eq!(get_virtual_transaction_size(tx.weight().to_wu()), 184); let fee_rate = FeeRate { n_satoshis_per_k: 1000 }; - assert_eq!(fee_rate.get_fee(tx.weight().div_ceil(WITNESS_SCALE_FACTOR) as u64), 184); + assert_eq!( + fee_rate.get_fee(tx.weight().to_wu().div_ceil(WITNESS_SCALE_FACTOR as u64)), + 184 + ); let actual_fee = 100000 - tx.output.iter().map(|tx_out| tx_out.value).sum::(); assert_eq!(actual_fee, 184); @@ -633,13 +618,13 @@ mod tests { let outputs_no_change = vec![ TxOut { value: 0, - script_pubkey: Script::from_str( + script_pubkey: ScriptBuf::from_hex( "6a20f66966cde9d87d08cc58e6378cde0a57b21dd21a9688f2723aad4b184c56005b", )?, }, TxOut { value: 99116, - script_pubkey: Script::from_str("00146b980ce352f5389938fae6ecd905d4c8af25b8d6")?, + script_pubkey: ScriptBuf::from_hex("00146b980ce352f5389938fae6ecd905d4c8af25b8d6")?, }, ]; @@ -651,7 +636,7 @@ mod tests { .sum::(); let change_output_size = TxOut { value: 0, - script_pubkey: Script::from_str("0014810b092d165f424556b1c33fd343871a0cf4d36b")?, + script_pubkey: ScriptBuf::from_hex("0014810b092d165f424556b1c33fd343871a0cf4d36b")?, } .get_serialize_size(); @@ -671,7 +656,7 @@ mod tests { let secp = Secp256k1::new(); let key_store: BTreeMap<_, _> = map_btree! { - Address::from_str("bcrt1qxu0en0v9dsywqchvpr6g9aa5vh9wyeupys2ka8").unwrap() => + Address::from_str("bcrt1qxu0en0v9dsywqchvpr6g9aa5vh9wyeupys2ka8").unwrap().require_network(Network::Regtest).unwrap() => PrivateKey::from_wif("cNbq2Es45c5E8hYt6MT2Phk84A4tN3KSWxPzi8JpH61eW6Ttpusf").unwrap() }; let wallet = Wallet { @@ -685,7 +670,7 @@ mod tests { let mut psbt = PartiallySignedTransaction { unsigned_tx: Transaction { version: 2, - lock_time: PackedLockTime::ZERO, + lock_time: LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { txid: Txid::from_str("dcd25c1eb82783b323a7e6582a6a46edd9ff9ef7954e16a5ba5352f39c607189")?, @@ -699,19 +684,21 @@ mod tests { TxOut { value: 100000, // bcrt1qnx8uakvjhyxyns3ft3tjfm0smt68frw2c9adgx - script_pubkey: Script::from_str("0014998fced992b90c49c2295c5724edf0daf4748dca")?, + script_pubkey: ScriptBuf::from_hex("0014998fced992b90c49c2295c5724edf0daf4748dca")?, }, TxOut { value: 4999897180, // bcrt1qwz2x0729sswxhd3cl8ss0h3fx03pfuw9anc7ww - script_pubkey: Script::from_str("0014709467f945841c6bb638f9e107de2933e214f1c5")?, + script_pubkey: ScriptBuf::from_hex("0014709467f945841c6bb638f9e107de2933e214f1c5")?, }, ], }, inputs: vec![psbt::Input { witness_utxo: Some(TxOut { value: 5000000000, - script_pubkey: Address::from_str("bcrt1qxu0en0v9dsywqchvpr6g9aa5vh9wyeupys2ka8")?.script_pubkey(), + script_pubkey: Address::from_str("bcrt1qxu0en0v9dsywqchvpr6g9aa5vh9wyeupys2ka8")? + .require_network(Network::Regtest)? + .script_pubkey(), }), ..Default::default() }], @@ -723,11 +710,11 @@ mod tests { }; wallet.sign_transaction(&mut psbt)?; - let signed_tx = psbt.extract_tx(); + let witness = psbt.extract_tx().input[0].witness.clone(); assert_eq!( "3044022057aeb22db1f8656513b7f44df3a30d8405ba040cb250d731379307f1799f9cad02201582f355d461fd0c8ced789eb02053995663c66fc63a80341da9354ce3b23e5801", - signed_tx.input[0].witness.to_vec()[0].to_hex() + hex::encode(&witness.to_vec()[0]) ); Ok(()) diff --git a/bitcoin/tests/electrs.rs b/bitcoin/tests/electrs.rs index b7f31463b..3f27f98a8 100644 --- a/bitcoin/tests/electrs.rs +++ b/bitcoin/tests/electrs.rs @@ -64,8 +64,13 @@ where fn mine_blocks(block_num: u64, maybe_address: Option
) -> BlockHash { let bitcoin_client = new_bitcoin_client(); - let address = - maybe_address.unwrap_or_else(|| bitcoin_client.get_new_address(None, Some(AddressType::Bech32)).unwrap()); + let address = maybe_address.unwrap_or_else(|| { + bitcoin_client + .get_new_address(None, Some(AddressType::Bech32)) + .unwrap() + .require_network(Network::Regtest) + .unwrap() + }); bitcoin_client .generate_to_address(block_num, &address) .unwrap() diff --git a/runtime/src/addr.rs b/runtime/src/addr.rs index 7de4e1dd1..cd56b1cc0 100644 --- a/runtime/src/addr.rs +++ b/runtime/src/addr.rs @@ -1,6 +1,7 @@ use crate::{BtcAddress, H160}; use bitcoin::{ - Address, ConversionError, Hash, Network, Payload, PubkeyHash, Script, ScriptHash, WPubkeyHash, WScriptHash, + json::bitcoin::ScriptBuf, Address, ConversionError, Hash, Network, Payload, PubkeyHash, ScriptHash, WPubkeyHash, + WScriptHash, }; pub trait PartialAddress: Sized + Eq + PartialOrd { @@ -29,24 +30,31 @@ pub trait PartialAddress: Sized + Eq + PartialOrd { impl PartialAddress for BtcAddress { fn from_payload(payload: Payload) -> Result { match payload { - Payload::PubkeyHash(hash) => Ok(Self::P2PKH(H160::from(hash.as_hash().into_inner()))), - Payload::ScriptHash(hash) => Ok(Self::P2SH(H160::from(hash.as_hash().into_inner()))), - Payload::WitnessProgram { version: _, program } => { + Payload::PubkeyHash(hash) => Ok(Self::P2PKH(H160::from(hash.to_byte_array()))), + Payload::ScriptHash(hash) => Ok(Self::P2SH(H160::from(hash.to_byte_array()))), + Payload::WitnessProgram(witness_program) => { + let program = witness_program.program(); + if program.len() == 20 { - Ok(Self::P2WPKHv0(H160::from_slice(program.as_slice()))) + Ok(Self::P2WPKHv0(H160::from_slice(program.as_bytes()))) } else { Err(ConversionError::InvalidPayload) } } + _ => { + // catch-all required due to non_exhaustive annotation - at the time of writing + // all cases are actually caught + Err(ConversionError::InvalidFormat) + } } } fn to_payload(&self) -> Result { let script = match self { - Self::P2PKH(hash) => Script::new_p2pkh(&PubkeyHash::from_slice(hash.as_bytes())?), - Self::P2SH(hash) => Script::new_p2sh(&ScriptHash::from_slice(hash.as_bytes())?), - Self::P2WPKHv0(hash) => Script::new_v0_p2wpkh(&WPubkeyHash::from_slice(hash.as_bytes())?), - Self::P2WSHv0(hash) => Script::new_v0_p2wsh(&WScriptHash::from_slice(hash.as_bytes())?), + Self::P2PKH(hash) => ScriptBuf::new_p2pkh(&PubkeyHash::from_slice(hash.as_bytes())?), + Self::P2SH(hash) => ScriptBuf::new_p2sh(&ScriptHash::from_slice(hash.as_bytes())?), + Self::P2WPKHv0(hash) => ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::from_slice(hash.as_bytes())?), + Self::P2WSHv0(hash) => ScriptBuf::new_v0_p2wsh(&WScriptHash::from_slice(hash.as_bytes())?), }; Ok(Payload::from_script(&script)?) @@ -58,7 +66,7 @@ impl PartialAddress for BtcAddress { fn to_address(&self, network: Network) -> Result { let payload = self.to_payload()?; - Ok(Address { payload, network }) + Ok(Address::new(network, payload)) } } @@ -76,10 +84,7 @@ impl PartialAddress for Payload { } fn to_address(&self, network: Network) -> Result { - Ok(Address { - network, - payload: self.clone(), - }) + Ok(Address::new(network, self.clone())) } } @@ -93,11 +98,16 @@ mod tests { let addr = "bcrt1q6v2c7q7uv8vu6xle2k9ryfj3y3fuuy4rqnl50f"; assert_eq!( addr, - Payload::from_address(Address::from_str(addr).unwrap()) - .unwrap() - .to_address(Network::Regtest) - .unwrap() - .to_string() + Payload::from_address( + Address::from_str(addr) + .unwrap() + .require_network(Network::Regtest) + .unwrap() + ) + .unwrap() + .to_address(Network::Regtest) + .unwrap() + .to_string() ); } } diff --git a/runtime/src/integration/bitcoin_simulator.rs b/runtime/src/integration/bitcoin_simulator.rs index 3363b0eab..50d7d2b1e 100644 --- a/runtime/src/integration/bitcoin_simulator.rs +++ b/runtime/src/integration/bitcoin_simulator.rs @@ -6,14 +6,15 @@ use crate::{BtcAddress, BtcRelayPallet, InterBtcParachain, PartialAddress, RawBlockHeader, H160, H256, U256}; use async_trait::async_trait; use bitcoin::{ + bitcoin_primitives::{absolute::Height, block::Version, ScriptBuf, Target}, json::{ self, - bitcoin::{PackedLockTime, Sequence, Witness}, + bitcoin::{locktime::absolute::LockTime, Sequence, Witness}, }, secp256k1::{self, constants::SECRET_KEY_SIZE, Secp256k1, SecretKey}, serialize, Address, Amount, BitcoinCoreApi, Block, BlockHash, BlockHeader, Error as BitcoinError, GetBlockResult, Hash, Network, OutPoint, PartialMerkleTree, PrivateKey, PublicKey, SatPerVbyte, Script, Transaction, - TransactionExt, TransactionMetadata, TxIn, TxMerkleNode, TxOut, Txid, Uint256, PUBLIC_KEY_SIZE, + TransactionExt, TransactionMetadata, TxIn, TxMerkleNode, TxOut, Txid, PUBLIC_KEY_SIZE, }; use rand::{thread_rng, Rng}; use std::{convert::TryInto, sync::Arc, time::Duration}; @@ -21,7 +22,6 @@ use tokio::{ sync::{Mutex, OwnedMutexGuard, RwLock}, time::sleep, }; - /// A simulated bitcoin-core interface. It combines the roles of bitcoin-core and the /// staked relayer: it automatically relays the generated transactions to the parachain. /// It does the minimum amount of work it can get away with, and the relayed data may @@ -103,7 +103,7 @@ impl MockBitcoinCore { let target = U256::from(2).pow(254.into()); let mut bytes = [0u8; 32]; target.to_big_endian(&mut bytes); - let target = Uint256::from_be_bytes(bytes); + let target = Target::from_be_bytes(bytes); let mut blocks = self.blocks.write().await; let prev_blockhash = if blocks.is_empty() { @@ -122,9 +122,9 @@ impl MockBitcoinCore { transaction.clone(), ], header: BlockHeader { - version: 4, + version: Version::from_consensus(4), merkle_root: TxMerkleNode::all_zeros(), - bits: BlockHeader::compact_target_from_u256(&target), + bits: target.to_compact_lossy(), nonce: 0, prev_blockhash, time: 1, @@ -133,7 +133,7 @@ impl MockBitcoinCore { block.header.merkle_root = block.compute_merkle_root().unwrap(); loop { - if block.header.validate_pow(&target).is_ok() { + if block.header.validate_pow(target).is_ok() { break; } block.header.nonce += 1; @@ -145,10 +145,10 @@ impl MockBitcoinCore { } fn generate_normal_transaction(address: &Address, reward: u64) -> Transaction { - let address = Script::from(address.payload.script_pubkey().as_bytes().to_vec()); + let address = ScriptBuf::from(address.payload.script_pubkey().as_bytes().to_vec()); let return_to_self_address = BtcAddress::P2PKH(H160::from_slice(&[20; 20])); - let return_to_self_address = Script::from(return_to_self_address.to_script_pub_key().as_bytes().to_vec()); + let return_to_self_address = ScriptBuf::from(return_to_self_address.to_script_pub_key().as_bytes().to_vec()); Transaction { input: vec![TxIn { @@ -159,10 +159,10 @@ impl MockBitcoinCore { txid: Txid::from_slice(&[1; 32]).unwrap(), vout: 0, }, - witness: Witness::from_vec(vec![]), + witness: Witness::from_slice::<&[u8]>(&[]), // actual contents of don't script_sig don't really matter as long as it contains // a parsable script - script_sig: Script::from(vec![ + script_sig: ScriptBuf::from(vec![ 0, 71, 48, 68, 2, 32, 91, 128, 41, 150, 96, 53, 187, 63, 230, 129, 53, 234, 210, 186, 21, 187, 98, 38, 255, 112, 30, 27, 228, 29, 132, 140, 155, 62, 123, 216, 232, 168, 2, 32, 72, 126, 179, 207, 142, 8, 99, 8, 32, 78, 244, 166, 106, 160, 207, 227, 61, 210, 172, 234, 234, 93, 59, 159, 79, 12, @@ -184,20 +184,20 @@ impl MockBitcoinCore { value: 42, }, ], - lock_time: PackedLockTime::ZERO, + lock_time: LockTime::ZERO, version: 2, } } fn generate_coinbase_transaction(address: &BtcAddress, reward: u64, height: u32) -> Transaction { - let address = Script::from(address.to_script_pub_key().as_bytes().to_vec()); + let address = ScriptBuf::from(address.to_script_pub_key().as_bytes().to_vec()); // note that we set lock_time to height, otherwise we might generate blocks with // identical block hashes Transaction { input: vec![TxIn { previous_output: OutPoint::null(), // coinbase - witness: Witness::from_vec(vec![]), + witness: Witness::from_slice::<&[u8]>(&[]), script_sig: Default::default(), sequence: Sequence(u32::max_value()), }], @@ -205,7 +205,7 @@ impl MockBitcoinCore { script_pubkey: address, value: reward, }], - lock_time: PackedLockTime(height), + lock_time: LockTime::Blocks(Height::from_consensus(height).unwrap()), version: 2, } } @@ -237,7 +237,7 @@ impl MockBitcoinCore { op_return_script.append(&mut vec![0; 32]); let op_return = TxOut { value: 0, - script_pubkey: Script::from(op_return_script), + script_pubkey: ScriptBuf::from(op_return_script), }; transaction.output.insert(0, op_return.clone()); } @@ -248,7 +248,7 @@ impl MockBitcoinCore { op_return_script.append(&mut request_id.to_fixed_bytes().to_vec()); let op_return = TxOut { value: 0, - script_pubkey: Script::from(op_return_script), + script_pubkey: ScriptBuf::from(op_return_script), }; transaction.output.push(op_return); } @@ -296,7 +296,7 @@ impl MockBitcoinCore { op_return_script.append(&mut request_id.to_fixed_bytes().to_vec()); let op_return = TxOut { value: 0, - script_pubkey: Script::from(op_return_script), + script_pubkey: ScriptBuf::from(op_return_script), }; transaction.output.push(op_return); } diff --git a/runtime/src/integration/mod.rs b/runtime/src/integration/mod.rs index e012d5310..a6be1e446 100644 --- a/runtime/src/integration/mod.rs +++ b/runtime/src/integration/mod.rs @@ -4,9 +4,9 @@ mod bitcoin_simulator; use crate::{ rpc::{IssuePallet, OraclePallet, SudoPallet, VaultRegistryPallet}, - CurrencyId, FixedU128, H256Le, InterBtcParachain, InterBtcSigner, OracleKey, PartialAddress, VaultId, + CurrencyId, FixedU128, InterBtcParachain, InterBtcSigner, OracleKey, PartialAddress, VaultId, }; -use bitcoin::{BitcoinCoreApi, BlockHash, SatPerVbyte, Txid}; +use bitcoin::{BitcoinCoreApi, SatPerVbyte}; use frame_support::assert_ok; use futures::{ future::{try_join, Either}, @@ -29,26 +29,6 @@ pub use subxt_client::SubxtClient; // export the mocked bitcoin interface pub use bitcoin_simulator::MockBitcoinCore; -/// Trait to help between different types used by the two bitcoin libraries -pub trait Translate { - type Associated; - fn translate(&self) -> Self::Associated; -} - -impl Translate for Txid { - type Associated = H256Le; - fn translate(&self) -> Self::Associated { - H256Le::from_bytes_le(self) - } -} - -impl Translate for BlockHash { - type Associated = H256Le; - fn translate(&self) -> Self::Associated { - H256Le::from_bytes_le(self) - } -} - /// Start a new instance of the parachain. The second item in the returned tuple must remain in /// scope as long as the parachain is active, since dropping it will remove the temporary directory /// that the parachain uses diff --git a/runtime/src/tests.rs b/runtime/src/tests.rs index 42d075013..a2980c53b 100644 --- a/runtime/src/tests.rs +++ b/runtime/src/tests.rs @@ -8,8 +8,7 @@ use super::{ VaultRegistryPallet, KBTC, KINT, KSM, }; use crate::{ - integration::*, utils_accountid::AccountId32, AccountId, FeedValuesEvent, OracleKey, RuntimeCurrencyInfo, VaultId, - H160, U256, + integration::*, utils_accountid::AccountId32, FeedValuesEvent, OracleKey, RuntimeCurrencyInfo, VaultId, H160, U256, }; use module_bitcoin::{formatter::TryFormat, types::BlockBuilder}; pub use primitives::CurrencyId::ForeignAsset; diff --git a/vault/Cargo.toml b/vault/Cargo.toml index c50f765d6..9f6b9f9b0 100644 --- a/vault/Cargo.toml +++ b/vault/Cargo.toml @@ -28,7 +28,7 @@ signal-hook = "0.3.14" signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] } serde_json = "1.0.71" # note: secp256k1 needs to be the same as the dependency in bitcoincore-rpc -secp256k1 = { version = "0.24.0", features = ["rand", "rand-std"] } +secp256k1 = { version = "0.27.0", features = ["rand", "rand-std"] } lazy_static = "1.4" governor = "0.5.0" nonzero_ext = "0.3.0" diff --git a/vault/src/cancellation.rs b/vault/src/cancellation.rs index fcb7d8628..ab0deafb9 100644 --- a/vault/src/cancellation.rs +++ b/vault/src/cancellation.rs @@ -322,7 +322,6 @@ mod tests { InterBtcIssueRequest, InterBtcReplaceRequest, IssueRequestStatus, RequestIssueEvent, StatusCode, Token, VaultId, DOT, IBTC, INTR, }; - use std::collections::BTreeSet; macro_rules! assert_err { ($result:expr, $err:pat) => {{ diff --git a/vault/src/execution.rs b/vault/src/execution.rs index a9a42ddd5..ac2dccc48 100644 --- a/vault/src/execution.rs +++ b/vault/src/execution.rs @@ -1,6 +1,6 @@ use crate::{error::Error, metrics::update_bitcoin_metrics, system::VaultData, VaultIdManager, YIELD_RATE}; use bitcoin::{ - Error as BitcoinError, SatPerVbyte, Transaction, TransactionExt, TransactionMetadata, Txid, + Error as BitcoinError, Hash, SatPerVbyte, Transaction, TransactionExt, TransactionMetadata, Txid, BLOCK_INTERVAL as BITCOIN_BLOCK_INTERVAL, }; use futures::{future::Either, stream::StreamExt, try_join, TryStreamExt}; @@ -357,7 +357,10 @@ impl Request { tracing::info!("Awaiting parachain confirmations..."); match parachain_rpc - .wait_for_block_in_relay(H256Le::from_bytes_le(&tx_metadata.block_hash), Some(num_confirmations)) + .wait_for_block_in_relay( + H256Le::from_bytes_le(tx_metadata.block_hash.as_byte_array()), + Some(num_confirmations), + ) .await { Ok(_) => { diff --git a/vault/src/issue.rs b/vault/src/issue.rs index 5c2720677..a621df503 100644 --- a/vault/src/issue.rs +++ b/vault/src/issue.rs @@ -2,7 +2,7 @@ use crate::{ delay::RandomDelay, metrics::publish_expected_bitcoin_balance, system::DatabaseConfig, Error, Event, IssueRequests, VaultIdManager, }; -use bitcoin::{BlockHash, Error as BitcoinError, PublicKey, Transaction, TransactionExt}; +use bitcoin::{BlockHash, Error as BitcoinError, Hash, PublicKey, Transaction, TransactionExt}; use futures::{channel::mpsc::Sender, future, SinkExt, StreamExt, TryFutureExt}; use runtime::{ AccountId, BtcAddress, BtcPublicKey, BtcRelayPallet, CancelIssueEvent, ExecuteIssueEvent, H256Le, @@ -281,7 +281,10 @@ async fn process_transaction_and_execute_issue( // at this point we know that the transaction has `num_confirmations` on the bitcoin chain, // but the relay can introduce a delay, so wait until the relay also confirms the transaction. btc_parachain - .wait_for_block_in_relay(H256Le::from_bytes_le(&block_hash), Some(num_confirmations)) + .wait_for_block_in_relay( + H256Le::from_bytes_le(block_hash.as_byte_array()), + Some(num_confirmations), + ) .await?; // wait a random amount of blocks, to avoid all vaults flooding the parachain with diff --git a/vault/src/metrics.rs b/vault/src/metrics.rs index dcb0b095d..a62186473 100644 --- a/vault/src/metrics.rs +++ b/vault/src/metrics.rs @@ -673,7 +673,6 @@ mod tests { InterBtcVault, LendingAssets, RequestIssueEvent, StatusCode, Token, VaultId, VaultStatus, DOT, H256, IBTC, INTR, }; - use std::collections::BTreeSet; mockall::mock! { Provider {} diff --git a/vault/src/relay/issuing.rs b/vault/src/relay/issuing.rs index 8332217c7..7f1a5f85d 100644 --- a/vault/src/relay/issuing.rs +++ b/vault/src/relay/issuing.rs @@ -80,7 +80,7 @@ impl Issuing for InterBtcParachain { // wait a random amount of blocks, to avoid all vaults flooding the parachain with // this transaction (*random_delay) - .delay(&sha256::Hash::hash(header.as_slice()).into_inner()) + .delay(sha256::Hash::hash(header.as_slice()).as_byte_array()) .await?; if self .is_block_stored(raw_block_header.hash().to_bytes_le().to_vec()) diff --git a/vault/src/replace.rs b/vault/src/replace.rs index 07f6ebb8f..b45897b52 100644 --- a/vault/src/replace.rs +++ b/vault/src/replace.rs @@ -362,9 +362,12 @@ mod tests { #[tokio::test] async fn test_handle_replace_request_with_insufficient_balance() { let mut mock_bitcoin = MockBitcoin::default(); - mock_bitcoin - .expect_get_new_address() - .returning(|| Ok(Address::from_str("bcrt1q6v2c7q7uv8vu6xle2k9ryfj3y3fuuy4rqnl50f").unwrap())); + mock_bitcoin.expect_get_new_address().returning(|| { + Ok(Address::from_str("bcrt1q6v2c7q7uv8vu6xle2k9ryfj3y3fuuy4rqnl50f") + .unwrap() + .require_network(Network::Regtest) + .unwrap()) + }); let btc_rpc: DynBitcoinCoreApi = Arc::new(mock_bitcoin); let mut parachain_rpc = MockProvider::default(); @@ -390,9 +393,12 @@ mod tests { #[tokio::test] async fn test_handle_replace_request_with_sufficient_balance() { let mut mock_bitcoin = MockBitcoin::default(); - mock_bitcoin - .expect_get_new_address() - .returning(|| Ok(Address::from_str("bcrt1q6v2c7q7uv8vu6xle2k9ryfj3y3fuuy4rqnl50f").unwrap())); + mock_bitcoin.expect_get_new_address().returning(|| { + Ok(Address::from_str("bcrt1q6v2c7q7uv8vu6xle2k9ryfj3y3fuuy4rqnl50f") + .unwrap() + .require_network(Network::Regtest) + .unwrap()) + }); let btc_rpc: DynBitcoinCoreApi = Arc::new(mock_bitcoin); let mut parachain_rpc = MockProvider::default(); diff --git a/vault/src/system.rs b/vault/src/system.rs index 430ede0fb..4aa883d37 100644 --- a/vault/src/system.rs +++ b/vault/src/system.rs @@ -557,6 +557,12 @@ impl VaultService { Network::Testnet => "testnet", Network::Regtest => "regtest", Network::Signet => "signet", + _ => { + // enum marked as non-exhaustive + return Err( + runtime::Error::BitcoinNetworkMismatch("".to_string(), "UnknownNetwork".to_string()).into(), + ); + } }; let system_properties = self.btc_parachain.get_rpc_properties().await.unwrap_or_default(); diff --git a/vault/tests/vault_integration_tests.rs b/vault/tests/vault_integration_tests.rs index 446b5e9a2..b7246a196 100644 --- a/vault/tests/vault_integration_tests.rs +++ b/vault/tests/vault_integration_tests.rs @@ -13,8 +13,7 @@ use runtime::{ types::*, utils::account_id::AccountId32, BtcAddress, CurrencyId, FixedPointNumber, FixedU128, InterBtcParachain, InterBtcRedeemRequest, IssuePallet, - OraclePallet, PartialAddress, RedeemPallet, ReplacePallet, ShutdownSender, SudoPallet, UtilFuncs, VaultId, - VaultRegistryPallet, + PartialAddress, RedeemPallet, ReplacePallet, ShutdownSender, SudoPallet, UtilFuncs, VaultId, VaultRegistryPallet, }; use service::DynBitcoinCoreApi; use sp_keyring::AccountKeyring; @@ -960,12 +959,10 @@ impl InterBtcParachainExt for InterBtcParachain { #[cfg(feature = "uses-bitcoind")] mod test_with_bitcoind { - use bitcoin::{BitcoinCore, BitcoinCoreApi, Transaction, TransactionExt}; + use bitcoin::{BitcoinCore, BitcoinCoreApi, Hash, Transaction, TransactionExt}; use runtime::BtcRelayPallet; - use vault::service::Runner; - use std::cmp::max; - use vault::{delay::ZeroDelay, relay::Config}; + use vault::{delay::ZeroDelay, relay::Config, service::Runner}; use super::*; @@ -1020,7 +1017,7 @@ mod test_with_bitcoind { .unwrap(); parachain_rpc - .wait_for_block_in_relay(H256Le::from_bytes_le(&metadata.block_hash), Some(0)) + .wait_for_block_in_relay(H256Le::from_bytes_le(metadata.block_hash.as_byte_array()), Some(0)) .await .unwrap();