Repository navigation
Conversation
oleonardolima
left a comment
There was a problem hiding this comment.
cACK a5d9f41
You can rebase to get the latest toolchain updated CI. Overall looks good, I only would like to take a deeper look into the last commit.
Also, I'd avoid mixing renaming and moving code in the same commits. |
a5d9f41 to
6d5cac1
Compare
|
@tvpeter Oh, there are some conflicts 😅 |
Yeah, from the recent merge. I will rebase and resolve |
e381444 to
49ba5a5
Compare
49ba5a5 to
067245e
Compare
|
@tvpeter I've rebased it on top of master to solve the conflicts, let me know if it's all good or I've messed something. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2177 +/- ##
=======================================
Coverage 80.66% 80.66%
=======================================
Files 31 31
Lines 6236 6236
Branches 293 293
=======================================
Hits 5030 5030
Misses 1136 1136
Partials 70 70
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
At a glance, it looks just fine. Thank you. |
|
Remember that PR descriptions need to explain why things are done.
What is the rationale for this? Edit: I see that it is my suggestion in the ticket. I was wrong. |
Alright, should I revert the aspect that updates the |
5ee920d to
ee76753
Compare
ee76753 to
16619d4
Compare
16619d4 to
1b2e2b6
Compare
|
@tvpeter any idea when we can expect a 0.14.0 release of testenv? |
I checked and noticed that the last release was nearly a year ago. Therefore, next month should be an ideal time for the next release. |
1b2e2b6 to
f8e51df
Compare
c93e2ae to
d85a806
Compare
d85a806 to
8a43ad7
Compare
|
CI failures issue #2386 |
8a43ad7 to
c521f1c
Compare
f8b517d to
40f4cd5
Compare
chain to testenvtestenv
evanlinjin
left a comment
There was a problem hiding this comment.
Thanks for pushing this forward.
| //! - `std` (default): use the standard library, including its `HashMap`/`HashSet`. Without it, this | ||
| //! crate is `no_std` and uses `alloc`'s `BTreeMap`/`BTreeSet` instead. | ||
| //! - `serde`: implement `serde::Serialize`/`serde::Deserialize` for this crate's types. | ||
| //! - `hashbrown`: use [`hashbrown`](https://docs.rs/hashbrown)'s `HashMap`/`HashSet` for this | ||
| //! crate's hash collections (e.g. `bdk_chain`'s `TxGraph`), on `std` builds too. These hash | ||
| //! with `ahash` using fixed, publicly known keys unless `ahash`'s `runtime-rng` or | ||
| //! `compile-time-rng` feature is enabled somewhere in the dependency graph. With fixed keys, a | ||
| //! malicious chain source can send transactions crafted to collide, making insertion | ||
| //! quadratic. To randomize the keys, depend on | ||
| //! `ahash = { version = "0.8", features = ["runtime-rng"] }` (or `compile-time-rng`) yourself. | ||
| //! crate's hash collections (e.g. `bdk_chain`'s `TxGraph`), on `std` builds too. These hash with | ||
| //! `ahash` using fixed, publicly known keys unless `ahash`'s `runtime-rng` or `compile-time-rng` | ||
| //! feature is enabled somewhere in the dependency graph. With fixed keys, a malicious chain | ||
| //! source can send transactions crafted to collide, making insertion quadratic. To randomize the | ||
| //! keys, depend on `ahash = { version = "0.8", features = ["runtime-rng"] }` (or | ||
| //! `compile-time-rng`) yourself. |
There was a problem hiding this comment.
Rebasing onto master dropped the changes.
| //! Testing utilities for building and testing Bitcoin applications against a local | ||
| //! regtest network. The struct [`TestEnv`], manages a single `bitcoind` node | ||
| //! with a connected `electrs` instance and drives them through common test scenarios. | ||
| //! | ||
| //! ## Features | ||
| //! | ||
| //! * **Node management** — spin up and configure `bitcoind` and `electrs` via [`TestEnv`] and | ||
| //! [`Config`]. The default configuration enables HTTP on `electrsd`, as required by `bdk_esplora` | ||
| //! tests. | ||
| //! * **Block mining** — generate blocks with [`TestEnv::mine_blocks`], or shape individual blocks | ||
| //! with [`TestEnv::mine_block`] and [`MineParams`] to produce empty blocks, set custom | ||
| //! timestamps, or choose the coinbase output script. | ||
| //! * **Chain reorganizations** — fork and reorg the chain with [`TestEnv::invalidate_blocks`], | ||
| //! [`TestEnv::reorg`], and [`TestEnv::reorg_empty_blocks`] to exercise how an application handles | ||
| //! conflicting chain states. | ||
| //! * **Transactions & sync** — broadcast via Bitcoin Core RPC ([`TestEnv::send`]) and block on the | ||
| //! Electrum server with [`TestEnv::wait_until_electrum_tip_syncs_with_bitcoind`], | ||
| //! [`TestEnv::wait_until_electrum_sees_block`], and [`TestEnv::wait_until_electrum_sees_txid`] to | ||
| //! keep components in sync during tests. | ||
| //! * **Transaction-graph templates** — build deterministic transaction histories and conflict | ||
| //! scenarios with the [`tx_template`] module, without a running node. |
There was a problem hiding this comment.
nit: The Features list uses em dashes, but doc comments are kept ASCII in this repo. It also repeats most method names, and line 4 has a stray comma ("The struct [TestEnv], manages"). A shorter ASCII version:
| //! Testing utilities for building and testing Bitcoin applications against a local | |
| //! regtest network. The struct [`TestEnv`], manages a single `bitcoind` node | |
| //! with a connected `electrs` instance and drives them through common test scenarios. | |
| //! | |
| //! ## Features | |
| //! | |
| //! * **Node management** — spin up and configure `bitcoind` and `electrs` via [`TestEnv`] and | |
| //! [`Config`]. The default configuration enables HTTP on `electrsd`, as required by `bdk_esplora` | |
| //! tests. | |
| //! * **Block mining** — generate blocks with [`TestEnv::mine_blocks`], or shape individual blocks | |
| //! with [`TestEnv::mine_block`] and [`MineParams`] to produce empty blocks, set custom | |
| //! timestamps, or choose the coinbase output script. | |
| //! * **Chain reorganizations** — fork and reorg the chain with [`TestEnv::invalidate_blocks`], | |
| //! [`TestEnv::reorg`], and [`TestEnv::reorg_empty_blocks`] to exercise how an application handles | |
| //! conflicting chain states. | |
| //! * **Transactions & sync** — broadcast via Bitcoin Core RPC ([`TestEnv::send`]) and block on the | |
| //! Electrum server with [`TestEnv::wait_until_electrum_tip_syncs_with_bitcoind`], | |
| //! [`TestEnv::wait_until_electrum_sees_block`], and [`TestEnv::wait_until_electrum_sees_txid`] to | |
| //! keep components in sync during tests. | |
| //! * **Transaction-graph templates** — build deterministic transaction histories and conflict | |
| //! scenarios with the [`tx_template`] module, without a running node. | |
| //! Testing utilities for building and testing Bitcoin applications against a local | |
| //! regtest network. | |
| //! | |
| //! * [`TestEnv`] runs a `bitcoind` node with a connected `electrs` (HTTP enabled, for | |
| //! `bdk_esplora`), and mines blocks, reorgs the chain, broadcasts transactions and waits for | |
| //! `electrs` to catch up. | |
| //! * [`tx_template`] builds deterministic transaction graphs, without a running node. |
There was a problem hiding this comment.
Applied. Thank you.
| impl<A> Default for TxTemplate<A> { | ||
| fn default() -> Self { | ||
| Self { | ||
| tx_name: "", | ||
| inputs: Vec::new(), | ||
| outputs: Vec::new(), | ||
| anchors: Vec::new(), | ||
| last_seen: None, | ||
| assume_canonical: false, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<A> TxTemplate<A> { | ||
| /// Create a new template with a name. | ||
| pub fn new(tx_name: &'static str) -> Self { | ||
| Self { | ||
| tx_name, | ||
| ..Default::default() | ||
| } | ||
| } |
There was a problem hiding this comment.
design: Drop the Default impl. Only new uses it. It's left over from the struct-literal style (..Default::default()) that the builder replaced. It also lets callers build a template whose tx_name is "", so two such templates hit the duplicate-name panic. Without it, every template has to be named:
| impl<A> Default for TxTemplate<A> { | |
| fn default() -> Self { | |
| Self { | |
| tx_name: "", | |
| inputs: Vec::new(), | |
| outputs: Vec::new(), | |
| anchors: Vec::new(), | |
| last_seen: None, | |
| assume_canonical: false, | |
| } | |
| } | |
| } | |
| impl<A> TxTemplate<A> { | |
| /// Create a new template with a name. | |
| pub fn new(tx_name: &'static str) -> Self { | |
| Self { | |
| tx_name, | |
| ..Default::default() | |
| } | |
| } | |
| impl<A> TxTemplate<A> { | |
| /// Create a new template with a name. | |
| pub fn new(tx_name: &'static str) -> Self { | |
| Self { | |
| tx_name, | |
| inputs: Vec::new(), | |
| outputs: Vec::new(), | |
| anchors: Vec::new(), | |
| last_seen: None, | |
| assume_canonical: false, | |
| } | |
| } |
There was a problem hiding this comment.
Dropped. Also makes empty tx_name no longer representable.
- Move `TxTemplate`, `TxInTemplate`, `TxOutTemplate`, `init_graph` `new_tx`, `genesis_block_id`, `tip_block_id` and `spk_at_index` into `bdk_testenv`. - Replace `TxTemplate`'s borrowed `&'a [T]` fields with owned `Vec`s and add a builder API. - Update `tip_block_id` to height. - `bdk_testenv` enables the `miniscript` feature in `bdk_chain`. Because `bdk_chain` has a dev-dependency on `bdk_testenv`, all `bdk_chain` test and benchmark builds run with `miniscript` enabled. This includes CI's `cargo build --workspace --all-targets --no-default-features` step, rendering the `#![cfg(feature = "miniscript")]` gates in `crates/chain/tests/*` always true during these runs.
- Derive output script pubkeys in `init_graph` from the indices a template actually uses, replacing the static loop that pre-populated the `SpkTxOutIndex`. This lifts the 0-9 output limit and stops generating spks that are never used. - Derive `TxInTemplate::Bogus` prevouts from the template and input index instead of a random string, so graphs built from templates are reproducible across runs. - Remove the `changeset!` macro. - Drop redundant `Clone` bound on `init_graph`.
The benchmark constructed txs with `TxIn::default()`. Because a default `TxIn` has a null previous output, these txs were classified as coinbases. When combined with recorded `seen_at` timestamps, this broke canonicalization: - Since bitcoindevkit#2372, canonicalization skips coinbases with a `last_seen` timestamp. This resulted in 0 canonical txs and a balance assertion failure (`0 SAT` vs expected `21000 SAT`). - Prior to bitcoindevkit#2372, this invalid test data triggered a `debug_assert!`. Fix this by assigning each benchmark transaction a distinct, non-null `previous_output`.
- Add crate-level docs covering `TestEnv`, block mining, reorgs and the transaction-graph templates, and document all macros, functions and constants in `utils`. - Add an explicit warning that `DESCRIPTORS` embeds well-known test keys and must never be used on mainnet.
- Problem: `TxTemplateEnv::txids` silently overwrote txids when multiple templates shared a `tx_name` including default unnamed templates where `tx_name` is empty. This caused `PrevTx` references to bind to the wrong transactions. - fix: Panic on `tx_name` collisions during `init_graph` initiali- zation to ensure stricter safety in `init_graph` as a public API.
40f4cd5 to
7088e03
Compare
Description
This PR moves
TxTemplateand helper functions fromcrates/chain/tests/commonintocrates/testenvso that other BDK libraries and users testing against BDK can build transaction histories the same way.Key improvements:
&'a [T]fields inTxTemplatewith ownedVecs and a fluent builder API (with_inputs,with_outputs,with_anchors, andassume_canonical()), removing local variable binding boilerplate.init_graphnow lazily derives script pubkeys from the indices a template actually uses, removing the old 0-9 output limit.TxInTemplate::Bogusprevouts are now deterministically derived from the template and input index instead of a random string.init_graphpanics on duplicatetx_namecollisions instead of silently overwriting entries and breakingPrevTxreferences.changeset!macroAddresses the first and second todos on #1936 and #2275
Note to Reviewers:
new_tx: Retains its exact original behavior to prevent unintended txid changes across callers.reindex_tx_graphbenchmark where default null prevouts made transactions look like coinbases carryingseen_at, causing post-fix(chain): skip coinbase txs with alast_seenin canonicalization #2372 canonicalization failures (0 SATvs21000 SAT).miniscriptfeature:bdk_testenvnow depends onbdk_chain/miniscript, so test/bench builds always have it enabled.Changelog notice
TxTemplate,TxInTemplate,TxOutTemplateandinit_graphfrombdk_chain's tests intobdk_testenv::tx_templatenew_tx,genesis_block_id,tip_block_idandspk_at_indexintobdk_testenv::utils;tip_block_idnow takes a heightTxTemplate;with_inputs/with_outputs/with_anchorstakeimpl IntoIterator, andassume_canonical()replaceswith_assume_canonical(bool)init_graphnow panics on a duplicatetx_nameTxTemplateEnv::txid_to_nametotxidsspk_at_indextakes&Descriptor<DescriptorPublicKey>instead of aKeychainTxOutIndexchangeset!macrobdk_testenvnow depends onbdk_chain'sminiscriptfeatureDESCRIPTORSis no longer#[doc(hidden)], so its warning against mainnet use is visible in the docsChecklists
All Submissions: