Skip to content

fix(abstract-substrate): remove double Ed25519 prefix in MPCv2 recovery - #9557

Merged
vibhavgo merged 1 commit into
masterfrom
fix/sdk-abstract-substrate/mpcv2-recovery
Aug 25, 2026
Merged

fix(abstract-substrate): remove double Ed25519 prefix in MPCv2 recovery#9557
vibhavgo merged 1 commit into
masterfrom
fix/sdk-abstract-substrate/mpcv2-recovery

Conversation

@vibhavgo

@vibhavgo vibhavgo commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes MPCv2 non-BitGo recovery for Substrate-based EDDSA coins (TAO, POLYX). addSubstrateRecoverySignature was double-prefixing the Ed25519 MultiSignature discriminant, corrupting the on-wire signature by one byte and causing the chain to reject the extrinsic with 1010: Bad signature.

Linear: WCI-1454

Root cause

addSubstrateRecoverySignature wrapped the raw 64-byte MPCv2 signature with 0x00 before calling txBuilder.addSignature:

const substrateSig = Buffer.concat([Buffer.from([ED25519_MULTI_SIGNATURE_PREFIX]), rawSig]);
txBuilder.addSignature({ pub }, substrateSig);

But Transaction.constructSignedPayload (called during build()) already prepends 0x00:

const edSignature = \`0x00\${signature.toString('hex')}\` as HexString;

Result: polkadot-js's MultiSignature decoder consumed 0x00 as the Ed25519 discriminant, then read the next 64 bytes as the signature — which were [0x00][R (32B)][first 31 bytes of sigma]. The last byte of sigma was dropped; the chain re-verified against the true 64-byte signature and rejected.

MPCv1 was unaffected because its branch already passed the raw 64-byte sig through untouched. sdk-coin-dot implements the same helper correctly (see dot.ts L744 — with a comment explicitly warning against double-prefixing).

Changes

  • modules/abstract-substrate/src/abstractSubstrateCoin.ts: MPCv2 branch of addSubstrateRecoverySignature now passes rawSig directly, mirroring MPCv1 and sdk-coin-dot. Removed the unused ED25519_MULTI_SIGNATURE_PREFIX constant. Updated the doc comment to explain the invariant.
  • modules/abstract-substrate/test/unit/abstractSubstrateCoin.ts: updated the MPCv2 unit test which previously pinned the buggy behavior (sig[0] === 0x00, sig.slice(1) === rawSig) — it now asserts sig.length === 64 and sig === rawSig.

Scope of impact

Coins that extend SubstrateCoin from @bitgo/abstract-substrate:

Coin Package Affected
TAO / TTAO sdk-coin-tao yes → fixed
POLYX / TPOLYX sdk-coin-polyx yes → fixed
DOT / TDOT sdk-coin-dot no — has its own addRecoverySignature that was already correct

Test Plan

  • Unit test updated and passes locally (yarn nyc mocha in modules/abstract-substrate).
  • End-to-end verified on Bittensor testnet (finney) via WRW → MPCv2 recovery → broadcast:
    • Status: Ready → Broadcast → InBlock → Finalized
    • Block 0x3c5605b939d2cc403211f0d32c88fe1bc4125e2632da4ffa4957eff41c8dcf06
  • Retest TAO MPCv2 recovery on staging with released package (tracked in WCI-1435).
  • Retest POLYX MPCv2 recovery on staging with released package.

Made with Cursor

addSubstrateRecoverySignature wrapped the raw 64-byte MPCv2 signature with 0x00.

Transaction.constructSignedPayload already prepends that discriminant.

The resulting on-wire signature was shifted by one byte, dropping the last byte of sigma.

The chain rejected the extrinsic with `1010: Bad signature`.

Fix: pass rawSig through untouched, mirroring MPCv1 and sdk-coin-dot.

Verified on Bittensor testnet (finney). Block hash below.

0x3c5605b939d2cc403211f0d32c88fe1bc4125e2632da4ffa4957eff41c8dcf06

Update the MPCv2 unit test which pinned the buggy behavior.

Ticket: WCI-1454
@vibhavgo
vibhavgo force-pushed the fix/sdk-abstract-substrate/mpcv2-recovery branch from 8e94603 to 06ec943 Compare August 25, 2026 07:56
@vibhavgo
vibhavgo marked this pull request as ready for review August 25, 2026 08:24
@vibhavgo
vibhavgo requested a review from a team as a code owner August 25, 2026 08:24
@vibhavgo
vibhavgo requested a review from Marzooqa August 25, 2026 08:24
@vibhavgo
vibhavgo merged commit 401493f into master Aug 25, 2026
25 checks passed
@linear-code

linear-code Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

WCI-1464

WCI-1454

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.

3 participants