Skip to content

feat(wasm-utxo): add Pearl (PEARL) network support - #328

Merged
manojkumar138 merged 1 commit into
masterfrom
manojkumar138/cecho-1503-duplex-wasm-utxo
Jul 22, 2026
Merged

feat(wasm-utxo): add Pearl (PEARL) network support#328
manojkumar138 merged 1 commit into
masterfrom
manojkumar138/cecho-1503-duplex-wasm-utxo

Conversation

@manojkumar138

@manojkumar138 manojkumar138 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add `Pearl` and `PearlTestnet` variants to `Network` enum with all match arms (`ALL`, `as_str`, `from_name_exact`, `from_coin_name`, `to_coin_name`, `mainnet`)
  • Coin names: `pearl` / `tpearl`; bech32 HRPs: `prl` / `tprl` (regtest: `rprl`)
  • Pearl is Taproot-only (btcd fork): `legacy=false`, `segwit=false`, `taproot=true`; only bech32m addresses, no P2PKH/P2SH/P2WSH
  • Add `Pearl`/`PearlTestnet` to `BitcoinLike` PSBT deserialization arm (standard Bitcoin PSBT format)
  • Add `OutputScriptSupport.legacy` flag; Pearl sets it `false` — rejects P2SH/P2PKH at encode and script-type gating
  • Extend MuSig2 support to Pearl (taproot key-path spending is standard BIP-340/341, same as Bitcoin)
  • Add `pearl.json` address fixture with P2TR test vectors from live regtest node (`pearld 1.0.2`, coins-sandbox PR #898)
  • Update `test_all_networks!` macro and `ALL.len()` assertions (22 → 24)
  • Add `pearl`/`tpearl` to `js/coinName.ts`, webui `networkLabels`, `COIN_NAMES`, and `ALL_COINS`
  • Gate `p2shP2pk` input and hardcoded P2SH outputs in `AcidTest` behind `supportsScriptType(coin, "p2sh")`

Test plan

  • `cargo test` — 452 passed, 0 failed
  • P2TR address encode/decode roundtrip via `pearl.json` fixture (regtest HRP `rprl`)
  • `test_all_networks` macro covers Pearl/PearlTestnet for PSBT deserialization
  • Address compatibility test updated: Pearl appears only in `taprootGroups`, not `segwitGroups` or `legacyGroups`
  • `output_script_support()` — legacy and segwit rejected, P2TR accepted
  • Fixture generation succeeds for Pearl (P2TR inputs/outputs only, MuSig2 enabled)
  • Webui TypeScript build passes (`Record<CoinName, string>` exhaustiveness satisfied)

References

🤖 Generated with Claude Code

@manojkumar138
manojkumar138 requested a review from a team as a code owner July 22, 2026 09:02
@linear-code

linear-code Bot commented Jul 22, 2026

Copy link
Copy Markdown

CECHO-1503

Comment thread packages/wasm-utxo/src/address/mod.rs Outdated
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use stable links (tags or git shas)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread packages/wasm-utxo/src/networks.rs Outdated
Zcash,
ZcashTestnet,

// https://github.com/pearl-research-labs/pearl/blob/master/chaincfg/params.go

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stable link

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@manojkumar138
manojkumar138 force-pushed the manojkumar138/cecho-1503-duplex-wasm-utxo branch 2 times, most recently from 898eded to 9b21001 Compare July 22, 2026 09:52

@OttoAllmendinger OttoAllmendinger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed, rewriting

@manojkumar138
manojkumar138 force-pushed the manojkumar138/cecho-1503-duplex-wasm-utxo branch from 9b21001 to c521159 Compare July 22, 2026 10:05

@OttoAllmendinger OttoAllmendinger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_network is 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 legacy flag is wired into supports_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

@manojkumar138
manojkumar138 force-pushed the manojkumar138/cecho-1503-duplex-wasm-utxo branch 3 times, most recently from fc8c4d8 to aabfc7d Compare July 22, 2026 10:59
@OttoAllmendinger
OttoAllmendinger self-requested a review July 22, 2026 11:05
@manojkumar138
manojkumar138 force-pushed the manojkumar138/cecho-1503-duplex-wasm-utxo branch from aabfc7d to dd9a549 Compare July 22, 2026 11:17
@manojkumar138

Copy link
Copy Markdown
Contributor Author

@claude review

const p2msScriptTypes = ["p2sh", "p2shP2wsh", "p2wsh"] as const;

const EXCLUDED_COINS: CoinName[] = ["bsv", "bcha"];
const EXCLUDED_COINS: CoinName[] = ["bsv", "bcha", "pearl"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@manojkumar138
manojkumar138 force-pushed the manojkumar138/cecho-1503-duplex-wasm-utxo branch from dd9a549 to 3b81958 Compare July 22, 2026 11:32
@manojkumar138
manojkumar138 merged commit b5675be into master Jul 22, 2026
13 checks passed
@manojkumar138
manojkumar138 deleted the manojkumar138/cecho-1503-duplex-wasm-utxo branch July 22, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants