IntersectMBO / IntersectMBO/evolution-sdk

Signing: key-hash governance voters are never added to required signers

Offen
#479 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
bug external-review
Vorherrschende Sprache
TypeScript
Sterne
22
Forks
30
Ø Merge
13 Std.
Gemergte PRs (30 T.)
14

Beschreibung

## Summary
`computeRequiredKeyHashesSync` derives the signing keys from inputs, withdrawals, and certificates, but never inspects `votingProcedures` (body key 19) or `proposalProcedures` (key 20). The tx builder's Vote operation likewise only tracks redeemers for *script* voters and never adds a key-hash voter to `requiredSigners`. So a governance vote cast by a key-hash DRep, constitutional-committee member, or stake pool is not signed by the wallet, and the node rejects the under-signed transaction. Fail closed: no fund loss and no unauthorized action (a vkey witness covers the whole body, so nothing is signed that the signer didn't already authorize). The SDK can build a vote it cannot sign.

## Affected
packages/evolution/src/sdk/client/internal/Signing.ts
- computeRequiredKeyHashesSync (L47-184): checks requiredSigners, nativeScripts, inputs, collateralInputs, withdrawals, certificates; no votingProcedures / proposalProcedures branch

packages/evolution/src/sdk/builders/operations/Vote.ts
- createVoteProgram: only tracks redeemers for script voters (isScriptVoter); key-hash voters are never added to state.requiredSigners

## Fix
In `computeRequiredKeyHashesSync`, when `tx.body.votingProcedures` is present, iterate the voters and add the wallet credential on a match, mirroring the existing certificate logic:
- DRepVoter with KeyHash drep -> match against stakeKhHex (same as RegDrepCert handling)
- ConstitutionalCommitteeVoter with KeyHash credential -> match against the wallet's committee credential (same as AuthCommitteeHotCert handling)
- StakePoolVoter -> match poolKeyHash against paymentKhHex (same as PoolRegistration/PoolRetirement handling)

Apply the equivalent for proposalProcedures.

## Regression test
- given: a transaction whose only wallet-relevant field is a votingProcedures entry for a key-hash DRep voter equal to the wallet's stake credential
- before fix: signTx returns an empty witness set (voter key not added)
- after fix: signTx adds the stake-key vkey witness
Must FAIL on main today and PASS after the fix.

## Reference
Reported informally (governance signing gap). The same report also claimed this enables "unauthorized voting"; that part does not hold, since a vkey witness signs the entire transaction body, so a vote riding along in a signed transaction is the ordinary review-before-signing consideration, not a separate escalation.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Beginne in packages/evolution/src/sdk/client/internal/Signing.ts bei computeRequiredKeyHashesSync und vergleiche die Zertifikatsbehandlung dort mit den Feldern für Abstimmungs- und Proposal-Verfahren. Untersuche anschließend packages/evolution/src/sdk/builders/operations/Vote.ts und führe das in der Issue beschriebene Signing-Regressionsszenario aus. Erledigt bedeutet, dass ein DRep-Votum mit key-hash dazu führt, dass signTx den stake-key-vkey-Witness der Wallet einschließt, während der Test vor der Behebung fehlschlägt und danach erfolgreich ist.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
blockchain
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Ruhig
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
68/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.