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

Update to bitcoin 0.30 ecosystem #41

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 31 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Expand Up @@ -24,11 +24,11 @@ default = ["cli"]
cli = ["base64-compat", "clap", "fern", "hex", "log", "jobserver", "shell-escape"]

[dependencies]
bitcoin = { version = "0.29.2", features = [ "serde", "rand" ] }
secp256k1 = { version = "0.24.3", features = [ "recovery" ] }
bitcoin = { version = "0.30.1", features = [ "serde", "rand", "rand-std" ] }
secp256k1 = { version = "0.27.0", features = [ "recovery" ] }
bip39 = { version = "1.0.1", features = [ "all-languages" ] }
lightning-invoice = "0.4.0"
miniscript = { version = "9.0.0", features = ["compiler"] }
miniscript = { version = "10.0.0", features = ["compiler"] }
byteorder = "1.3.1"
chrono = { version = "0.4.6", features = ["serde"] }
lazy_static = "1.4"
Expand Down
38 changes: 23 additions & 15 deletions src/address.rs
@@ -1,4 +1,6 @@
use bitcoin::address::NetworkUnchecked;
use bitcoin::{self, Address, Network, Script, PubkeyHash, ScriptHash, WPubkeyHash, WScriptHash};
use secp256k1::XOnlyPublicKey;
use serde::{Deserialize, Serialize};

use crate::SECP;
Expand All @@ -20,42 +22,48 @@ pub struct AddressInfo {
pub witness_pubkey_hash: Option<WPubkeyHash>,
#[serde(skip_serializing_if = "Option::is_none")]
pub witness_script_hash: Option<WScriptHash>,
#[serde(skip_serializing_if = "Option::is_none")]
pub taproot_output_key: Option<XOnlyPublicKey>,
}

#[derive(Clone, PartialEq, Eq, Debug, Default, Deserialize, Serialize)]
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
pub struct Addresses {
#[serde(skip_serializing_if = "Option::is_none")]
pub p2pkh: Option<Address>,
pub p2pkh: Option<Address<NetworkUnchecked>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub p2wpkh: Option<Address>,
pub p2wpkh: Option<Address<NetworkUnchecked>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub p2shwpkh: Option<Address>,
pub p2shwpkh: Option<Address<NetworkUnchecked>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub p2sh: Option<Address>,
pub p2sh: Option<Address<NetworkUnchecked>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub p2wsh: Option<Address>,
pub p2wsh: Option<Address<NetworkUnchecked>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub p2shwsh: Option<Address>,
pub p2shwsh: Option<Address<NetworkUnchecked>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub p2tr: Option<Address>,
pub p2tr: Option<Address<NetworkUnchecked>>,
}

pub fn addr_unchecked(addr: Address) -> Address<NetworkUnchecked> {
Address::new(addr.network, addr.payload)
Copy link
Owner

Choose a reason for hiding this comment

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

Uff this is a bit annoying..

}

impl Addresses {
pub fn from_pubkey(pubkey: &bitcoin::PublicKey, network: Network) -> Addresses {
Addresses {
p2pkh: Some(Address::p2pkh(pubkey, network)),
p2wpkh: Address::p2wpkh(pubkey, network).ok(),
p2shwpkh: Address::p2shwpkh(pubkey, network).ok(),
p2tr: Some(Address::p2tr(&SECP, pubkey.inner.into(), None, network)),
p2pkh: Some(addr_unchecked(Address::p2pkh(pubkey, network))),
p2wpkh: Address::p2wpkh(pubkey, network).map(addr_unchecked).ok(),
p2shwpkh: Address::p2shwpkh(pubkey, network).map(addr_unchecked).ok(),
p2tr: Some(addr_unchecked(Address::p2tr(&SECP, pubkey.inner.into(), None, network))),
..Default::default()
}
}

pub fn from_script(script: &Script, network: Network) -> Addresses {
Addresses {
p2sh: Address::p2sh(&script, network).ok(),
p2wsh: Some(Address::p2wsh(&script, network)),
p2shwsh: Some(Address::p2shwsh(&script, network)),
p2sh: Address::p2sh(&script, network).map(addr_unchecked).ok(),
p2wsh: Some(addr_unchecked(Address::p2wsh(&script, network))),
p2shwsh: Some(addr_unchecked(Address::p2shwsh(&script, network))),
// NB to make a p2tr here we need a NUMS internal key and it's
// probably not safe to pick one ourselves. AFAIK there is no
// standard NUMS point for this purpose.
Expand Down
64 changes: 37 additions & 27 deletions src/bin/hal/cmd/address.rs
@@ -1,12 +1,15 @@

use std::str::FromStr;

use bitcoin::address::NetworkUnchecked;
use bitcoin::hashes::Hash;
use bitcoin::hashes::hex::FromHex;
use bitcoin::{Address, WPubkeyHash, WScriptHash};
use bitcoin::{Address, WPubkeyHash, WScriptHash, Script, AddressType};
use clap;

use hal;
use hal::address::addr_unchecked;
use secp256k1::XOnlyPublicKey;

use crate::prelude::*;

Expand Down Expand Up @@ -67,9 +70,9 @@ fn exec_create<'a>(args: &clap::ArgMatches<'a>) {
args.print_output(&addr)
} else if let Some(script_hex) = args.value_of("script") {
let script_bytes = hex::decode(script_hex).need("invalid script hex");
let script = script_bytes.into();
let script = Script::from_bytes(&script_bytes);

let mut ret = hal::address::Addresses::from_script(&script, network);
let mut ret = hal::address::Addresses::from_script(script, network);

// If the user provided NUMS information we can add a p2tr address.
if util::more_than_one(&[
Expand All @@ -94,7 +97,7 @@ fn exec_create<'a>(args: &clap::ArgMatches<'a>) {
};
if let Some(pk) = nums {
let spk = script.to_v1_p2tr(&SECP, pk.into());
ret.p2tr = Some(Address::from_script(&spk, network).unwrap());
ret.p2tr = Some(addr_unchecked(Address::from_script(&spk, network).unwrap()));
}

args.print_output(&ret)
Expand All @@ -111,26 +114,30 @@ fn cmd_inspect<'a>() -> clap::App<'a, 'a> {

fn exec_inspect<'a>(args: &clap::ArgMatches<'a>) {
let address_str = args.value_of("address").need("no address provided");
let address: Address = address_str.parse().need("invalid address format");
let address: Address<NetworkUnchecked> = address_str.parse().need("invalid address format");
let address = address.require_network(args.network()).unwrap();
let script_pk = address.script_pubkey();

let mut info = hal::address::AddressInfo {
network: address.network,
script_pub_key: hal::tx::OutputScriptInfo {
hex: Some(script_pk.to_bytes().into()),
asm: Some(script_pk.asm()),
asm: Some(script_pk.to_asm_string()),
address: None,
type_: None,
},
type_: None,
witness_program_version: None,
pubkey_hash: None,
script_hash: None,
witness_pubkey_hash: None,
witness_script_hash: None,
witness_program_version: None,
taproot_output_key: None,
};

use bitcoin::util::address::Payload;

use bitcoin::address::Payload;
let addr_ty = address.address_type();
match address.payload {
Payload::PubkeyHash(pkh) => {
info.type_ = Some("p2pkh".to_owned());
Expand All @@ -140,28 +147,31 @@ fn exec_inspect<'a>(args: &clap::ArgMatches<'a>) {
info.type_ = Some("p2sh".to_owned());
info.script_hash = Some(sh);
}
Payload::WitnessProgram {
version,
program,
} => {
Payload::WitnessProgram(prog) => {
let (version, program) = (prog.version(), prog.program());
let version = version.to_num() as usize;
info.witness_program_version = Some(version);

if version == 0 {
if program.len() == 20 {
info.type_ = Some("p2wpkh".to_owned());
info.witness_pubkey_hash =
Some(WPubkeyHash::from_slice(&program).need("size 20"));
} else if program.len() == 32 {
info.type_ = Some("p2wsh".to_owned());
info.witness_script_hash =
Some(WScriptHash::from_slice(&program).need("size 32"));
} else {
info.type_ = Some("invalid-witness-program".to_owned());
}
} else {
info.type_ = Some("unknown-witness-program-version".to_owned());
}
match addr_ty {
Some(ty) => {
info.type_ = Some(ty.to_string());
match ty {
AddressType::P2pkh => unreachable!("Dealt earlier"),
AddressType::P2sh => unreachable!("Dealt earlier"),
AddressType::P2wpkh =>
info.witness_pubkey_hash = Some(WPubkeyHash::from_slice(program.as_bytes()).need("size 20")),
AddressType::P2wsh =>
info.witness_script_hash = Some(WScriptHash::from_slice(program.as_bytes()).need("size 32")),
AddressType::P2tr =>
info.taproot_output_key = Some(XOnlyPublicKey::from_slice(program.as_bytes()).need("size 32")),
_ => {},
}
},
None => info.type_ = Some("unknown-witness-program-version".to_owned()),
};
}
_ => {
info.type_ = Some("unknown payload".to_owned());
Copy link
Owner

Choose a reason for hiding this comment

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

Is this because of non-exhaustive?

}
}

Expand Down
2 changes: 1 addition & 1 deletion src/bin/hal/cmd/bip32.rs
@@ -1,6 +1,6 @@
use std::str::FromStr;

use bitcoin::util::bip32;
use bitcoin::bip32;
use clap;

use crate::prelude::*;
Expand Down
6 changes: 3 additions & 3 deletions src/bin/hal/cmd/block.rs
@@ -1,7 +1,7 @@
use std::io::Write;

use bitcoin::consensus::encode::{deserialize, serialize};
use bitcoin::{Block, BlockHeader};
use bitcoin::{Block, block};

use hal::block::{BlockHeaderInfo, BlockInfo};
use crate::prelude::*;
Expand Down Expand Up @@ -60,12 +60,12 @@ Example format:
)
}

fn create_block_header(info: BlockHeaderInfo) -> BlockHeader {
fn create_block_header(info: BlockHeaderInfo) -> block::Header {
if info.block_hash.is_some() {
warn!("Field \"block_hash\" is ignored.");
}

BlockHeader {
block::Header {
version: info.version,
prev_blockhash: info.previous_block_hash,
merkle_root: info.merkle_root,
Expand Down
3 changes: 2 additions & 1 deletion src/bin/hal/cmd/merkle.rs
Expand Up @@ -3,8 +3,9 @@ use std::io::Write;
use std::str::FromStr;
use std::process;

use bitcoin::merkle_tree::PartialMerkleTree;
use bitcoin::{Block, Txid};
use bitcoin::util::merkleblock::PartialMerkleTree;

use clap;

use crate::prelude::*;
Expand Down