IntersectMBO / IntersectMBO/evolution-sdk
Signing: key-hash governance voters are never added to required signers
- Lingua principale
- TypeScript
- Stelle
- 22
- Fork
- 30
- Merge medio
- 5h 29m
- PR unite (30g)
- 12
Descrizione
## 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.
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
Start in packages/evolution/src/sdk/client/internal/Signing.ts at computeRequiredKeyHashesSync and compare its certificate handling with the voting and proposal procedure fields. Then inspect packages/evolution/src/sdk/builders/operations/Vote.ts and run the signing regression scenario described in the issue. Done means a key-hash DRep vote causes signTx to include the wallet's stake-key vkey witness, while the test fails before and passes after the fix.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- typescript
- Ambito
- blockchain
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Tranquilla
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 68/100