Skip to content

Keep the signature that opts in when a quorum has more than it needs - #7

Open
kwsantiago wants to merge 2 commits into
masterfrom
keep-the-opted-in-signature
Open

Keep the signature that opts in when a quorum has more than it needs#7
kwsantiago wants to merge 2 commits into
masterfrom
keep-the-opted-in-signature

Conversation

@kwsantiago

Copy link
Copy Markdown

A 2 of 3 where every signer signs has one signature more than the threshold needs, so finalising chooses which two to keep. It chose by key order, so where the marked device key sorted last its opted-in signature was the one discarded, and the transaction went out carrying no replay protection having had it. The label was right about the result; the protection existed and the wallet dropped it.

It now keeps the ones that opt in. Only which signatures are kept changes, never their order, because CHECKMULTISIG requires them in the order of the keys. A signature is only preferred if it verifies under the key naming it, since both the bit and the name come out of the PSBT: matching by value alone let a copy filed under a second key take a slot whose key does not verify it, which does not spend at all.

Verified against a Bitcoin Knots regtest node for P2WSH, P2SH and P2SH-P2WSH: the opted-in signature is kept, the forked node mines the result, and a node that never scheduled the fork refuses it. Where nothing opts in it keeps exactly what key order kept, which is every multisig wallet that has never heard of this.

Based on #5, which adds the accessor it verifies with.

Taproot script path signatures were discarded at parse, so an input carrying only those looked exactly like an unsigned one, and they were lost on the way back out. They are kept as hex, so a combiner hands back what it was given.

A partial signature is verified against the key that names it, matched by curve point, rather than against every key the caller holds: an 11 of 15 input costs 11 checks instead of 165. The named key still has to be one the caller vouches for and the signature still has to verify under it. getVerifiedPartialSignatures keeps those pairs, since a signature does not carry the key that made it and compares by hash type and by r and s alone.

A public key in a PSBT is not validated at parse, so one that is not a point on the curve is refused rather than thrown past the caller.
@kwsantiago
kwsantiago force-pushed the keep-tap-script-signatures branch from eb526bc to efa39ed Compare September 6, 2026 00:50
@kwsantiago
kwsantiago force-pushed the keep-the-opted-in-signature branch from 02408b1 to 0d98d41 Compare September 6, 2026 00:50
@kwsantiago
kwsantiago changed the base branch from keep-tap-script-signatures to master September 6, 2026 00:59
@kwsantiago

Copy link
Copy Markdown
Author

Held back from the next release. The label is honest without this: a quorum that over-signs still reads "not replay protected", so nobody is misled, they simply do not gain protection they could have had. Against that, this changes multisig finalisation for every wallet, which is the largest regression surface of the three PRs and the least needed. It stays open for a release of its own with more soak time.

@kwsantiago
kwsantiago changed the base branch from master to keep-tap-script-signatures September 6, 2026 01:00
Base automatically changed from keep-tap-script-signatures to master September 6, 2026 01:17
@kwsantiago kwsantiago self-assigned this Sep 6, 2026
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.

1 participant