Merge pull request #387 from pandoracore/builder-p2wildcard
Refactoring script generating functions into a single place
This commit is contained in:
commit
49e97cca65
|
@ -29,7 +29,7 @@ use std::{error, fmt, io};
|
||||||
|
|
||||||
#[cfg(feature = "serde")] use serde;
|
#[cfg(feature = "serde")] use serde;
|
||||||
|
|
||||||
use hash_types::{ScriptHash, WScriptHash};
|
use hash_types::{PubkeyHash, WPubkeyHash, ScriptHash, WScriptHash};
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use consensus::{encode, Decodable, Encodable};
|
use consensus::{encode, Decodable, Encodable};
|
||||||
use hashes::Hash;
|
use hashes::Hash;
|
||||||
|
@ -216,6 +216,65 @@ impl Script {
|
||||||
/// Creates a new empty script
|
/// Creates a new empty script
|
||||||
pub fn new() -> Script { Script(vec![].into_boxed_slice()) }
|
pub fn new() -> Script { Script(vec![].into_boxed_slice()) }
|
||||||
|
|
||||||
|
/// Generates P2PK-type of scriptPubkey
|
||||||
|
pub fn new_p2pk(pubkey: &PublicKey) -> Script {
|
||||||
|
Builder::new()
|
||||||
|
.push_key(pubkey)
|
||||||
|
.push_opcode(opcodes::all::OP_CHECKSIG)
|
||||||
|
.into_script()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates P2PKH-type of scriptPubkey
|
||||||
|
pub fn new_p2pkh(pubkey_hash: &PubkeyHash) -> Script {
|
||||||
|
Builder::new()
|
||||||
|
.push_opcode(opcodes::all::OP_DUP)
|
||||||
|
.push_opcode(opcodes::all::OP_HASH160)
|
||||||
|
.push_slice(&pubkey_hash[..])
|
||||||
|
.push_opcode(opcodes::all::OP_EQUALVERIFY)
|
||||||
|
.push_opcode(opcodes::all::OP_CHECKSIG)
|
||||||
|
.into_script()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates P2SH-type of scriptPubkey with a given hash of the redeem script
|
||||||
|
pub fn new_p2sh(script_hash: &ScriptHash) -> Script {
|
||||||
|
Builder::new()
|
||||||
|
.push_opcode(opcodes::all::OP_HASH160)
|
||||||
|
.push_slice(&script_hash[..])
|
||||||
|
.push_opcode(opcodes::all::OP_EQUAL)
|
||||||
|
.into_script()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates P2WPKH-type of scriptPubkey
|
||||||
|
pub fn new_v0_wpkh(pubkey_hash: &WPubkeyHash) -> Script {
|
||||||
|
Script::new_witness_program(::bech32::u5::try_from_u8(0).unwrap(), &pubkey_hash.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
|
||||||
|
pub fn new_v0_wsh(script_hash: &WScriptHash) -> Script {
|
||||||
|
Script::new_witness_program(::bech32::u5::try_from_u8(0).unwrap(), &script_hash.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
|
||||||
|
pub fn new_witness_program(ver: ::bech32::u5, program: &[u8]) -> Script {
|
||||||
|
let mut verop = ver.to_u8();
|
||||||
|
assert!(verop <= 16);
|
||||||
|
if verop > 0 {
|
||||||
|
verop = 0x50 + verop;
|
||||||
|
}
|
||||||
|
Builder::new()
|
||||||
|
.push_opcode(verop.into())
|
||||||
|
.push_slice(&program)
|
||||||
|
.into_script()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates OP_RETURN-type of scriptPubkey for a given data
|
||||||
|
pub fn new_op_return(data: &[u8]) -> Script {
|
||||||
|
Builder::new()
|
||||||
|
.push_opcode(opcodes::all::OP_RETURN)
|
||||||
|
.push_slice(data)
|
||||||
|
.into_script()
|
||||||
|
}
|
||||||
|
|
||||||
/// The length in bytes of the script
|
/// The length in bytes of the script
|
||||||
pub fn len(&self) -> usize { self.0.len() }
|
pub fn len(&self) -> usize { self.0.len() }
|
||||||
|
|
||||||
|
@ -233,18 +292,13 @@ impl Script {
|
||||||
|
|
||||||
/// Compute the P2SH output corresponding to this redeem script
|
/// Compute the P2SH output corresponding to this redeem script
|
||||||
pub fn to_p2sh(&self) -> Script {
|
pub fn to_p2sh(&self) -> Script {
|
||||||
Builder::new().push_opcode(opcodes::all::OP_HASH160)
|
Script::new_p2sh(&ScriptHash::hash(&self.0))
|
||||||
.push_slice(&ScriptHash::hash(&self.0)[..])
|
|
||||||
.push_opcode(opcodes::all::OP_EQUAL)
|
|
||||||
.into_script()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the P2WSH output corresponding to this witnessScript (aka the "witness redeem
|
/// Compute the P2WSH output corresponding to this witnessScript (aka the "witness redeem
|
||||||
/// script")
|
/// script")
|
||||||
pub fn to_v0_p2wsh(&self) -> Script {
|
pub fn to_v0_p2wsh(&self) -> Script {
|
||||||
Builder::new().push_int(0)
|
Script::new_v0_wsh(&WScriptHash::hash(&self.0))
|
||||||
.push_slice(&WScriptHash::hash(&self.0)[..])
|
|
||||||
.into_script()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether a script pubkey is a p2sh output
|
/// Checks whether a script pubkey is a p2sh output
|
||||||
|
@ -565,7 +619,7 @@ impl<'a> Iterator for Instructions<'a> {
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
/// Creates a new empty script
|
/// Creates a new empty script
|
||||||
pub fn new() -> Builder {
|
pub fn new() -> Self {
|
||||||
Builder(vec![], None)
|
Builder(vec![], None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,14 +825,15 @@ impl Decodable for Script {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use hashes::hex::FromHex;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::build_scriptint;
|
use super::build_scriptint;
|
||||||
|
|
||||||
|
use hashes::hex::{FromHex, ToHex};
|
||||||
use consensus::encode::{deserialize, serialize};
|
use consensus::encode::{deserialize, serialize};
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use util::key::PublicKey;
|
use util::key::PublicKey;
|
||||||
|
use util::psbt::serialize::Serialize;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script() {
|
fn script() {
|
||||||
|
@ -828,6 +883,38 @@ mod test {
|
||||||
assert_eq!(&format!("{:x}", script), "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac");
|
assert_eq!(&format!("{:x}", script), "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn script_generators() {
|
||||||
|
let pubkey = PublicKey::from_str("0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e").unwrap();
|
||||||
|
assert!(Script::new_p2pk(&pubkey).is_p2pk());
|
||||||
|
|
||||||
|
let pubkey_hash = PubkeyHash::hash(&pubkey.serialize());
|
||||||
|
assert!(Script::new_p2pkh(&pubkey_hash).is_p2pkh());
|
||||||
|
|
||||||
|
let wpubkey_hash = WPubkeyHash::hash(&pubkey.serialize());
|
||||||
|
assert!(Script::new_v0_wpkh(&wpubkey_hash).is_v0_p2wpkh());
|
||||||
|
|
||||||
|
let script = Builder::new().push_opcode(opcodes::all::OP_NUMEQUAL)
|
||||||
|
.push_verify()
|
||||||
|
.into_script();
|
||||||
|
let script_hash = ScriptHash::hash(&script.serialize());
|
||||||
|
let p2sh = Script::new_p2sh(&script_hash);
|
||||||
|
assert!(p2sh.is_p2sh());
|
||||||
|
assert_eq!(script.to_p2sh(), p2sh);
|
||||||
|
|
||||||
|
let wscript_hash = WScriptHash::hash(&script.serialize());
|
||||||
|
let p2wsh = Script::new_v0_wsh(&wscript_hash);
|
||||||
|
assert!(p2wsh.is_v0_p2wsh());
|
||||||
|
assert_eq!(script.to_v0_p2wsh(), p2wsh);
|
||||||
|
|
||||||
|
// Test data are taken from the second output of
|
||||||
|
// 2ccb3a1f745eb4eefcf29391460250adda5fab78aaddb902d25d3cd97d9d8e61 transaction
|
||||||
|
let data = Vec::<u8>::from_hex("aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a").unwrap();
|
||||||
|
let op_return = Script::new_op_return(&data);
|
||||||
|
assert!(op_return.is_op_return());
|
||||||
|
assert_eq!(op_return.to_hex(), "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_builder_verify() {
|
fn script_builder_verify() {
|
||||||
let simple = Builder::new()
|
let simple = Builder::new()
|
||||||
|
|
|
@ -41,9 +41,7 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use bech32;
|
use bech32;
|
||||||
use hashes::Hash;
|
use hashes::Hash;
|
||||||
|
|
||||||
use hash_types::{PubkeyHash, WPubkeyHash, ScriptHash, WScriptHash};
|
use hash_types::{PubkeyHash, WPubkeyHash, ScriptHash, WScriptHash};
|
||||||
use blockdata::opcodes;
|
|
||||||
use blockdata::script;
|
use blockdata::script;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
use util::base58;
|
use util::base58;
|
||||||
|
@ -157,11 +155,11 @@ impl FromStr for AddressType {
|
||||||
/// The method used to produce an address
|
/// The method used to produce an address
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum Payload {
|
pub enum Payload {
|
||||||
/// pay-to-pkhash address
|
/// P2PKH address
|
||||||
PubkeyHash(PubkeyHash),
|
PubkeyHash(PubkeyHash),
|
||||||
/// P2SH address
|
/// P2SH address
|
||||||
ScriptHash(ScriptHash),
|
ScriptHash(ScriptHash),
|
||||||
/// Segwit address
|
/// Segwit addresses
|
||||||
WitnessProgram {
|
WitnessProgram {
|
||||||
/// The witness program version
|
/// The witness program version
|
||||||
version: bech32::u5,
|
version: bech32::u5,
|
||||||
|
@ -200,29 +198,15 @@ impl Payload {
|
||||||
/// Generates a script pubkey spending to this [Payload].
|
/// Generates a script pubkey spending to this [Payload].
|
||||||
pub fn script_pubkey(&self) -> script::Script {
|
pub fn script_pubkey(&self) -> script::Script {
|
||||||
match *self {
|
match *self {
|
||||||
Payload::PubkeyHash(ref hash) => script::Builder::new()
|
Payload::PubkeyHash(ref hash) =>
|
||||||
.push_opcode(opcodes::all::OP_DUP)
|
script::Script::new_p2pkh(hash),
|
||||||
.push_opcode(opcodes::all::OP_HASH160)
|
Payload::ScriptHash(ref hash) =>
|
||||||
.push_slice(&hash[..])
|
script::Script::new_p2sh(hash),
|
||||||
.push_opcode(opcodes::all::OP_EQUALVERIFY)
|
|
||||||
.push_opcode(opcodes::all::OP_CHECKSIG),
|
|
||||||
Payload::ScriptHash(ref hash) => script::Builder::new()
|
|
||||||
.push_opcode(opcodes::all::OP_HASH160)
|
|
||||||
.push_slice(&hash[..])
|
|
||||||
.push_opcode(opcodes::all::OP_EQUAL),
|
|
||||||
Payload::WitnessProgram {
|
Payload::WitnessProgram {
|
||||||
version: ver,
|
version: ver,
|
||||||
program: ref prog,
|
program: ref prog,
|
||||||
} => {
|
} => script::Script::new_witness_program(ver, prog)
|
||||||
assert!(ver.to_u8() <= 16);
|
|
||||||
let mut verop = ver.to_u8();
|
|
||||||
if verop > 0 {
|
|
||||||
verop += 0x50;
|
|
||||||
}
|
|
||||||
script::Builder::new().push_opcode(verop.into()).push_slice(&prog)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.into_script()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue