From 1e9ecfbe52a254c0ac529d34fc3c84aefa43740c Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Wed, 1 Feb 2023 16:20:41 -0500 Subject: [PATCH 01/17] Add weight, size, and vsize methods on the Transaction type --- bdk-ffi/src/bdk.udl | 12 +++++++++--- bdk-ffi/src/lib.rs | 12 ++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 9be878d..dea0604 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -244,10 +244,16 @@ interface FeeRate { }; interface Transaction { - [Throws=BdkError] - constructor(sequence transaction_bytes); + [Throws=BdkError] + constructor(sequence transaction_bytes); - sequence serialize(); + sequence serialize(); + + u64 weight(); + + u64 size(); + + u64 vsize(); }; interface PartiallySignedTransaction { diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index f82b6cb..de67dea 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -254,6 +254,18 @@ impl Transaction { fn serialize(&self) -> Vec { self.internal.serialize() } + + fn weight(&self) -> u64 { + self.internal.weight() as u64 + } + + fn size(&self) -> u64 { + self.internal.size() as u64 + } + + fn vsize(&self) -> u64 { + self.internal.vsize() as u64 + } } /// A Bitcoin address. From d3e183a498dcf0764544adeb0c8d2232b0f00df0 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Wed, 8 Mar 2023 15:20:14 -0500 Subject: [PATCH 02/17] Add Kotlin API docs for new Transaction methods --- .../src/main/kotlin/org/bitcoindevkit/bdk.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt b/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt index 77ad251..baf8976 100644 --- a/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt +++ b/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt @@ -290,6 +290,23 @@ class Blockchain( class Transaction(transactionBytes: List) { /** Return the transaction bytes, bitcoin consensus encoded. */ fun serialize(): List {} + + /** + * Returns the "weight" of this transaction, as defined by BIP141. + * + * For transactions with an empty witness, this is simply the consensus-serialized size times four. For transactions with a witness, this is the non-witness consensus-serialized size multiplied by three plus the with-witness consensus-serialized size. + */ + fun weight(): ULong {} + + /** Returns the regular byte-wise consensus-serialized size of this transaction. */ + fun size(): ULong {} + + /** + * Returns the "virtual size" (vsize) of this transaction. + * + * Will be ceil(weight / 4.0). Note this implements the virtual size as per BIP141, which is different to what is implemented in Bitcoin Core. The computation should be the same for any remotely sane transaction. + */ + fun vsize(): ULong {} } /** From e0506deffa155ed2bd9794e904bd10e42a523578 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Fri, 10 Mar 2023 15:36:58 -0500 Subject: [PATCH 03/17] Add new utility methods on Transaction type This PR adds the txid(), is_coin_base(), is_explicitly_rbf(), and is_lock_time_enabled() methods. Fixes #303 --- Cargo.lock | 8 +++--- .../src/main/kotlin/org/bitcoindevkit/bdk.kt | 26 ++++++++++++++++--- bdk-ffi/src/bdk.udl | 10 ++++++- bdk-ffi/src/lib.rs | 20 ++++++++++++-- 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e603be..0310efa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1197,18 +1197,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", diff --git a/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt b/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt index baf8976..3cd6e2f 100644 --- a/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt +++ b/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt @@ -288,13 +288,15 @@ class Blockchain( * @param transactionBytes The transaction bytes, bitcoin consensus encoded. */ class Transaction(transactionBytes: List) { - /** Return the transaction bytes, bitcoin consensus encoded. */ - fun serialize(): List {} + /** Computes the txid. */ + fun txid(): String {} /** * Returns the "weight" of this transaction, as defined by BIP141. * - * For transactions with an empty witness, this is simply the consensus-serialized size times four. For transactions with a witness, this is the non-witness consensus-serialized size multiplied by three plus the with-witness consensus-serialized size. + * For transactions with an empty witness, this is simply the consensus-serialized size times four. + * For transactions with a witness, this is the non-witness consensus-serialized size multiplied by three + * plus the with-witness consensus-serialized size. */ fun weight(): ULong {} @@ -304,9 +306,25 @@ class Transaction(transactionBytes: List) { /** * Returns the "virtual size" (vsize) of this transaction. * - * Will be ceil(weight / 4.0). Note this implements the virtual size as per BIP141, which is different to what is implemented in Bitcoin Core. The computation should be the same for any remotely sane transaction. + * Will be ceil(weight / 4.0). Note this implements the virtual size as per BIP141, which is different to + * what is implemented in Bitcoin Core. The computation should be the same for any remotely sane transaction. */ fun vsize(): ULong {} + + /** Return the transaction bytes, bitcoin consensus encoded. */ + fun serialize(): List {} + + /** Is this a coin base transaction? */ + fun isCoinBase(): Boolean {} + + /** + * Returns true if the transaction itself opted in to be BIP-125-replaceable (RBF). + * This does not cover the case where a transaction becomes replaceable due to ancestors being RBF. + */ + fun isExplicitlyRbf(): Boolean {} + + /** Returns true if this transactions nLockTime is enabled (BIP-65). */ + fun isLockTimeEnabled(): Boolean {} } /** diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index dea0604..287b541 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -247,13 +247,21 @@ interface Transaction { [Throws=BdkError] constructor(sequence transaction_bytes); - sequence serialize(); + string txid(); u64 weight(); u64 size(); u64 vsize(); + + sequence serialize(); + + boolean is_coin_base(); + + boolean is_explicitly_rbf(); + + boolean is_lock_time_enabled(); }; interface PartiallySignedTransaction { diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index de67dea..6cef73a 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -251,8 +251,8 @@ impl Transaction { Ok(Transaction { internal: tx }) } - fn serialize(&self) -> Vec { - self.internal.serialize() + fn txid(&self) -> String { + self.internal.txid().to_string() } fn weight(&self) -> u64 { @@ -266,6 +266,22 @@ impl Transaction { fn vsize(&self) -> u64 { self.internal.vsize() as u64 } + + fn serialize(&self) -> Vec { + self.internal.serialize() + } + + fn is_coin_base(&self) -> bool { + self.internal.is_coin_base() + } + + fn is_explicitly_rbf(&self) -> bool { + self.internal.is_explicitly_rbf() + } + + fn is_lock_time_enabled(&self) -> bool { + self.internal.is_lock_time_enabled() + } } /// A Bitcoin address. From 40ca62086c3a15a014303659ea4d3f3794a0a088 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Mon, 13 Mar 2023 12:04:51 -0400 Subject: [PATCH 04/17] Expose all fields on the Transaction type --- bdk-ffi/src/bdk.udl | 2 +- bdk-ffi/src/lib.rs | 59 +++++++++++++++++++++++++++++++++---------- bdk-ffi/src/psbt.rs | 4 ++- bdk-ffi/src/wallet.rs | 2 +- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 287b541..09195ab 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -188,7 +188,7 @@ dictionary OutPoint { dictionary TxOut { u64 value; - string address; + Script script_pubkey; }; enum KeychainKind { diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index 6cef73a..a90403d 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -17,9 +17,7 @@ use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet}; use bdk::bitcoin::blockdata::script::Script as BdkScript; use bdk::bitcoin::consensus::Decodable; use bdk::bitcoin::psbt::serialize::Serialize; -use bdk::bitcoin::{ - Address as BdkAddress, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid, -}; +use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid}; use bdk::blockchain::Progress as BdkProgress; use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration}; use bdk::keys::bip39::WordCount; @@ -79,7 +77,7 @@ pub enum AddressIndex { /// Use with caution, if an index is given that is less than the current descriptor index /// then the returned address and subsequent addresses returned by calls to `AddressIndex::New` /// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a - /// value earlier than the [`crate::blockchain::Blockchain`] stop_gap (default is 20) then a + /// value earlier than the [`Blockchain`] stop_gap (default is 20) then a /// larger stop_gap should be used to monitor for all possibly used addresses. Reset { index: u32 }, } @@ -175,11 +173,12 @@ impl From for Balance { } /// A transaction output, which defines new coins to be created from old ones. +#[derive(Debug)] pub struct TxOut { /// The value of the output, in satoshis. value: u64, /// The address of the output. - address: String, + script_pubkey: Arc