Skip to content

feat(sdk-coin-flrp): enhance txn verification for atomic transactions#8821

Merged
mohd-kashif merged 1 commit into
masterfrom
CECHO-1140
May 21, 2026
Merged

feat(sdk-coin-flrp): enhance txn verification for atomic transactions#8821
mohd-kashif merged 1 commit into
masterfrom
CECHO-1140

Conversation

@mohd-kashif
Copy link
Copy Markdown
Contributor

@mohd-kashif mohd-kashif commented May 20, 2026

fix(sdk-core): fix FLRP MPCv2 verifyTransaction and hash bypass for Avalanche atomic transactions

Ticket: CECHO-1140

Problem

FLRP (Flare P-chain) MPCv2 cross-chain atomic transactions fail during TSS signing with:

failed to sign transaction Error: Invalid transaction: Transaction type not supported

Root cause — two bugs in ecdsaMPCv2.ts signRequestBase:

  1. Bug 1 — verifyTransaction receives unparseable signableHex: For Avalanche atomic transactions, signableHex is a 32-byte SHA-256 digest (SHA-256(txBody)), not the actual PVM transaction bytes.
    signRequestBase was passing signableHex as txHex to verifyTransaction, which tried to parse it as a PVM transaction and failed with "Transaction type not supported".

  2. Bug 2 — signRequestBase double-hashes the signing payload: signRequestBase applies keccak256 to the signableHex buffer before passing it to the DKLS signer. For Avalanche atomic txs, signableHex is
    already SHA-256(txBody) — the final signing hash. Applying keccak256 on top produces keccak256(SHA-256(txBody)), which doesn't match the HSM/BitGo party that uses SHA-256(txBody) directly. The two DKLS
    parties disagree on the message hash, producing an invalid combined signature.

Fix

Bug 1: Detect Avalanche atomic transactions via serializedTxHex.startsWith('0000') (Avalanche codec type ID prefix; EVM RLP starts with 0xf8xx so no collision). When detected, pass serializedTxHex
(full parseable PVM bytes) to verifyTransaction instead of signableHex. This follows the existing ICP pattern already in the code.

Bug 2: When serializedTxHex starts with '0000', skip keccak256 and use the signableHex buffer directly as the 32-byte DKLS message hash. This matches the existing fix in
getHashStringAndDerivationPath (external signer path) and the WP/HSM BitGo-party behaviour (MPCv2Signer.isPreHashed).

Detection mechanism

Avalanche atomic tx: serializedTxHex starts with '0000' (codec type ID)
Standard EVM tx: serializedTxHex starts with 'f8' (RLP encoding)

The WP explicitly strips the 0x prefix before storing serializedTxHex (see flrp.ts:1369 and flr.ts:1145), so the check is against bare hex.

Sandbox verification

Both fixes verified against real Coston2 testnet transactions:

Direction Sandbox script Export TX ID
C→P c2pMpcToMpcTss.ts 2Z5ELShnmmMgvTeupzLQzEKtAgbvZkDvq6KRYqbzVgcyBGVGpb
P→C p2cMpcToMpcTss.ts 2tDQmQUtDMyVWe8Bo36yHXykV2RMvh8rft3to5QsgoNhATMDXz

Key sandbox values used in test assertions:

  • Threshold: 1 (MPC single-sig, no hop transaction)
  • signablePayload: 32 bytes (SHA-256 digest)
  • serializedTxHex: starts with 0000 (Avalanche codec prefix)
  • Signature format: recid:R:S:pubkey with R/S each 32 bytes, recovery ∈ {0, 1}

Changes

File Change
modules/sdk-core/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.ts Bug 6: pass serializedTxHex to verifyTransaction for Avalanche atomic txs. Bug 7: skip keccak256 for pre-hashed signableHex.
modules/sdk-core/test/unit/bitgo/utils/tss/ecdsa/ecdsaMPCv2.ts +156 lines: full 4-round DKLS signing test with Avalanche atomic fixture; signRequestBase hash bypass tests for both Avalanche (skip keccak)
and EVM (apply keccak); keccak256 negative test on regular EVM tx.
modules/sdk-coin-flrp/test/unit/flrp.ts +89 lines: TSS verifyTransaction tests for all 3 cross-chain types (ExportInP, ImportInP, ImportInC); signablePayload SHA-256 length/codec-prefix assertions;
SHA-256 hash rejection test.

Test results

sdk-coin-flrp: 353 passing
ecdsaMPCv2: 7 passing

@mohd-kashif mohd-kashif requested review from a team as code owners May 20, 2026 20:17
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 20, 2026

CECHO-1140

@mohd-kashif mohd-kashif self-assigned this May 20, 2026
@mohd-kashif mohd-kashif merged commit ab22209 into master May 21, 2026
22 checks passed
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