Merge bitcoindevkit/bdk-ffi#325: Expose Address payload and network properties

cd10c75e965584160235db8abb79540d55ce9c80 Add to_qr_uri() method on Address type (thunderbiscuit)
cbd44249f31dd5d92a7e5087f6bc5f2de99163b6 Add kotlin api-docs for Address.payload() and Address.network() (Steve Myers)
20c31d53838ad956c72f4f442654d894ee8d68e1 Expose Address payload and network properties (Steve Myers)
616cb21738d5c3c60743bf27cae3c27944ecd979 Update Cargo.lock (Steve Myers)

Pull request description:

  ### Description

  Fixes #319

  ### Notes to the reviewers

  The test data was generated with:
  ```
  bitcoin-cli -rpcwallet="regtest2" -datadir=/tmp/regtest1/bitcoind -regtest validateaddress "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
  {
    "isvalid": true,
    "address": "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv",
    "scriptPubKey": "001404a6545885dd87b8e147cd327f2e9db362b72346",
    "isscript": false,
    "iswitness": true,
    "witness_version": 0,
    "witness_program": "04a6545885dd87b8e147cd327f2e9db362b72346"
  }
  ```

  ### Changelog notice

  Added
  - Expose Address payload and network properties.

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

  #### New Features:

  * [x] I've added tests for the new feature
  * [x] I've added docs for the new feature

ACKs for top commit:
  thunderbiscuit:
    ACK cd10c75e965584160235db8abb79540d55ce9c80.

Tree-SHA512: 65a1d550577fd4a35cfeb8fb765002e47e0703ff40fc7a68c07b78bc1ba642d33a0efbdfa8f9322024841ba84d25c0e289294c10ae4c1b4d52eb9beffa3d0e10
This commit is contained in:
Steve Myers 2023-03-23 16:38:13 -05:00
commit 6be4ddaf7b
No known key found for this signature in database
GPG Key ID: 8105A46B22C2D051
4 changed files with 212 additions and 69 deletions

141
Cargo.lock generated
View File

