feat(utxo): add RXD ForkIdRxd sighash signing path#2713
feat(utxo): add RXD ForkIdRxd sighash signing path#2713shamardy merged 9 commits intoGLEECBTC:devfrom
Conversation
|
can you please rebase to latest dev branch? |
- add ChainVariant::RXD and coin-scoped routing for RXD signing - implement RXD hashOutputHashes computation and insert before hashOutputs in ForkId preimage - enforce RXD fork_id default (0x40) when chain_variant=RXD - keep BTC/BCH signing behavior unchanged
- Revert accidental SHA256-only change in RXD output-hash summarization - Use DSHA256 for scriptPubKey hash, sortedPushRefs hash, and hashOutputHashes aggregate
350f207 to
779faf8
Compare
done |
|
Thanks for the PR, below is my first review to make sure we are on the right track before going deeper. I think the approach of adding It also creates propagation issues. The I think a cleaner approach would be to add a match sigversion {
SignatureVersion::ForkId if sighash.fork_id => {
self.signature_hash_fork_id(...)
},
SignatureVersion::ForkIdRxd if sighash.fork_id => {
self.signature_hash_fork_id_rxd(...)
},
// ...
}The mapping would happen once in One more thing, it would be good to add at least one RXD sighash test vector from a known transaction to verify correctness end-to-end. The Radiant node repo has |
|
Thanks, agreed. I’ll switch dispatch to |
|
Hi @shamardy ,
If you’d like this structured differently, I can adjust. I will be out of country on vacation for 5 days starting Thursday, so my response time may be delayed. |
|
Just for reference, I have run this through a successful swap with the latest change (reduced json): {
"type": "Taker",
"uuid": "71997f0d-9ddb-4587-a558-66fc23c6ec10",
"pair": "RXD/KMD",
"amounts": {
"taker_amount": "10 RXD",
"maker_amount": "0.04 KMD"
},
"sighash_type": "0x41 (ALL|FORKID)",
"htlc": {
"secret_hash": "c5e61f8d5102af8e88e4634d3e8f3d4f3cf06cbc",
"secret_revealed": "e998d47a14fb649037f61a7dda3b67b15dd09da02ca4598f703f1f7f6eae0164"
},
"transactions": {
"taker_fee_tx": "3684bbf882f271ff716110bcfce12123057d41da72892e8961683d297a3f1a09",
"maker_payment_tx": "df4f861a07f9c85c3316199cf2164624a7bec30a08b9561dd513e84d2c723789",
"taker_payment_tx": "fb77ee357a4fa2d657f4dbc2d48c132676f98c3ca585aae8986f42eab123278c",
"taker_payment_spent_tx": "73300377eeb6fb73ff7732b0d560f232b062b004560774f52b17e7e366f4874b",
"maker_payment_spent_tx": "8a3da3efdc5037a8491251832cf6b9763f75cce49c474734f863e00595df1463"
},
"status": {
"finished": true,
"success": true
},
"mm_version": "2.6.0-beta_779faf886"
}coins: {
"coin": "RXD",
"name": "rxd",
"fname": "Radiant",
"rpcport": 7332,
"pubtype": 0,
"p2shtype": 5,
"wiftype": 128,
"txfee": 1000000,
"segwit": false,
"fork_id": "0x40",
"signature_version": "fork_id_rxd",
"mm2": 1,
"sign_message_prefix": "Bitcoin Signed Message:\n",
"required_confirmations": 2,
"avg_blocktime": 300,
"protocol": { "type": "UTXO", "chain_variant": "RXD" },
"derivation_path": "m/44'/512'",
} |
shamardy
left a comment
There was a problem hiding this comment.
Thanks for the fixes. I have more comments below, since you mentioned you'll be on vacation, would it be ok if I continue this PR, I can push fixes to your branch directly.
|
There are some nits / small changes that I will fix and push. |
Prevent integer overflow on 32-bit targets (wasm32) where OP_PUSHDATA2/4 declared lengths could wrap pos + push_len, bypassing bounds checks. Also revert stray whitespace in reader.rs and cherry-pick clippy doctest fix from tron branch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace wildcard with explicit SighashBase variants in compute_hash_output_hashes_rxd for exhaustive matching - Move stream inside match arms to match existing compute_hash_outputs pattern - Use matches! macro for ref-opcode filtering Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Thanks for doing this, much appreciated, my rust coding is rusty :) |

Summary
Adds Radiant (RXD) sighash support by introducing a
ForkIdRxdvariant toSignatureVersion, keeping the signing dispatch clean and self-contained inmm2_bitcoin/script.What changed
SignatureVersion::ForkIdRxdvariant (serde:"fork_id_rxd") to route RXD signing through its own preimage path.signature_hash_fork_id_rxdonTransactionInputSigner— follows the BIP143-style ForkId preimage but inserts an additionalhashOutputHashescommitment beforehashOutputs.compute_hash_output_hashes_rxdwhich commits per-output summaries: value, double-SHA256 of scriptPubKey, push-ref count, and double-SHA256 of sorted push-refs.sorted_push_refs_rxdscript parser that extracts and deduplicatesOP_PUSHINPUTREF/OP_PUSHINPUTREFSINGLETON36-byte references from output scripts, withchecked_addfor wasm32 safety.Sighash::is_definedandSighash::from_u32to recognizeForkIdRxdalongsideForkId.enum_derives(cherry-picked).Coin configuration
RXD coins specify the signing path via config — no protocol-level inference needed:
{ "fork_id": "0x40", "signature_version": "fork_id_rxd" }Why
RXD consensus requires a distinct sighash preimage that includes output-hash summaries with push-ref commitments. Routing via
SignatureVersion(where all signing dispatch already happens) avoids addingchain_varianttoTransactionInputSignerand the propagation issues that would cause (e.g.From<Transaction>hardcodingStandard).Tests
test_rxd_forkid_sighash_vector: Verifies sighash against a real on-chain RXD transaction with signature verification.test_sorted_push_refs_rxd_extracts_and_sorts_push_refs: Tests push-ref opcode parsing, deduplication, and sorting with crafted scripts containingOP_PUSHINPUTREF,OP_REQUIREINPUTREF, andOP_PUSHINPUTREFSINGLETON.test_sighash_forkid_is_definedwithForkIdRxdassertions.Validation
ForkIdRxdsigning path.cargo fmtand build checks passed.Files changed
mm2src/mm2_bitcoin/script/src/sign.rs— All RXD sighash logic and testsmm2src/derives/enum_derives/src/lib.rs— Clippy doctest fix