From 771fe284ccbca08cc56a122248032c2012cc4e0a Mon Sep 17 00:00:00 2001 From: Aleksey Sidorov Date: Fri, 31 Aug 2018 13:30:02 +0300 Subject: [PATCH] Release 0.3.0 (#5) * Use new rust bitcoin release * Release 0.3.0 * Fix lints * Update fmt script --- .travis.yml | 9 +++++---- CHANGELOG.md | 6 ++++++ Cargo.toml | 16 ++++++++-------- exonum-dictionary.txt | 1 + src/lib.rs | 18 +++++++++++------- src/multisig.rs | 6 +++--- src/p2wpk.rs | 44 +++++++++++++++++++++---------------------- src/p2wsh.rs | 44 +++++++++++++++++++++---------------------- src/sign.rs | 28 +++++++++++++++++---------- src/test_data.rs | 2 +- 10 files changed, 95 insertions(+), 79 deletions(-) diff --git a/.travis.yml b/.travis.yml index bd5e7bf..885e434 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ jobs: include: # Formatting & other lints that do not require compilation - env: FEATURE=lints - rust: 1.26.0 + rust: 1.28.0 install: - rustup component add rustfmt-preview - rustfmt --version @@ -66,16 +66,17 @@ jobs: - npm install markdownlint-cli - ./node_modules/.bin/markdownlint --version script: - - cargo fmt --all -- --write-mode=diff + - cargo fmt --all -- --check - ./node_modules/.bin/cspell {src,examples,tests}/**/*.rs - find . -not -path "./node_modules/*" -name "*.md" | xargs ./node_modules/.bin/cspell - find . -not -path "./node_modules/*" -name "*.md" | xargs ./node_modules/.bin/markdownlint --config .markdownlintrc # Clippy linting - env: FEATURE=clippy - rust: nightly-2018-05-05 + rust: nightly-2018-08-30 install: - - cargo clippy --version | grep $CLIPPY_VERS || cargo install clippy --force --vers $CLIPPY_VERS + - rustup component add clippy-preview + - cargo clippy --version script: - cargo clippy --all -- -D warnings diff --git a/CHANGELOG.md b/CHANGELOG.md index b691d16..d84c05e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## 0.3 - 2018-08-31 + +### Breaking changes + +- `bitcoin` dependency has been updated to the new major release `0.14.1`. (#5) + ## 0.2 - 2018-05-24 ### New features diff --git a/Cargo.toml b/Cargo.toml index 94199ef..f6c8d0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "btc-transaction-utils" -version = "0.2.0" +version = "0.3.0" description = "A collection of helpers for signing bitcoin transactions with segwit." authors = ["The Exonum Team "] readme = "README.md" @@ -11,13 +11,13 @@ categories = ["cryptography"] keywords = ["crypto", "bitcoin", "segwit"] [dependencies] -bitcoin = { version = "0.13.0" } +bitcoin = { version = "0.14.1" } display_derive = "0.0.0" -failure = "0.1.1" -failure_derive = "0.1.1" -hex = "0.3.1" -rand = "0.4.0" -secp256k1 = { version = "0.9.0", features = ["rand"] } -serde = "1.0.37" +failure = "0.1.2" +failure_derive = "0.1.2" +hex = "0.3.2" +rand = "0.4.3" +secp256k1 = { version = "0.11.1", features = ["rand"] } +serde = "1.0.75" serde_str = "0.1.0" pretty_assertions = "0.5.1" \ No newline at end of file diff --git a/exonum-dictionary.txt b/exonum-dictionary.txt index 5efc05d..4b53c32 100644 --- a/exonum-dictionary.txt +++ b/exonum-dictionary.txt @@ -171,6 +171,7 @@ usize validator validator's validators +vout webhook webhooks Webhooks diff --git a/src/lib.rs b/src/lib.rs index 330a0f9..c8d6f5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,7 @@ //! //! use bitcoin::blockdata::opcodes::All; //! use bitcoin::blockdata::script::{Builder, Script}; -//! use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; +//! use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; //! use bitcoin::network::constants::Network; //! use btc_transaction_utils::p2wpk; //! use btc_transaction_utils::test_data::{secp_gen_keypair_with_rng, btc_tx_from_hex}; @@ -88,8 +88,10 @@ //! lock_time: 0, //! input: vec![ //! TxIn { -//! prev_hash: prev_tx.txid(), -//! prev_index: 1, +//! previous_output: OutPoint { +//! txid: prev_tx.txid(), +//! vout: 1, +//! }, //! script_sig: Script::default(), //! sequence: 0xFFFFFFFF, //! witness: Vec::default(), @@ -124,7 +126,7 @@ //! //! use bitcoin::blockdata::opcodes::All; //! use bitcoin::blockdata::script::{Builder, Script}; -//! use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; +//! use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; //! use bitcoin::network::constants::Network; //! use btc_transaction_utils::multisig::RedeemScriptBuilder; //! use btc_transaction_utils::p2wsh; @@ -164,8 +166,10 @@ //! lock_time: 0, //! input: vec![ //! TxIn { -//! prev_hash: prev_tx.txid(), -//! prev_index: 1, +//! previous_output: OutPoint { +//! txid: prev_tx.txid(), +//! vout: 1, +//! }, //! script_sig: Script::default(), //! sequence: 0xFFFFFFFF, //! witness: Vec::default(), @@ -281,7 +285,7 @@ impl<'a> UnspentTxOutValue<'a> { match self { UnspentTxOutValue::Balance(value) => value, UnspentTxOutValue::PrevTx(prev_tx) => { - prev_tx.output[txin.input().prev_index as usize].value + prev_tx.output[txin.input().previous_output.vout as usize].value } UnspentTxOutValue::PrevOut(out) => out.value, } diff --git a/src/multisig.rs b/src/multisig.rs index bdb74cc..bcbea07 100644 --- a/src/multisig.rs +++ b/src/multisig.rs @@ -25,7 +25,7 @@ use bitcoin::blockdata::opcodes::{All, Class}; use bitcoin::blockdata::script::{read_uint, Builder, Instruction, Script}; use failure; use hex; -use secp256k1::{PublicKey, Secp256k1}; +use secp256k1::{None, PublicKey, Secp256k1}; /// A standard redeem script. #[derive(Debug, PartialEq, Clone)] @@ -110,7 +110,7 @@ impl RedeemScriptContent { /// Tries to fetch redeem script content from the given raw script and returns error /// if the script doesn't satisfy `BIP-16` standard. pub fn parse( - context: &Secp256k1, + context: &Secp256k1, script: &Script, ) -> Result { // The lint is false positive in this case. @@ -132,7 +132,7 @@ impl RedeemScriptContent { } }; - let mut instructions = script.into_iter().peekable(); + let mut instructions = script.iter(true).peekable(); // Parses quorum. let quorum = instructions .next() diff --git a/src/p2wpk.rs b/src/p2wpk.rs index ee98e7d..74210ea 100644 --- a/src/p2wpk.rs +++ b/src/p2wpk.rs @@ -19,7 +19,7 @@ use bitcoin::blockdata::transaction::TxIn; use bitcoin::network::constants::Network; use bitcoin::util::address::Address; use bitcoin::util::hash::{Hash160, Sha256dHash}; -use secp256k1::{self, PublicKey, Secp256k1, SecretKey}; +use secp256k1::{self, All, PublicKey, Secp256k1, SecretKey}; use sign; use {InputSignature, InputSignatureRef, TxInRef, UnspentTxOutValue}; @@ -42,7 +42,7 @@ pub fn script_pubkey(pk: &PublicKey) -> Script { /// An input signer. #[derive(Debug)] pub struct InputSigner { - context: Secp256k1, + context: Secp256k1, public_key: PublicKey, network: Network, } @@ -58,12 +58,12 @@ impl InputSigner { } /// Returns a reference to the secp256k1 engine, used to execute all signature operations. - pub fn secp256k1_context(&self) -> &Secp256k1 { + pub fn secp256k1_context(&self) -> &Secp256k1 { &self.context } /// Returns a mutable reference to the secp256k1 engine, used to execute all signature operations. - pub fn secp256k1_context_mut(&mut self) -> &mut Secp256k1 { + pub fn secp256k1_context_mut(&mut self) -> &mut Secp256k1 { &mut self.context } @@ -136,13 +136,13 @@ impl InputSigner { mod tests { use bitcoin::blockdata::opcodes::All; use bitcoin::blockdata::script::{Builder, Script}; - use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; + use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; use bitcoin::network::constants::Network; use rand::{SeedableRng, StdRng}; - use TxInRef; use p2wpk; use test_data::{btc_tx_from_hex, secp_gen_keypair_with_rng}; + use TxInRef; #[test] fn test_native_segwit() { @@ -163,24 +163,22 @@ mod tests { let mut transaction = Transaction { version: 2, lock_time: 0, - input: vec![ - TxIn { - prev_hash: prev_tx.txid(), - prev_index: 1, - script_sig: Script::default(), - sequence: 0xFFFFFFFF, - witness: Vec::default(), - }, - ], - output: vec![ - TxOut { - value: 0, - script_pubkey: Builder::new() - .push_opcode(All::OP_RETURN) - .push_slice(b"Hello Exonum!") - .into_script(), + input: vec![TxIn { + previous_output: OutPoint { + txid: prev_tx.txid(), + vout: 1, }, - ], + script_sig: Script::default(), + sequence: 0xFFFFFFFF, + witness: Vec::default(), + }], + output: vec![TxOut { + value: 0, + script_pubkey: Builder::new() + .push_opcode(All::OP_RETURN) + .push_slice(b"Hello Exonum!") + .into_script(), + }], }; // Makes signature. let mut signer = p2wpk::InputSigner::new(pk, Network::Testnet); diff --git a/src/p2wsh.rs b/src/p2wsh.rs index 78934d9..32fe5c7 100644 --- a/src/p2wsh.rs +++ b/src/p2wsh.rs @@ -19,7 +19,7 @@ use bitcoin::blockdata::transaction::TxIn; use bitcoin::network::constants::Network; use bitcoin::util::address::Address; use bitcoin::util::hash::Sha256dHash; -use secp256k1::{self, PublicKey, Secp256k1, SecretKey}; +use secp256k1::{self, All, PublicKey, Secp256k1, SecretKey}; use multisig::RedeemScript; use sign; @@ -38,7 +38,7 @@ pub fn script_pubkey(redeem_script: &RedeemScript) -> Script { /// An input signer. #[derive(Debug)] pub struct InputSigner { - context: Secp256k1, + context: Secp256k1, script: RedeemScript, } @@ -52,12 +52,12 @@ impl InputSigner { } /// Returns a reference to the secp256k1 engine, used to execute all signature operations. - pub fn secp256k1_context(&self) -> &Secp256k1 { + pub fn secp256k1_context(&self) -> &Secp256k1 { &self.context } /// Returns a mutable reference to the secp256k1 engine, used to execute all signature operations. - pub fn secp256k1_context_mut(&mut self) -> &mut Secp256k1 { + pub fn secp256k1_context_mut(&mut self) -> &mut Secp256k1 { &mut self.context } @@ -123,7 +123,7 @@ impl InputSigner { fn witness_data>>(&self, signatures: I) -> Vec> { let mut witness_stack = vec![Vec::default()]; witness_stack.extend(signatures); - witness_stack.push(self.script.0.clone().into_vec()); + witness_stack.push(self.script.0[..].to_vec()); witness_stack } } @@ -132,7 +132,7 @@ impl InputSigner { mod tests { use bitcoin::blockdata::opcodes::All; use bitcoin::blockdata::script::{Builder, Script}; - use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; + use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; use rand::{SeedableRng, StdRng}; use multisig::RedeemScriptBuilder; @@ -173,24 +173,22 @@ mod tests { let mut transaction = Transaction { version: 2, lock_time: 0, - input: vec![ - TxIn { - prev_hash: prev_tx.txid(), - prev_index: 1, - script_sig: Script::default(), - sequence: 0xFFFFFFFF, - witness: Vec::default(), + input: vec![TxIn { + previous_output: OutPoint { + txid: prev_tx.txid(), + vout: 1, }, - ], - output: vec![ - TxOut { - value: 0, - script_pubkey: Builder::new() - .push_opcode(All::OP_RETURN) - .push_slice(b"Hello Exonum with multisig!") - .into_script(), - }, - ], + script_sig: Script::default(), + sequence: 0xFFFFFFFF, + witness: Vec::default(), + }], + output: vec![TxOut { + value: 0, + script_pubkey: Builder::new() + .push_opcode(All::OP_RETURN) + .push_slice(b"Hello Exonum with multisig!") + .into_script(), + }], }; // Signs transaction. diff --git a/src/sign.rs b/src/sign.rs index c7ca34a..29eb68f 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -20,7 +20,7 @@ use bitcoin::blockdata::script::Script; use bitcoin::blockdata::transaction::SigHashType; use bitcoin::util::bip143::SighashComponents; use bitcoin::util::hash::Sha256dHash; -use secp256k1::{self, Message, PublicKey, Secp256k1, SecretKey, Signature}; +use secp256k1::{self, Message, PublicKey, Secp256k1, SecretKey, Signature, Signing, Verification}; use {TxInRef, UnspentTxOutValue}; @@ -36,7 +36,10 @@ impl InputSignature { } /// Tries to construct input signature from the raw bytes. - pub fn from_bytes(ctx: &Secp256k1, bytes: Vec) -> Result { + pub fn from_bytes( + ctx: &Secp256k1, + bytes: Vec, + ) -> Result { InputSignatureRef::from_bytes(ctx, bytes.as_ref())?; Ok(InputSignature(bytes)) } @@ -84,8 +87,8 @@ pub struct InputSignatureRef<'a>(&'a [u8]); impl<'a> InputSignatureRef<'a> { /// Tries to construct input signature from the raw bytes. - pub fn from_bytes( - ctx: &Secp256k1, + pub fn from_bytes( + ctx: &Secp256k1, bytes: &'a [u8], ) -> Result, secp256k1::Error> { let (_sighash_type, content) = bytes @@ -162,18 +165,22 @@ pub fn signature_hash<'a, 'b, V: Into>>( /// /// [bip-143]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki /// [signature-hash]: fn.signature_hash.html -pub fn sign_input<'a, 'b, V: Into>>( - context: &mut Secp256k1, +pub fn sign_input<'a, 'b, C, V>( + context: &mut Secp256k1, txin: TxInRef<'a>, script: &Script, value: V, secret_key: &SecretKey, -) -> Result { +) -> Result +where + C: Signing, + V: Into>, +{ // Computes sighash. let sighash = signature_hash(txin, script, value); // Makes signature. let msg = Message::from_slice(&sighash[..])?; - let signature = context.sign(&msg, secret_key)?.serialize_der(context); + let signature = context.sign(&msg, secret_key).serialize_der(context); Ok(InputSignature::new(signature, SigHashType::All)) } @@ -181,8 +188,8 @@ pub fn sign_input<'a, 'b, V: Into>>( /// [Read more...][signature-hash] /// /// [signature-hash]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki -pub fn verify_input_signature<'a, 'b, V>( - context: &Secp256k1, +pub fn verify_input_signature<'a, 'b, C, V>( + context: &Secp256k1, txin: TxInRef<'a>, script: &Script, value: V, @@ -190,6 +197,7 @@ pub fn verify_input_signature<'a, 'b, V>( signature: &[u8], ) -> Result<(), secp256k1::Error> where + C: Verification, V: Into>, { // Computes sighash. diff --git a/src/test_data.rs b/src/test_data.rs index 9016b58..0b73042 100644 --- a/src/test_data.rs +++ b/src/test_data.rs @@ -24,7 +24,7 @@ use secp256k1::{PublicKey, Secp256k1, SecretKey}; pub fn secp_gen_keypair_with_rng(rng: &mut R) -> (PublicKey, SecretKey) { let context = Secp256k1::new(); let sk = SecretKey::new(&context, rng); - let pk = PublicKey::from_secret_key(&context, &sk).unwrap(); + let pk = PublicKey::from_secret_key(&context, &sk); (pk, sk) }