@ -78,9 +78,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
[[package]]
name = "async-trait"
version = "0.1.64"
version = "0.1.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc"
dependencies = [
"proc-macro2",
"quote",
@ -182,11 +182,11 @@ dependencies = [
[[package]]
name = "bip39"
version = "1.0.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f"
checksum = "29b9e657de8ff1c3488a4ab77cb51d604eab53415ce34f0bc800f2eac9b13c28"
dependencies = [
"bitcoin_hashes 0.9.7",
"bitcoin_hashes",
"rand_core 0.4.2",
"serde",
"unicode-normalization",
@ -200,17 +200,11 @@ checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3"
dependencies = [
"base64",
"bech32",
"bitcoin_hashes 0.11.0",
"bitcoin_hashes",
"secp256k1",
"serde",
]
[[package]]
name = "bitcoin_hashes"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1"
[[package]]
name = "bitcoin_hashes"
version = "0.11.0"
@ -270,9 +264,9 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "camino"
version = "1.1.2"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055"
checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
dependencies = [
"serde",
]
@ -362,9 +356,9 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg",
"cfg-if",
@ -375,18 +369,18 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
[[package]]
name = "electrum-client"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82a232d46710f8064b7bb2029d82819fc1f5fba053687e0e3bb47cc762af24f6"
checksum = "a8e1e1e452aef3ee772d19cc6272ef642f22ce0f4a9fb715ffe98010934e2ae1"
dependencies = [
"bitcoin",
"byteorder",
@ -561,9 +555,9 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "js-sys"
@ -588,9 +582,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]]
name = "libsqlite3-sys"
@ -642,9 +636,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.7.1"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
@ -673,9 +667,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniscript"
version = "9.0.0"
version = "9.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "123a10aae81d0712ecc09b780f6f0ae0b0f506a5c4c912974725760d59ba073e"
checksum = "b9601439f168c13bdc5bf84349c2e61c815be4a4dcebe8c4ff4af58f4e8a6d20"
dependencies = [
"bitcoin",
"serde",
@ -739,9 +733,9 @@ dependencies = [
[[package]]
name = "paste"
version = "1.0.11"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "percent-encoding"
@ -799,18 +793,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.51"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
@ -903,9 +897,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.12"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "scopeguard"
@ -949,7 +943,7 @@ version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62"
dependencies = [
"bitcoin_hashes 0.11.0",
"bitcoin_hashes",
"rand",
"secp256k1-sys",
"serde",
@ -966,27 +960,27 @@ dependencies = [
[[package]]
name = "semver"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.152"
version = "1.0.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
checksum = "71f2b4817415c6d4210bfe1c7bfcf4801b2d904cb4d0e1a8fdb651013c9e86b8"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
version = "1.0.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
checksum = "d071a94a3fac4aff69d023a7f411e33f40f3483f8c5190b1953822b6b76d7630"
dependencies = [
"proc-macro2",
"quote",
@ -995,9 +989,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.93"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
dependencies = [
"itoa",
"ryu",
@ -1072,9 +1066,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.107"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
@ -1118,9 +1112,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.25.0"
version = "1.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
dependencies = [
"autocfg",
"pin-project-lite",
@ -1159,15 +1153,15 @@ dependencies = [
[[package]]
name = "unicode-bidi"
version = "0.3.10"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c"
[[package]]
name = "unicode-ident"
version = "1.0.6"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "unicode-normalization"
@ -1478,9 +1472,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
@ -1493,42 +1496,42 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_i686_gnu"
version = "0.42.1"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_msvc"
version = "0.42.1"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.1"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.1"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"

View File

@ -794,8 +794,56 @@ class Script(rawOutputScript: List<UByte>)
* @param address The address in string format.
*/
class Address(address: String) {
/** Return the Payload */
fun payload(): Payload
/** Return the Network. */
fun network(): Network
/** Return the ScriptPubKey. */
fun scriptPubkey(): Script
/**
* Creates a URI string bitcoin:address optimized to be encoded in QR codes.
*
* If the address is bech32, both the schema and the address become uppercase. If the address is base58, the schema is lowercase and the address is left mixed case.
*
* Quoting BIP 173 "inside QR codes uppercase SHOULD be used, as those permit the use of alphanumeric mode, which is 45% more compact than the normal byte mode."
*/
fun toQrUri(): String
}}
/**
* The method used to produce an address.
*/
sealed class Payload {
/** P2PKH address. */
data class PubkeyHash(
val pubkeyHash: List<UByte>
) : Payload()
/** P2SH address. */
data class ScriptHash(
val scriptHash: List<UByte>
) : Payload()
/** Segwit address. */
data class WitnessProgram(
val version: WitnessVersion,
val program: List<UByte>
) : Payload()
}
/**
* Version of the witness program.
*
* Helps limit possible versions of the witness according to the specification. If a plain u8 type
* was used instead it would mean that the version may be > 16, which would be incorrect.
* First byte of scriptPubkey in transaction output for transactions starting with opcodes ranging
* from 0 to 16 (inclusive).
*/
enum class WitnessVersion {
V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16
}
/**

View File

@ -435,7 +435,42 @@ interface Address {
[Throws=BdkError]
constructor(string address);
Payload payload();
Network network();
Script script_pubkey();
string to_qr_uri();
};
[Enum]
interface Payload {
PubkeyHash(sequence<u8> pubkey_hash);
ScriptHash(sequence<u8> script_hash);
WitnessProgram(WitnessVersion version, sequence<u8> program);
};
enum WitnessVersion {
"V0",
"V1",
"V2",
"V3",
"V4",
"V5",
"V6",
"V7",
"V8",
"V9",
"V10",
"V11",
"V12",
"V13",
"V14",
"V15",
"V16"
};
interface Script {

View File

@ -19,6 +19,7 @@ use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn;
use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
use bdk::bitcoin::consensus::Decodable;
use bdk::bitcoin::psbt::serialize::Serialize;
use bdk::bitcoin::util::address::{Payload as BdkPayload, WitnessVersion};
use bdk::bitcoin::{
Address as BdkAddress, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid,
};
@ -356,11 +357,50 @@ impl Address {
.map_err(|e| BdkError::Generic(e.to_string()))
}
fn payload(&self) -> Payload {
match &self.address.payload.clone() {
BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
pubkey_hash: pubkey_hash.to_vec(),
},
BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
script_hash: script_hash.to_vec(),
},
BdkPayload::WitnessProgram { version, program } => Payload::WitnessProgram {
version: *version,
program: program.clone(),
},
}
}
fn network(&self) -> Network {
self.address.network
}
fn script_pubkey(&self) -> Arc<Script> {
Arc::new(Script {
script: self.address.script_pubkey(),
})
}
fn to_qr_uri(&self) -> String {
self.address.to_qr_uri()
}
}
/// The method used to produce an address.
#[derive(Debug)]
pub enum Payload {
/// P2PKH address.
PubkeyHash { pubkey_hash: Vec<u8> },
/// P2SH address.
ScriptHash { script_hash: Vec<u8> },
/// Segwit address.
WitnessProgram {
/// The witness program version.
version: WitnessVersion,
/// The witness program.
program: Vec<u8>,
},
}
/// A Bitcoin script.
@ -403,7 +443,11 @@ uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
#[cfg(test)]
mod test {
use super::Transaction;
use crate::Network::Regtest;
use crate::{Address, Payload};
use assert_matches::assert_matches;
use bdk::bitcoin::hashes::hex::FromHex;
use bdk::bitcoin::util::address::WitnessVersion;
// Verify that bdk-ffi Transaction can be created from valid bytes and serialized back into the same bytes.
#[test]
@ -413,4 +457,17 @@ mod test {
let serialized_tx_to_bytes = new_tx_from_bytes.serialize();
assert_eq!(test_tx_bytes, serialized_tx_to_bytes);
}
// Verify that bdk-ffi Address.payload includes expected WitnessProgram variant, version and program bytes.
#[test]
fn test_address_witness_program() {
let address =
Address::new("bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string()).unwrap();
let payload = address.payload();
assert_matches!(payload, Payload::WitnessProgram { version, program } => {
assert_eq!(version,WitnessVersion::V0);
assert_eq!(program, Vec::from_hex("04a6545885dd87b8e147cd327f2e9db362b72346").unwrap());
});
assert_eq!(address.network(), Regtest);
}
}