Shrike 2.5.5-blake2b.10 - multisig opts in on a quorum
Shrike signing with the unified opt-in signature hash as Bitcoin Knots v29.4.1.knots20260508rc4 defines it, on upstream Sparrow 2.5.5.
Multisig
A multisig opts in once enough signers are marked to meet its threshold, rather than requiring every keystore. A 2-of-3 holding one signer whose firmware cannot opt in now works with the other two, where before it declined on every transaction and signed the legacy way.
The previous release needed every keystore marked, so the only way to get protection from a lagging cosigner's wallet was to mark it anyway, which told the wallet something false about it. That is no longer necessary.
Where some keystore is left out, the send screen says the transaction has to be signed by the marked signers. The others cannot produce the hash type it asks for, and a device that is marked but does not implement the opt-in signs nothing rather than falling back.
The protocol is more permissive still. SIGHASH_UNIFIED is opted into per signature, so one opted-in signature in a transaction is enough to make it unreplayable. Matching that would mean mixed hash types within an input, which a PSBT cannot express: it carries one hash type per input, and omitting it makes capable signers fall back to legacy.
Verified
Replay protection is now demonstrated rather than argued. A 2-of-2 spend this wallet signed with the opt-in, submitted to a node running the pre-fork rules:
allowed: False
reject-reason: mempool-script-verify-flag-failed (Signature opts in to the hardfork, which is not active here)
The same spend, same input and output, signed the legacy way, is accepted by the same node. So the refusal is caused by the opt-in and not by anything else about the transaction.
Reproducible: this commit built locally with Eclipse Temurin 25.0.2 produces an application tree in which all 171 paths hash identically to CI's, covering the .tar.gz and .zip contents rather than the installers.
Each behaviour above was checked by reverting the code that implements it and confirming the test covering it fails, then restoring.
335 wallet and 610 drongo unit tests, including a 2-of-3 that signs and finalises on two signatures with every signature carrying the opt-in.
Also fixed
A threshold that cannot be read no longer decides anything. The policy may be absent on a wallet still being built and throws on one it cannot parse, and this runs on the send path. Both cases now require every keystore rather than throwing or opting in on fewer signers than the wallet might need.
Downloads
| Platform | File |
|---|---|
| Windows | Shrike-2.5.5.msi, or .zip for a portable copy |
| macOS | Shrike-2.5.5-arm64-unsigned.dmg, or -x86_64-unsigned.dmg for Intel |
| Linux x86_64 | shrike_2.5.5-1_amd64.deb, or -x86_64.tar.gz |
| Linux aarch64 | shrike_2.5.5-1_arm64.deb, or -aarch64.tar.gz |
| Headless | the shrikeserver-* files |
Verify before running:
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMSSigned by Kyle Santiago kyle@privkey.io, key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38.
The macOS builds are not code signed or notarized, so macOS reports the app as damaged or from an unidentified developer on first launch. That means it is unsigned, not that the download is bad:
xattr -dr com.apple.quarantine /Applications/Shrike.app
Verify SHA256SUMS first, because clearing quarantine removes the check that would otherwise stop a tampered download. The Windows installer is not Authenticode signed either, and SmartScreen will warn accordingly.