feat(wasm-utxo): add Pearl (PEARL) network support - #328
Conversation
| pub const ZCASH_TEST: Base58CheckCodec = Base58CheckCodec::new(0x1d25, 0x1cba); | ||
|
|
||
| // Pearl — Bech32m ONLY (no P2PKH/P2SH exist on this chain, Taproot-only) | ||
| // HRPs from: https://github.com/pearl-research-labs/pearl/blob/master/chaincfg/params.go |
There was a problem hiding this comment.
please use stable links (tags or git shas)
There was a problem hiding this comment.
Fixed — updated to stable tag URL: https://github.com/pearl-research-labs/pearl/blob/v1.1.6/node/chaincfg/params.go
| Zcash, | ||
| ZcashTestnet, | ||
|
|
||
| // https://github.com/pearl-research-labs/pearl/blob/master/chaincfg/params.go |
There was a problem hiding this comment.
Fixed — updated to stable tag URL: https://github.com/pearl-research-labs/pearl/blob/v1.1.6/node/chaincfg/params.go
898eded to
9b21001
Compare
9b21001 to
c521159
Compare
OttoAllmendinger
left a comment
There was a problem hiding this comment.
Review (supersedes my earlier comment)
Re-reviewed at the current head c521159. Correction to my previous review: please disregard its "an earlier revision had segwit && …, good it was fixed" framing — that referenced a force-pushed/orphaned revision that isn't visible in this single-commit PR, so it was confusing. The current code already models Pearl correctly: legacy=false, segwit=false, taproot=true, p2mr=false. No bug there.
I verified the design against the Pearl node source (pearl-research-labs/pearl @ v1.1.6): GetScriptClass (node/txscript/standard.go) recognizes only Taproot (v1), P2MR (v2), and OP_RETURN — everything else is NonStandardTy and rejected by mempool/policy.go. So "taproot-only, no legacy, no segwit v0" matches consensus. 👍
🟡 One real issue in the current code
assert_support() doesn't enforce the new legacy flag. The legacy branch is a no-op:
match script.witness_version() {
None => { /* all coins support legacy scripts */ } // never calls assert_legacy()
...Consequences for Pearl (legacy=false):
- A P2SH/P2PKH script passed to
from_output_script_with_networkis still rejected only incidentally by the bech32 codec, producing a misleading error ("Bech32 only supports witness programs…") instead of "Network does not support legacy scripts". - The
legacyflag is wired intosupports_script_type()but not into the encode path, so the two disagree on why legacy is unsupported.
Suggest calling self.assert_legacy()? in the None arm so the flag is authoritative and the error is meaningful.
🧪 Please add explicit input-type / output-type support tests for Pearl
Right now the only address coverage is the pearl.json fixture, which uses the regtest HRP rprl — the production codecs (prl/tprl) are never exercised, and there are no per-script-type accept/reject assertions for the new coin. Please add tests covering the full support matrix for both Network::Pearl and Network::PearlTestnet:
Output type (script → address, from_output_script_with_network):
| script | expected |
|---|---|
| P2TR (v1) | ✅ encodes to prl1p… / tprl1p… (asserts production HRP) |
| P2WPKH / P2WSH (v0) | ❌ err "does not support segwit" |
| P2PKH / P2SH (legacy) | ❌ err "does not support legacy scripts" (currently fails for the wrong reason — see above) |
| P2MR (v2) | ❌ err "does not support P2MR" |
Input type (address → script, to_output_script_with_network):
| address | expected |
|---|---|
valid prl1p… / tprl1p… P2TR |
✅ decodes to the P2TR script (round-trip) |
a prl1q… v0 address |
define & assert the intended behavior — note the current decode path (get_decode_codecs → single Bech32Codec) will happily decode any witness version, so a v0 input is not rejected today |
| wrong-HRP / legacy-format address | ❌ rejected |
Script-type gating (supports_script_type): assert P2sh=false, P2wsh=P2shP2wsh=false, P2trLegacy=P2trMusig2=true, P2mr=false for Pearl.
FYI I pushed a starting point (test_pearl_taproot_only, production-HRP round-trip + v0/legacy rejection) on claude/bitgowasm-pr-328-review-84d6d2, but it was based on an earlier revision of this commit and predates the legacy flag — treat it as a reference, not something to merge as-is. Happy to rebase it onto c521159 and extend it to the full matrix above if useful.
🤖 Generated with Claude Code
Generated by Claude Code
fc8c4d8 to
aabfc7d
Compare
aabfc7d to
dd9a549
Compare
|
@claude review |
| const p2msScriptTypes = ["p2sh", "p2shP2wsh", "p2wsh"] as const; | ||
|
|
||
| const EXCLUDED_COINS: CoinName[] = ["bsv", "bcha"]; | ||
| const EXCLUDED_COINS: CoinName[] = ["bsv", "bcha", "pearl"]; |
There was a problem hiding this comment.
Done — removed "pearl" from EXCLUDED_COINS. fromNetworkFormat only supports P2MS inputs (its docstring says "Only supports p2sh, p2shP2wsh, and p2wsh inputs (not taproot)"), so Pearl's tests are now marked pending via this.skip() rather than being statically excluded. Pearl will be exercised here once fromNetworkFormat gains taproot support.
- Add Pearl and PearlTestnet variants to Network enum and all match arms - Add pearl/tpearl coin names to js/coinName.ts - Add Bech32Codec constants (HRPs: prl/tprl/rprl) in address/mod.rs - Wire Pearl into get_decode_codecs(), output_script_support(), get_encode_codec() - Add Pearl to BitcoinLike PSBT deserialization arm - Add Pearl cases to test_all_networks! macro and update ALL.len() assertion to 24 - Create test/fixtures/address/pearl.json with P2TR regtest vectors - Add pearl/tpearl to webui networkLabels, COIN_NAMES, and ALL_COINS Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dd9a549 to
3b81958
Compare
Summary
Test plan
References
🤖 Generated with Claude Code