Repository navigation
test(htlc): assert the swap tree against the SDK/maker golden vectors - #20
Arshia-r-m wants to merge 1 commit into
Conversation
htlc_swap_tree.rs builds the Boltz swap tree by hand and only checked it against its own reading of the Boltz layout. Nothing tied rgb-lib's leaf encoders, MuSig2 key order and recipient-id encoder to the trees and recipient ids the maker actually returns, and that the SDK checks against. Drift on any side would only show up in a live swap. Vendor the relevant subset of kaleidoswap-sdk's rgb-v1 fixtures (wire-contract.json and rgb-golden-vectors.json at 3b034ac, trunk 660779a) and add three service-free tests: - the claim and refund leaves built by claim_leaf_script and refund_leaf_script match the maker's leaves. The reverse claim leaf carries Boltz's OP_SIZE 32 OP_EQUALVERIFY guard, which the test builder does not emit; the test pins that difference; - MuSig2 aggregation (libsecp256k1) in Boltz order, claim-first for submarine and refund-first for reverse, tweaked by the tree from swap_tree_spend_info, gives the vector output key and lockup address. The other order does not, and each tapleaf hash is committed by that output key; - recipient_id_from_script_buf matches all 12 recipient vectors (both HTLC scripts on all six RGB networks) and the create-response ids. swap_tree_spend_info is factored out of SwapTreeHtlc::new so the integration tests and the golden test share one tree builder. Closes #16 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Regtest results (services restored, 2026-10-15)
🤖 Generated with Claude Code |
🔐 Automated security reviewNo security findings for this revision. This PR is test-only: it vendors golden-vector fixtures, adds service-free tests asserting the test-built swap tree, MuSig2 key order and the production recipient-id encoder against maker/SDK vectors, and factors out a shared tree builder. No production code paths that move funds, handle keys, or accept untrusted input are changed, and the vendored fixture contains only mock-capture test data (a synthetic preimage and throwaway keys), so the change introduces no exploitable security weakness. @cf/zai-org/glm-5.3 · 37,188 in / 1,498 out tokens (≈ $0.06) · 4 files · commit |
Problem
src/wallet/test/htlc_swap_tree.rsbuilds the Boltz swap tree by hand.swap_tree_leaves_match_boltz_layoutonly checks it against our own reading of the Boltz layout. Nothing ties rgb-lib's leaf encoders, MuSig2 key order or recipient-id encoder to what the maker actually returns, which is what the SDK checks against (kaleidoswap-sdk/tests/fixtures/rgb-v1, maker PR #668). If any of the three sides drifted, we would only find out in a live swap.Closes #16
Changes
tests/fixtures/kaleidoswap-sdk/rgb-v1/htlc-golden-vectors.json, plus aREADME.mdwith its provenance.kaleidoswap/kaleidoswap-sdk,tests/fixtures/rgb-v1/wire-contract.jsonandrgb-golden-vectors.json.3b034ac7fefe7a3388ba5fefb1d52fe33b1dce0a, the last commit touching both files.trunkwas at660779a3c1ec9f0bb7c32c9d9cdb276b7cbaff86when fetched on 2026-10-14._sourcekey records the upstream blob ids and SHA-256 hashes.swapTree, timeout, lockup address andrgb.{recipientId,scriptPubkey}, and all 12 recipient vectors.sdk_golden_vectorsmodule inhtlc_swap_tree.rswith three plain#[test]s. None of them callsinitialize().htlc_swap_tree_leaves_match_sdk_golden_vectors:claim_leaf_scriptandrefund_leaf_scriptmust reproduce the maker's claim and refund leaves for both swaps. It also checks the leaf version (0xc0) and that the preimage hashes to the reverse request'spreimageHash.htlc_swap_tree_output_key_matches_sdk_golden_vectors:swap_tree_spend_info, must give the vector's output key,scriptPubkeyand lockup address.htlc_recipient_ids_match_sdk_golden_vectors: productionrecipient_id_from_script_bufmust match all 12 vectors (both HTLC scripts ×bc/tb3/tb4/sb/sbc/bcrt) and round-trip throughscript_buf_from_recipient_id. It must also match the recipient ids in both create responses.swap_tree_spend_info()is factored out ofSwapTreeHtlc::newwithout changing behavior. The integration tests and the golden tests now share one tree builder.secp256k1_musig = { package = "secp256k1", version = "=0.32.0-beta.2" }, used for libsecp256k1's BIP327 key aggregation. It was already inCargo.lockthrough rgb-consensus, so the lockfile gains only one dependency edge and no new crate.Tests
SKIP_INIT=1 cargo test --all-features --lib sdk_golden_vectors: 3 passed, in 0.01s.sandbox-exec -p '(version 1)(allow default)(deny network*)' <test binary> sdk_golden_vectors).029000changed to029100. The leaves test and the output-key test both fail; the output key becomes16ca7d…instead ofa0649c….tb4recipient id changed. The recipient-id test fails.recipient_id_from_script_bufchanged to ignore its network argument. The recipient-id test fails (bcrt:returned wherebc:was expected).refund_leaf_scriptchanged fromOP_CLTVtoOP_CSV. The leaves test fails.cargo fmt --checkandcargo clippy --lib --workspace --all-features --all-targets -- -D warnings: clean.SKIP_INIT=1 cargo test --all-features htlc: 5 passed, 7 failed.swap_tree_leaves_match_boltz_layoutandswap_tree_witnesses_verify.go_online) withInvalidIndexer { details: "not a valid electrum nor esplora server" }, before any HTLC code runs.swap_tree_spend_inforefactor, which makes the sameTaprootBuildercalls.Notes
OP_SIZE 32 OP_EQUALVERIFY(82 01 20 88). rgb-lib'sclaim_leaf_scriptonly builds the submarine form, and the integration tests only exercise that form. The golden test asserts that the reverse leaf equals this guard followed byclaim_leaf_script(...), so the gap is pinned rather than hidden. Neither the builder nor the vectors were changed to make them agree.maker-layer-rgb::build_taker_claim_psbt) and the fee model.htlc_swap_treeis gated on theelectrumfeature, a default feature, so the new tests build in default and--all-featuresruns.🤖 Generated with Claude Code