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

Release 0.5 #9

Merged
merged 8 commits into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from 4 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
18 changes: 0 additions & 18 deletions .appveyor.yml

This file was deleted.

8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: rust

rust:
- 1.23.0
- 1.33.0

matrix:
allow_failures:
Expand All @@ -27,7 +27,7 @@ jobs:
include:
# Formatting & other lints that do not require compilation
- name: lints
rust: 1.30.1
rust: 1.33
install:
- rustup component add rustfmt-preview
- rustfmt --version
Expand All @@ -44,7 +44,7 @@ jobs:

# Clippy linting
- name: clippy
rust: 1.30.1
rust: 1.33
install:
- rustup component add clippy-preview
- cargo clippy --version
Expand All @@ -67,7 +67,7 @@ jobs:
# Non-fatal checks
- name: deadlinks
env: FEATURE=non-fatal-checks
rust: 1.30.1
rust: 1.33
install:
- cargo-deadlinks -V | grep $DEADLINKS_VERS || cargo install cargo-deadlinks --vers $DEADLINKS_VERS --force
script:
Expand Down
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## 0.4.0 - 2018-11-220
## 0.5.0 - 2019-03-14

### Breaking changes

- `bitcoin` dependency has been updated to the new major release `0.17`. (#9)

- Methods `secp_gen_keypair_with_rng` and `secp_gen_keypair` now requires
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

secp_gen_keypair_with_rng and secp_gen_keypair methods now require ... and return ...

bitcoin network type and returns `PrivateKey` key instead of `SecretKey`.
- Several methods now longer requires `Secp256k1` context.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"now longer"? Did you mean "no longer"?

- `secp256k1::PublicKey` replaced by the `bitcoin::PublicKey`.

## 0.4.0 - 2018-11-22

### Breaking changes

Expand Down
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "btc-transaction-utils"
version = "0.4.0"
edition = "2018"
description = "A collection of helpers for signing bitcoin transactions with segwit."
authors = ["The Exonum Team <exonum@bitfury.com>"]
readme = "README.md"
Expand All @@ -11,13 +12,12 @@ categories = ["cryptography"]
keywords = ["crypto", "bitcoin", "segwit"]

[dependencies]
bitcoin = { version = "0.15.1" }
display_derive = "0.0"
bitcoin = { version = "0.17" }
bitcoin_hashes = "0.3"
failure = "0.1"
failure_derive = "0.1"
hex = "0.3"
rand = "0.4"
secp256k1 = { version = "0.11", features = ["rand"] }
secp256k1 = { version = "0.12", features = ["rand"] }
serde = "1.0"
serde_str = "0.1"
pretty_assertions = "0.5"
serde_str = "0.1"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

endline

55 changes: 20 additions & 35 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
//! ## Create a redeem script and a corresponding multisig address (3 of 4).
//!
//! ```
//! extern crate bitcoin;
//! extern crate btc_transaction_utils;
//!
//! use bitcoin::network::constants::Network;
//! use btc_transaction_utils::multisig::RedeemScriptBuilder;
Expand All @@ -37,7 +35,7 @@
//! fn main() {
//! // Generate four key pairs.
//! let keypairs = (0..4)
//! .map(|_| secp_gen_keypair())
//! .map(|_| secp_gen_keypair(Network::Testnet))
//! .collect::<Vec<_>>();
//! // Create a corresponding redeem script.
//! let public_keys = keypairs.iter().map(|keypair| keypair.0);
Expand All @@ -54,11 +52,8 @@
//! ## Sign P2WPK input
//!
//! ```
//! extern crate bitcoin;
//! extern crate btc_transaction_utils;
//! extern crate rand;
//!
//! use bitcoin::blockdata::opcodes::All;
//! use bitcoin::blockdata::opcodes::all::OP_RETURN;
//! use bitcoin::blockdata::script::{Builder, Script};
//! use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut};
//! use bitcoin::network::constants::Network;
Expand All @@ -81,7 +76,7 @@
//! );
//! // Take the corresponding key pair.
//! let mut rng: StdRng = SeedableRng::from_seed([1, 2, 3, 4].as_ref());
//! let keypair = secp_gen_keypair_with_rng(&mut rng);
//! let keypair = secp_gen_keypair_with_rng(&mut rng, Network::Testnet);
//! // Create an unsigned transaction
//! let mut transaction = Transaction {
//! version: 2,
Expand All @@ -101,7 +96,7 @@
//! TxOut {
//! value: 0,
//! script_pubkey: Builder::new()
//! .push_opcode(All::OP_RETURN)
//! .push_opcode(OP_RETURN)
//! .push_slice(b"Hello Exonum!")
//! .into_script(),
//! },
Expand All @@ -110,7 +105,7 @@
//! // Create a signature for the given input.
//! let mut signer = p2wpk::InputSigner::new(keypair.0, Network::Testnet);
//! let signature = signer
//! .sign_input(TxInRef::new(&transaction, 0), &prev_tx, &keypair.1)
//! .sign_input(TxInRef::new(&transaction, 0), &prev_tx, &keypair.1.key)
//! .unwrap();
//! // Finalize the transaction.
//! signer.spend_input(&mut transaction.input[0], signature);
Expand All @@ -120,11 +115,8 @@
//! ## Sign P2WSH input
//!
//! ```
//! extern crate bitcoin;
//! extern crate btc_transaction_utils;
//! extern crate rand;
//!
//! use bitcoin::blockdata::opcodes::All;
//! use bitcoin::blockdata::opcodes::all::OP_RETURN;
//! use bitcoin::blockdata::script::{Builder, Script};
//! use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut};
//! use bitcoin::network::constants::Network;
Expand Down Expand Up @@ -153,7 +145,7 @@
//! let mut rng: StdRng = SeedableRng::from_seed([1, 2, 3, 4].as_ref());
//! let keypairs = (0..total_count)
//! .into_iter()
//! .map(|_| secp_gen_keypair_with_rng(&mut rng))
//! .map(|_| secp_gen_keypair_with_rng(&mut rng, Network::Testnet))
//! .collect::<Vec<_>>();
//! let public_keys = keypairs.iter().map(|keypair| keypair.0);
//! let redeem_script = RedeemScriptBuilder::with_public_keys(public_keys)
Expand All @@ -179,7 +171,7 @@
//! TxOut {
//! value: 0,
//! script_pubkey: Builder::new()
//! .push_opcode(All::OP_RETURN)
//! .push_opcode(OP_RETURN)
//! .push_slice(b"Hello Exonum with multisig!")
//! .into_script(),
//! },
Expand All @@ -191,7 +183,7 @@
//! .iter()
//! .map(|keypair| {
//! let txin = TxInRef::new(&transaction, 0);
//! signer.sign_input(txin, &prev_tx, &keypair.1).unwrap()
//! signer.sign_input(txin, &prev_tx, &keypair.1.key).unwrap()
//! })
//! .collect::<Vec<_>>();
//! // Finalize the transaction.
Expand All @@ -203,32 +195,25 @@
//! [p2wpk]: #sign-p2wpk-input
//! [p2wsh]: #sign-p2wsh-input

#![deny(missing_docs, missing_debug_implementations)]

extern crate bitcoin;
#[macro_use]
extern crate display_derive;
extern crate failure;
#[macro_use]
extern crate failure_derive;
extern crate hex;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
extern crate rand;
extern crate secp256k1;
extern crate serde;
extern crate serde_str;
#![deny(
missing_debug_implementations,
missing_docs,
unsafe_code,
bare_trait_objects
)]

#[macro_use]
mod macros;
mod sign;

use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};

pub mod multisig;
pub mod p2wpk;
pub mod p2wsh;
mod sign;
pub mod test_data;

use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
pub(crate) use bitcoin_hashes::{hash160::Hash as Hash160, sha256d::Hash as Sha256dHash, Hash};
pub use sign::{InputSignature, InputSignatureRef};

/// A borrowed reference to a transaction input.
Expand Down
62 changes: 35 additions & 27 deletions src/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@
use std::fmt;
use std::str::FromStr;

use bitcoin::blockdata::opcodes::{All, Class};
use bitcoin::blockdata::script::{read_uint, Builder, Instruction, Script};
use bitcoin::{
blockdata::{
opcodes::{all::OP_CHECKMULTISIG, Class},
script::{read_uint, Builder, Instruction, Script},
},
util::psbt::serialize::Serialize,
PublicKey,
};
use failure;
use failure_derive::Fail;
use hex;
use secp256k1::{None, PublicKey, Secp256k1};

/// A standard redeem script.
#[derive(Debug, PartialEq, Clone)]
Expand All @@ -35,13 +41,13 @@ impl RedeemScript {
/// Tries to parse a raw script as a standard redeem script and returns error
/// if the script doesn't satisfy `BIP-16` standard.
pub fn from_script(script: Script) -> Result<RedeemScript, RedeemScriptError> {
RedeemScriptContent::parse(&Secp256k1::without_caps(), &script)?;
RedeemScriptContent::parse(&script)?;
Ok(RedeemScript(script))
}

/// Returns the redeem script content.
pub fn content(&self) -> RedeemScriptContent {
RedeemScriptContent::parse(&Secp256k1::without_caps(), &self.0).unwrap()
RedeemScriptContent::parse(&self.0).unwrap()
}
}

