Expand description
BTC transaction utils is a small library that will help to create multisig addresses and sign a some types of segwit transactions.
By using this library you can make the following things:
- Create a redeem script and a corresponding multisig address (3 of 4).
- Sign the
P2WPKinputs. - Sign the
P2WSHinputs.
§Examples
§Create a redeem script and a corresponding multisig address (3 of 4).
use bitcoin::network::constants::Network;
use btc_transaction_utils::multisig::RedeemScriptBuilder;
use btc_transaction_utils::test_data::secp_gen_keypair;
use btc_transaction_utils::p2wsh;
// Generate four key pairs.
let keypairs = (0..4)
.map(|_| secp_gen_keypair(Network::Testnet))
.collect::<Vec<_>>();
// Create a corresponding redeem script.
let public_keys = keypairs.iter().map(|keypair| keypair.0);
let script = RedeemScriptBuilder::with_public_keys(public_keys)
.quorum(3)
.to_script()
.unwrap();
// Create a corresponding testnet address for the given redeem script.
let address = p2wsh::address(&script, Network::Testnet);
println!("{}", address.to_string());§Sign P2WPK input
use bitcoin::{
blockdata::opcodes::all::OP_RETURN,
blockdata::script::{Builder, Script},
blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut},
network::constants::Network
};
use btc_transaction_utils::{
p2wpk,
test_data::{secp_gen_keypair_with_rng, btc_tx_from_hex},
TxInRef
};
use rand::prelude::*;
// Take a transaction with the unspent P2WPK output.
let prev_tx = btc_tx_from_hex(
"02000000000101beccab33bc72bfc81b63fdec8a4a9a4719e4418bdb7b20e47b0\
2074dc42f2d800000000017160014f3b1b3819c1290cd5d675c1319dc7d9d98d5\
71bcfeffffff02dceffa0200000000160014368c6b7c38f0ff0839bf78d77544d\
a96cb685bf28096980000000000160014284175e336fa10865fb4d1351c9e18e7\
30f5d6f90247304402207c893c85d75e2230dde04f5a1e2c83c4f0b7d93213372\
746eb2227b068260d840220705484b6ec70a8fc0d1f80c3a98079602595351b7a\
9bca7caddb9a6adb0a3440012103150514f05f3e3f40c7b404b16f8a09c2c71ba\
d3ba8da5dd1e411a7069cc080a004b91300",
);
// Take the corresponding key pair.
let mut rng = thread_rng();
let keypair = secp_gen_keypair_with_rng(&mut rng, Network::Testnet);
// Create an unsigned transaction
let mut transaction = Transaction {
version: 2,
lock_time: 0,
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(OP_RETURN)
.push_slice(b"Hello Exonum!")
.into_script(),
},
],
};
// 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.key)
.unwrap();
// Finalize the transaction.
signer.spend_input(&mut transaction.input[0], signature);§Sign P2WSH input
use bitcoin::{
blockdata::opcodes::all::OP_RETURN,
blockdata::script::{Builder, Script},
blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut},
network::constants::Network
};
use btc_transaction_utils::{
multisig::RedeemScriptBuilder,
p2wsh,
test_data::{secp_gen_keypair_with_rng, btc_tx_from_hex},
TxInRef
};
use rand::prelude::*;
// Take a transaction with the unspent P2WSH output.
let prev_tx = btc_tx_from_hex(
"02000000000101f8c16000cc59f9505046303944d42a6c264a322f80b46bb4361\
15b6e306ba9950000000000feffffff02f07dc81600000000160014f65eb9d72a\
8475dd8e26f4fa748796e211aa8869102700000000000022002001fb25c3db04c\
a5580da43a7d38dd994650d9aa6d6ee075b4578388deed338ed0247304402206b\
5f211cd7f9b89e80c734b61113c33f437ba153e7ba6bc275eed857e54fcb26022\
0038562e88b805f0cdfd4873ab3579d52268babe6af9c49086c00343187cdf28a\
012103979dff5cd9045f4b6fa454d2bc5357586a85d4789123df45f83522963d9\
4e3217fb91300",
);
// Take the corresponding key pairs and the redeem script.
let total_count = 18;
let quorum = 12;
let mut rng = thread_rng();
let keypairs = (0..total_count)
.into_iter()
.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)
.quorum(quorum)
.to_script()
.unwrap();
// Create an unsigned transaction.
let mut transaction = Transaction {
version: 2,
lock_time: 0,
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(OP_RETURN)
.push_slice(b"Hello Exonum with multisig!")
.into_script(),
},
],
};
// Create signatures for the given input.
let mut signer = p2wsh::InputSigner::new(redeem_script.clone());
let signatures = keypairs[0..quorum]
.iter()
.map(|keypair| {
let txin = TxInRef::new(&transaction, 0);
signer.sign_input(txin, &prev_tx, &keypair.1.key).unwrap()
})
.collect::<Vec<_>>();
// Finalize the transaction.
signer.spend_input(&mut transaction.input[0], signatures);Modules§
- multisig
- Helpers for manipulating with the redeem scripts which used in multisignature transactions.
- p2wpk
- A native
P2WPKinput signer. - p2wsh
- A native
P2WSHinput signer. - test_
data - A set of helpers for testing.
Structs§
- Input
Signature - A signature data with the embedded sighash type byte.
- Input
Signature Ref - A borrowed equivalent of the
InputSignaturedata type. It can be useful for checking incoming signatures from unauthorized sources. - TxInRef
- A borrowed reference to a transaction input.
Enums§
- Unspent
TxOut Value - An auxiliary enumeration that helps to get the balance of the previous unspent transaction output.