feat(ows-signer): add Cardano chain support (CIP-1852, Ed25519-BIP32, bech32) - #186
feat(ows-signer): add Cardano chain support (CIP-1852, Ed25519-BIP32, bech32)#186adacapo21 wants to merge 9 commits into
Conversation
|
@adacapo21 is attempting to deploy a commit to the MoonPay Team on Vercel. A member of the Team first needs to authorize it. |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
0288f2c to
899ae8e
Compare
… bech32) - Add Cardano variant to ChainType enum in ows-core - Implement CardanoSigner with CIP-1852 HD derivation (m/1852'/1815'/0'/0/0) - Enterprise address encoding: bech32 with blake2b-224 payment key hash - Transaction signing: blake2b-256(tx_body) signed with ed25519-bip32 - CBOR witness set injection via ciborium - Support cardano:mainnet, cardano:preprod, cardano:preview CAIP-2 identifiers - Tests: address derivation from known vectors, message signing, tx signing
- Implement broadcast_cardano() using Koios submittx endpoint (POST /submittx, Content-Type: application/cbor, no API key required) - Add default RPC endpoints for cardano:mainnet, cardano:preprod, cardano:preview - Wire Cardano into the broadcast() dispatcher - ows sign send-tx --chain cardano now works end-to-end
0cf1b8b to
87b9446
Compare
…_bip32 key Loading a wallet created before Cardano support silently substituted an all-zero 64-byte key for the missing ed25519_bip32 field. Any Cardano address derived from it would be identical across all legacy wallets and publicly predictable, so funds sent there could be stolen by anyone. The missing key is now kept empty: account derivation skips Cardano for such wallets, and explicit Cardano operations fail with an error telling the user to re-import the wallet. Adds a regression test.
de97e4f to
8bfa8f5
Compare
|
@njdawn this is ready for another look: rebased onto latest |
- reward_address and derive_child_soft now build the XPrv through the shared clamping helper, matching the signing path so a malformed extended key can neither panic nor derive an inconsistent stake address. All raw-byte XPrv construction goes through one helper. - import_wallet_private_key no longer silently ignores a getrandom failure for the ed25519 fallback key; RNG errors now abort the import like every other key-generation call in the function.
BIP32-Ed25519 child derivation is keyed by the chain code; deriving with a hardcoded zero chain code makes sibling public keys enumerable from a single exposed public key, breaking the HD wallet privacy guarantee. The function had no callers — real path derivation happens in HdDeriver, which threads the proper chain code — so the unsound public API is removed rather than patched.
|
Hi, We are the WingRiders team, and we are currently developing the official Cardano support for OWS in cooperation with IOG. Our implementation is almost complete, and we are addressing the final review comments before it is ready to be merged. Compared with our implementation, this PR currently appears to have several gaps:
Since our implementation is already close to completion and covers these areas, we kindly ask that you do not move forward with this PR to avoid duplicating work and introducing two competing implementations. You can follow our work here: |
|
Hi @TechRiderWR, thanks for the technical feedback — I'm Aggelos leading engineer of Indigo Protocol. Concrete points like these are genuinely useful, and inline review comments on this PR are the right place for them. That said, I'd ask that we respect the open contribution process here. This PR has been open since April 4th — nearly four months — publicly visible, referenced in #222 as the reference Cardano implementation, and actively maintained. On the substance: everything you list — base addresses, stake-key signing, CIP-8 Having looked at your fork's PR series, that split is already visible in your own structure: [Cardano 1] (cryptography) and [Cardano 2] (register chain) cover roughly the same ground as this PR — the same Icarus/CIP-3 entropy-based derivation and the same CIP-1852 paths — while [Cardano 3] through [Cardano 7] (signing extensions, policy engine, balance fetching, Blockfrost, docs/bindings) are precisely the additive follow-up layers described above. Rebasing those onto this merged foundation would avoid duplicating the base and get your feature work upstream faster. @njdawn An open four-month-old PR should be reviewed on its merits. |
- sign_message now prepends a domain-separation prefix, so a signed message can never be byte-identical to a blake2b-256 transaction hash and message signatures are structurally unusable as transaction witnesses. Full CIP-8/COSE_Sign1 enveloping is left as a follow-up. - import_wallet_private_key no longer fabricates a random ed25519_bip32 key for secp256k1/ed25519 imports. Such a key has no derivation relationship to any user-held secret, so ADA sent to its address would be unrecoverable if the vault were lost. Cardano accounts are now simply skipped for these wallets (same path as legacy wallets).
… compatibility The previous root key construction hashed the BIP-39 seed, which is deterministic but derives different addresses than mainstream Cardano wallets. Cardano software wallets (Daedalus/Shelley, Yoroi, Eternl, Lucid) use the Icarus master key generation from CIP-3: PBKDF2-HMAC- SHA512 keyed on the mnemonic entropy (4096 iterations, 96-byte output). - Mnemonic gains to_entropy(), recovering the BIP-39 entropy bits - Ed25519Bip32 derivation now runs Icarus from entropy + passphrase; deriving Cardano keys from a bare seed is refused, since entropy cannot be recovered from the seed - Verified against the official CIP-3 Icarus test vectors (master key with and without passphrase) - End-to-end vectors cross-checked against @emurgo/cardano-serialization-lib: payment/enterprise and reward addresses now match byte-for-byte on mainnet and testnet for two mnemonics A mnemonic imported into OWS now yields the same Cardano addresses as any standard wallet, and vice versa.
|
Following up on the derivation-compatibility point raised above, since it's the only item on that list that concerns correctness rather than scope: as of 3a5210e it is settled, verifiably. Key derivation now uses the Icarus master key generation from CIP-3 — the scheme used by Daedalus (Shelley), Yoroi, Eternl, and Lucid — with CIP-1852 paths on top. Two layers of proof are in the test suite, reproducible by anyone:
A mnemonic imported into OWS yields the same Cardano addresses as any mainstream wallet, and vice versa. The remaining items (base addresses, stake-key transaction signing, CIP-8 COSE enveloping for |
Adds --proto/--proto-redir '-all,http,https' so a hostile rpc_url cannot route the spawned curl to non-HTTP schemes (file://, ftp://, dict://, ...), including via redirects. Spawning curl itself matches the existing broadcast convention (curl_post_json) used by every other chain.
Summary
ChainType::Cardanotoows-corewith CAIP-2 identifierscardano:mainnet,cardano:preprod,cardano:previewCardanoSignerusing CIP-1852 HD derivation (m/1852'/1815'/account'/0/index) viaed25519-bip32addr/addr_testHRP and blake2b-224 payment key hashciboriumCurve::Ed25519Bip32variant (64-byte extended keys) and updatesKeyPairinows-libm/1852'/1815'/0'/0/0Known limitations
Root key derivation uses the BIP-39 seed (PBKDF2 output) via HMAC-SHA512, not Icarus-style entropy-based derivation. Derived addresses are internally consistent and deterministic but will not match addresses generated by Lucid Evolution / Eternl (which use the Byron/Icarus root key from raw entropy).
Test plan
cargo test -p ows-signer— all Cardano unit tests pass (address format, signing roundtrip, CBOR tx sign, blake2b vectors, staking path)cargo test -p ows-core—test_parse_chain_cardano,test_serde_all_variants,test_all_chain_typespasscargo test -p ows-lib— all import/sign tests pass including Cardanocargo test --workspace— 540 tests pass, 0 failurescargo clippy --workspace -- -D warnings— no warningscargo fmt --all --check— no formatting issues