Expand Down Expand Up @@ -109,12 +115,7 @@ pub struct RedeemScriptContent {
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<None>,
script: &Script,
) -> Result<RedeemScriptContent, RedeemScriptError> {
// The lint is false positive in this case.
#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
pub fn parse(script: &Script) -> Result<RedeemScriptContent, RedeemScriptError> {
fn read_usize(instruction: Instruction) -> Option<usize> {
match instruction {
Instruction::Op(op) => {
Expand Down Expand Up @@ -148,8 +149,8 @@ impl RedeemScriptContent {
break;
}
// Extracts public key from slice.
let pub_key = PublicKey::from_slice(context, slice)
.map_err(|_| RedeemScriptError::NotStandard)?;
let pub_key =
PublicKey::from_slice(slice).map_err(|_| RedeemScriptError::NotStandard)?;
public_keys.push(pub_key);
instructions.next();
}
Expand All @@ -163,7 +164,7 @@ impl RedeemScriptContent {
RedeemScriptError::NotEnoughPublicKeys
);
ensure!(
Some(Instruction::Op(All::OP_CHECKMULTISIG)) == instructions.next(),
Some(Instruction::Op(OP_CHECKMULTISIG)) == instructions.next(),
RedeemScriptError::NotStandard
);
public_keys
Expand Down Expand Up @@ -241,7 +242,7 @@ impl RedeemScriptBuilder {
}
let inner = builder
.push_int(total_count as i64)
.push_opcode(All::OP_CHECKMULTISIG)
.push_opcode(OP_CHECKMULTISIG)
.into_script();
Ok(RedeemScript(inner))
}
Expand All @@ -254,27 +255,32 @@ impl Default for RedeemScriptBuilder {
}

/// Possible errors related to the redeem script.
#[derive(Debug, Copy, Clone, Fail, Display, PartialEq)]
#[derive(Debug, Copy, Clone, Fail, PartialEq)]
pub enum RedeemScriptError {
/// Not enough keys for the quorum.
#[display(fmt = "Not enough keys for the quorum.")]
#[fail(display = "Not enough keys for the quorum.")]
IncorrectQuorum,
/// Quorum was not set during the redeem script building.
#[display(fmt = "Quorum was not set.")]
#[fail(display = "Quorum was not set.")]
NoQuorum,
/// Not enough public keys. At least one public key must be specified.
#[display(fmt = "Not enough public keys. At least one public key must be specified.")]
#[fail(display = "Not enough public keys. At least one public key must be specified.")]
NotEnoughPublicKeys,
/// Given script is not the standard redeem script.
#[display(fmt = "Given script is not the standard redeem script.")]
#[fail(display = "Given script is not the standard redeem script.")]
NotStandard,
}

#[cfg(test)]
mod tests {
use multisig::{RedeemScript, RedeemScriptBuilder, RedeemScriptError};
use std::str::FromStr;
use test_data::secp_gen_keypair;

use bitcoin::network::constants::Network;

use crate::{
multisig::{RedeemScript, RedeemScriptBuilder, RedeemScriptError},
test_data::secp_gen_keypair,
};

#[test]
fn test_redeem_script_builder_no_quorum() {
Expand All @@ -294,7 +300,9 @@ mod tests {

#[test]
fn test_redeem_script_builder_incorrect_quorum() {
let keys = vec![secp_gen_keypair().0, secp_gen_keypair().0];
let keys = (0..2)
.into_iter()
.map(|_| secp_gen_keypair(Network::Testnet).0);
assert_eq!(
RedeemScriptBuilder::with_public_keys(keys)
.quorum(3)
Expand Down Expand Up @@ -346,10 +354,10 @@ mod tests {
#[test]
fn test_redeem_script_convert_hex() {
let script = RedeemScriptBuilder::with_quorum(3)
.public_key(secp_gen_keypair().0)
.public_key(secp_gen_keypair().0)
.public_key(secp_gen_keypair().0)
.public_key(secp_gen_keypair().0)
.public_key(secp_gen_keypair(Network::Testnet).0)
.public_key(secp_gen_keypair(Network::Testnet).0)
.public_key(secp_gen_keypair(Network::Testnet).0)
.public_key(secp_gen_keypair(Network::Testnet).0)
.to_script()
.unwrap();
let string = script.to_string();
Expand Down
Loading