Releases: privkeyio/shrike
Release list
Shrike 2.5.5-blake2b.22 - only says replay protected when it checked
Everything in 2.5.5-blake2b.21, plus one change. Signing is unchanged.
Only says replay protected when it checked
The transaction view could read Replay protected for a transaction carrying none. Any 64 or 65 byte push decodes as a signature whose hash type is its own last byte, so a taproot control block, an uncompressed public key, or a signature a stranger added and finalising drops all counted as an opt-in.
It now counts an opt-in only where a signature verifies against a key this wallet derives, for an input whose spent output matches the script this wallet derives for it. Keys are never taken from the transaction file, since whoever wrote the file wrote those too. What could not be checked reads as not checked rather than as protected.
A transaction signed only by a taproot script path also read as unsigned, so the label repeated what the file declared about itself. Those signatures are read now.
This matters most if someone hands you a transaction to sign: they can add a signature of their own that opts in, and finalising drops it, so what broadcasts carries no protection while the label said it did.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project, nor by any hardware wallet manufacturer. Using it is entirely at your own risk, and you alone bear any loss of funds.
Verifying this release
If you already have Shrike installed, download SHA256SUMS, SHA256SUMS.asc and your install file into one folder, then drag any of them onto Shrike, or open Tools > Verify Download.
Otherwise, with gpg, adding privkeyio-signing-key.asc to that folder:
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
Look for Good signature from "Kyle Santiago <kyle@privkey.io>" on key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38, and OK for your file. The warning that the key is not certified is expected: it means only that you have not marked it trusted yourself.
Shrike 2.5.5-blake2b.21 - connects to a BLAKE2b Electrum server, and names itself
Everything in 2.5.5-blake2b.20, plus two changes. Signing is unchanged.
Connects to a BLAKE2b Electrum server
Since the BLAKE2b hardfork a header is 164 bytes and hashed differently, so the electrs build that indexes it declines any client below Electrum protocol 1.8. Shrike asked for 1.4.2 and was refused before a single header was fetched (#22). It now asks for 1.8.
Asking that high also changes what Fulcrum sends: at 1.6 a run of headers arrives as a list rather than one string. Both forms are read.
Names itself
Notifications, the name given to an Electrum server, and the Help links said Sparrow, which is a different project. They name this one now. The saved file format keeps its name, since that is what the files are.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project, nor by any hardware wallet manufacturer. Using it is entirely at your own risk, and you alone bear any loss of funds.
Verifying this release
If you already have Shrike installed, download SHA256SUMS, SHA256SUMS.asc and your install file into one folder, then drag any of them onto Shrike, or open Tools > Verify Download.
Otherwise, with gpg, adding privkeyio-signing-key.asc to that folder:
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
Look for Good signature from "Kyle Santiago <kyle@privkey.io>" on key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38, and OK for your file. The warning that the key is not certified is expected: it means only that you have not marked it trusted yourself.
The macOS builds are not notarized and the Windows installer is not Authenticode signed, so both warn on first run. Reproducible builds: see reproducible.md.
Shrike 2.5.5-blake2b.20 - updated colors, and the opt-in reads the verified chain
Everything in 2.5.5-blake2b.19, plus Shrike's own colors, corrected icons, and one hardening change to how the opt-in is decided. Signing itself is unchanged.
Opting in on a hardware device needs firmware that implements it. Builds for SeedSigner, Coldcard and Trezor are listed under hardware wallet firmware. An unmarked device still signs, the ordinary way.
Built on upstream Sparrow's 2.5.5 development line, which this release is level with. Upstream's newest release is 2.5.4; 2.5.5 is not released yet.
Updated colors
The interface was upstream's blue throughout, and is Shrike's red now, taken from the site, so the icon, the browser tab and the wallet agree. Colors that carry meaning keep it: the palettes behind the transaction fields and the charts, the network indicators, the server type switches, the syntax colors.
The application icons sit on a red ground, which a launcher needs since the desktop draws it over a background the wallet does not choose. macOS keeps a shaped icon with no ground, as its dock expects.
The opt-in reads the verified chain
Nothing authenticates the tip a server announces, and this decision used to be taken from it. A forged header at or past the activation height could bring the opt-in forward, and transactions signed under it would not verify.
The header store is re-verified from a pinned anchor, so where it has reached the announced height its answer is used instead. Where it is behind, the announcement still decides, because declining there would sign the legacy way, and a signature carrying no replay protection is the worse of the two failures. This is never less protective than before, and more once the store is level.
Also
The Linux packages name this project's maintainer, rather than the one the packaging was inherited from.
Verification
Twenty end to end checks against a Bitcoin Knots v29.4.1.knots20260508 regtest node, every transaction judged by the node rather than by an assertion in the harness. All twenty pass. Unit suites: 1041 tests, no failures.
Builds are reproducible: on a second machine with the same JDK, every file is byte-identical apart from five bytes in the bundled Java runtime that jlink itself varies.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project, nor by any hardware wallet manufacturer. Using it is entirely at your own risk, and you alone bear any loss of funds.
Verifying this release
If you already have Shrike installed, download SHA256SUMS, SHA256SUMS.asc and your install file into one folder, then drag any of them onto Shrike, or open Tools > Verify Download.
Otherwise, with gpg, adding privkeyio-signing-key.asc to that folder:
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
Look for Good signature from "Kyle Santiago <kyle@privkey.io>" on key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38, and OK for your file. The warning that the key is not certified is expected: it means only that you have not marked it trusted yourself.
The macOS builds are not notarized and the Windows installer is not Authenticode signed, so both warn on first run. Reproducible builds: see reproducible.md.
Shrike 2.5.5-blake2b.19 - superseded by blake2b.20
Superseded by blake2b.20. Nothing here is unsafe: .20 is this release with the interface in the fork's own colors, the application icons corrected, and the opt-in decision taken from the verified chain rather than the tip a server announces. The files below stay in place for anyone already on it, and the Trezor firmware requirement is the same for both.
Everything in 2.5.5-blake2b.18, plus upstream's latest fixes and sharper artwork. Nothing this fork does changes, and a Trezor still needs firmware unified-sighash.2 to opt in.
Built on upstream Sparrow's 2.5.5 development line, which this release is level with. Upstream's newest release is 2.5.4; 2.5.5 is not released yet.
From upstream
- The signature hash selection reverts when the
SIGHASH_NONEwarning is dismissed rather than answered no. - A Trezor Safe 7 session recovers when the device retransmits a message that went unacknowledged.
- An announced chain tip below the last pinned header is refused.
- A block height taken from the server reads as unverified until it is proven.
- An amount or fee that parses as zero when only part of it validates is corrected.
- Silent payment scan addresses are compared when deciding whether wallet addresses changed.
Sharper artwork
The application icons were an SVG wrapping a bitmap, so the wallet resampled a fixed-size image and they rendered soft, worst on HiDPI screens. They are vector now, and render at whatever resolution the display asks for.
Verification
Twenty end to end checks against a Bitcoin Knots v29.4.1.knots20260508 regtest node, every transaction judged by the node, on a private loopback so nothing else on the machine can answer as the device. All twenty pass. Unit suites: drongo 615, Sparrow 396, lark 22, no failures.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project, nor by Trezor, KeepKey or OneKey. Using it is entirely at your own risk, and you alone bear any loss of funds.
Verifying this release
If you already have Shrike installed, this is the easy way. Download three files into the same folder: SHA256SUMS, SHA256SUMS.asc, and the install file for your platform. Then drag any one of them onto Shrike, or open Tools > Verify Download. It checks the signature and the hash and tells you whether the file is ready to install.
Otherwise, with gpg. Download those three files plus privkeyio-signing-key.asc into the same folder, then:
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
The second command must report:
gpg: Good signature from "Kyle Santiago <kyle@privkey.io>"
gpg: using RSA key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38
It will also print WARNING: This key is not certified with a trusted signature. That is expected and does not mean the check failed: it says only that you have not marked the key as trusted on your own keyring. What matters is Good signature and that the key matches the fingerprint above.
The third command prints OK for the file you downloaded. Anything else, or a missing Good signature, means do not install it.
The macOS builds are not notarized and the Windows installer is not Authenticode signed, so both will warn on first run. Reproducible builds: see reproducible.md.
Shrike 2.5.5-blake2b.18 - superseded by blake2b.19
Superseded by blake2b.19. Nothing here is wrong: .19 is this release plus upstream's latest fixes and vector artwork in place of the soft bitmap icons. The files below stay in place for anyone already on it, and the Trezor firmware requirement is the same for both.
Shrike signing with the unified opt-in signature hash as Bitcoin Knots v29.4.1.knots20260508 defines it, on upstream Sparrow 2.5.5. Everything in 2.5.5-blake2b.16, plus the Trezor path.
This replaces 2.5.5-blake2b.17, whose Trezor path cannot opt in against current firmware.
If you do not use a Trezor
Nothing about signing changes, and nothing below applies to you. The one visible difference from .16 is the application icons, which are now independent artwork rather than upstream Sparrow's.
If you use a Trezor
Requires firmware unified-sighash.2 on the device.
A Trezor announces the opt-in by reporting a capability number. Upstream has since assigned 28 to Capability_Ethereum_EIP7702, so the firmware moved the unified sighash capability to 29 rather than leave two meanings on one number. .17 still looks for 28, so on firmware unified-sighash.2 it reads the capability as absent and refuses every opt-in, which is the one thing that release exists to do. This release looks for 29 only.
Shrike could already build a PSBT declaring hash type 0x21, but nothing carried that request to a Trezor: the protobuf had no field for it, the Trezor path never read the declared hash type, and every returned signature was stamped SIGHASH_ALL regardless of what the device had done. The request now reaches the device, and the hash type recorded on the signature is the one the device really used.
Three things are refused rather than signed, because the alternative is a transaction that looks protected and is not. Only a transaction that asks for the opt-in is affected; ordinary signing on any of these devices is unchanged.
- The device's firmware does not implement the opt-in. Checked before signing rather than discovered afterwards, because firmware without the field ignores it silently. KeepKey and OneKey Classic devices take this same path and will never report the capability, so they are refused here too, and the message names whichever device is in hand rather than always saying Trezor.
- Any unified hash type other than
0x21. Trezor signsSIGHASH_ALLand nothing else, so the other five have no counterpart to ask for. - An input the device cannot sign sitting alongside an opted-in one. The unified message commits to every input's script, and an unsignable input is handed a stand-in, which would corrupt every opted-in signature in the transaction.
After signing, the PSBT is re-parsed with verification, which a legacy-digest signature fails.
Verification
Twenty end to end checks against a Bitcoin Knots v29.4.1.knots20260508 regtest node, every transaction judged by the node rather than by an assertion in the harness: each script type opted in and mined carrying 0x21, the legacy controls at 0x01 and taproot 0x00, a 2-of-2 with the second key on the device, all six non-ALL unified types refused, and a quorum wallet producing one input carrying 0x01 and 0x21 side by side. All twenty pass. Unit suites: drongo 615, Sparrow 383, lark 3, no failures.
Firmware unified-sighash.2 builds all five models; these checks are against the Model One. The opt-in path is not model-specific, so the others take the same code, but were not exercised.
Builds are reproducible: on a second machine with the same JDK, every file is byte-identical apart from five bytes in the bundled Java runtime that jlink itself varies.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project, nor by Trezor, KeepKey or OneKey. Using it is entirely at your own risk, and you alone bear any loss of funds.
Verifying this release
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
Signed by Kyle Santiago kyle@privkey.io, key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38. The macOS builds are not notarized and the Windows installer is not Authenticode signed. Reproducible: see reproducible.md.
Shrike 2.5.5-blake2b.17 - superseded by blake2b.19
Superseded by blake2b.19. The unified sighash capability moved from 28 to 29 in firmware unified-sighash.2, and this build still looks for 28, so on that firmware it refuses every opt-in. The firmware release this one paired with has been withdrawn. If you installed this version, reflash to unified-sighash.2 and take .19. The files below are left in place for anyone already on it. A mismatch refuses to sign rather than producing a signature without the protection it claims.
Shrike signing with the unified opt-in signature hash as Bitcoin Knots v29.4.1.knots20260508 defines it, on upstream Sparrow 2.5.5. Everything in 2.5.5-blake2b.16, plus the Trezor path.
If you do not use a Trezor
Nothing changed in this release, and nothing below applies to you. It was the Trezor path only. Take .19 instead.
If you use a Trezor
Required Trezor Model One firmware 1.14.2-unified-sighash.1 on the device, which has since been withdrawn.
Shrike could already build a PSBT declaring hash type 0x21. Nothing carried that request to a Trezor. The protobuf had no field for it, the Trezor path never read the hash type the PSBT declared, and every signature that came back was stamped SIGHASH_ALL regardless of what the device had actually done.
So a device that implements the opt-in would have signed the legacy message and handed back a transaction the wallet labeled as replay protected. That is what this closes: the request reaches the device, and the hash type recorded on the signature is the one the device really used.
Each of these is refused rather than signed, because the alternative is a transaction that looks protected and is not. Only a transaction that asks for the opt-in is affected; ordinary signing on any of these devices is unchanged.
- The device's firmware does not implement the opt-in. Checked before signing rather than discovered afterwards, because firmware without the field ignores it silently. KeepKey and OneKey Classic devices take this same path and will never report the capability, so they are refused here too, and the message now names whichever device is in hand rather than always saying Trezor.
- Any unified hash type other than
0x21. Trezor signsSIGHASH_ALLand nothing else, so the other five have no counterpart to ask for. They are refused rather than quietly downgraded. - An input the device cannot sign sitting alongside an opted-in one. The unified message commits to every input's script, and an unsignable input is handed a stand-in, which would corrupt every opted-in signature in the transaction.
After signing, the PSBT is re-parsed with verification, which a legacy-digest signature fails.
Verification
Twenty end to end checks against a Bitcoin Knots v29.4.1.knots20260508 regtest node, every transaction judged by the node rather than by an assertion in the harness: each script type opted in and mined carrying 0x21, the legacy controls mined carrying 0x01 and taproot 0x00, a 2-of-2 with the second key on the device, all six non-ALL unified types refused, the wallet's own decision path across marked, unmarked and fork-inactive, and a quorum wallet producing one input carrying 0x01 and 0x21 side by side.
Refusal was verified against a stock Model One emulator, which is the case that matters: refused before signing, and ordinary signing on it still works.
The firmware has been flashed to a real Model One and used to sign a mainnet transaction with the opt-in confirmed present. That is one device and one signing session.
The lark change had three independent review passes. The first found that the original guard was tautological: it read the hash type off the returned signature, a field the wallet stamps itself, so stock firmware produced a transaction labeled 0x21 that was invalid under both rule sets.
Builds are reproducible: on a second machine with the same JDK, every file this project produces is byte-identical, the only difference being five bytes in the bundled Java runtime image that jlink itself varies.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project, nor by Trezor, KeepKey or OneKey. Using it is entirely at your own risk, and you alone bear any loss of funds.
Verifying this release
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
Signed by Kyle Santiago kyle@privkey.io, key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38. The macOS builds are not notarized and the Windows installer is not Authenticode signed. Reproducible: see reproducible.md.
Shrike 2.5.5-blake2b.16 - report the protection a transaction actually has
Shrike signing with the unified opt-in signature hash as Bitcoin Knots v29.4.1.knots20260508 defines it, on upstream Sparrow 2.5.5.
Everything in 2.5.5-blake2b.15, plus the correctness work below. This one is worth taking: four of the fixes are cases where the wallet could report replay protection a transaction did not have.
The transaction view could say protected when it was not
The status was computed when the transaction tab opened, before anything had signed, and never recomputed. Signing happens in that same tab. Where a quorum of cosigners cannot opt in, each is handed the base hash type, so a transaction that declared the opt-in can finish carrying none of it while the screen it is broadcast from still reads as replay protected. The status is now recomputed wherever signatures land.
A mixed witness could not be combined
One marked signer is enough, and an unmarked cosigner is handed the base type so it can sign alongside. Verification computed a single digest from the hash type the input declared and checked every signature against it, so the resulting witness was rejected outright. Each signature is now checked against the type it names, bounded to the types the input actually asks for.
Combining also overwrote the declared hash type with whatever came back. A reply declaring the base type left every signer that had not signed yet being asked for the legacy digest. Whether to opt in is this wallet's decision, taken from the chain it follows, and it now survives a combine in both directions: a cosigner can change the output type but not the opt-in.
Header validation required the proof of work the chain uses
A header decides for itself which proof of work its hash is taken with. Nothing checked that against the height, so a run of pre-fork headers claiming the eased target the activation height allows would satisfy the difficulty and proof of work rules while being mined with the old algorithm, at a target chosen for a network that has none of that hashrate. The header version is now required to match the height, in both directions.
Reporting
A conditional opt-in in a partially marked multisig read identically to a guarantee. It holds only if a signer that can opt in is among those that sign, and it now says so.
On an Electrum connection the multisig caveat was dropped entirely, because no Electrum server reports an activation height and only one caveat could be the headline. Both are now reported.
A server announcing a pre-fork tip at or past the activation height is named as contradicting the schedule rather than reported as the chain not having activated. Nothing authenticates that tip, so a server could otherwise hold the wallet at "not activated" indefinitely with every transaction it signed replayable.
Watch only keystores and signing
Watch only keystores can be marked, but the marking dialog listed hardware only and the send screen offered a remedy whose dialog opened empty. The private key sweep never opted in, the only signing path that did not.
Applying an unrelated change in wallet settings could write back a stale mark and silently unmark a keystore that had just been marked from the send screen.
Verification
998 unit tests. Nine end to end suites against a Bitcoin Knots v29.4.1.knots20260508 node, covering the opt-in before and after activation, a mixed multisig witness, a marked watch only wallet signed externally, and the Anyone Can Pay lift. Header validation is checked against the real mainnet chain across its activation at 961640 and against 173 testnet4 headers across its own at 150308, anchored to values this project did not produce. The fixes above are mutation checked: reverting each one fails specific tests.
Verifying this release
gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
Signed by Kyle Santiago kyle@privkey.io, key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38. The macOS builds are not notarized and the Windows installer is not Authenticode signed. Reproducible: see reproducible.md.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project. Using it is entirely at your own risk, and you alone bear any loss of funds.
Shrike 2.5.5-blake2b.15 - superseded by blake2b.16
Superseded by blake2b.16. Later releases add: report the protection a transaction actually has.
Shrike signing with the unified opt-in signature hash as Bitcoin Knots v29.4.1.knots20260508 defines it, on upstream Sparrow 2.5.5.
Everything in 2.5.5-blake2b.14, plus the release-integrity work below. Nothing a user does changes, so there is no reason to hurry this one if you are already on .14.
Releases cannot ship an incomplete manifest
SHA256SUMS covers every file in a release, and it is what tells you a download was not tampered with. The job that writes it runs even when a build has failed, so that one platform failing does not skip the checksums for the rest. That also meant it would write a manifest for whatever arrived and upload it.
It nearly shipped twice. A Windows build failed and the manifest lost the .msi and .zip; a macOS build failed and it lost the arm64 .dmg. Both were caught by hand, by comparing the manifest against the artifacts before publishing. Anyone on the missing platform would have had a download with no line to check it against.
The manifest is now verified against the set of files a release carries, and the job refuses to upload a short one. It has already caught a real occurrence: a macOS build failed on a transient packaging error, and the job stopped rather than publishing eleven entries where there should be twelve.
The macOS packaging step also retries when hdiutil reports the volume busy, which is the transient behind both of those, so a release is less likely to need a re-run at all.
One chain
Bitcoin hardforked. Describing software that has not adopted the fork as following a separate chain frames it as a different coin, which it is not. The wallet now says what it means throughout, including on the send screen where a signature that can be lifted out is described as spendable against nodes that have not adopted the fork.
Verified
368 wallet and 611 drongo unit tests, nine end to end suites, and the manifest check pinned against six manifests including the short one the failed macOS run actually produced.
Reproducible: this commit built locally with Eclipse Temurin 25.0.2 produces an application tree whose 171 paths, every file and symlink, hash identically to the tree CI published in shrike-2.5.5-x86_64.tar.gz. Only the Linux x86_64 build was reproduced; the archive contents are compared rather than the installers.
Upgrading
From .12 onward the Debian revision carries the release number, so apt can order releases. Coming from .11 or earlier this still needs dpkg:
sudo dpkg -i shrike_2.5.5-15_amd64.deb
/opt/shrike/bin/Shrike --version # expect Shrike 2.5.5-blake2b.15Wallets and configuration in ~/.shrike are untouched.
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-15_amd64.deb, or -x86_64.tar.gz |
| Linux aarch64 | shrike_2.5.5-15_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 from an unidentified developer on first launch:
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.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project. Using it is entirely at your own risk, and you alone bear any loss of funds.
Shrike 2.5.5-blake2b.14 - superseded by blake2b.16
Superseded by blake2b.16. Later releases add: a release cannot ship an incomplete manifest; report the protection a transaction actually has.
Shrike signing with the unified opt-in signature hash as Bitcoin Knots v29.4.1.knots20260508rc4 defines it, on upstream Sparrow 2.5.5.
Everything in 2.5.5-blake2b.13, plus the macOS fix below. If you are on macOS, take this one.
macOS: the app would not open
Double clicking Shrike reported that it "may be damaged or incomplete", and it launched only by running the binary inside the bundle directly. Reported by a user, and confirmed by reading the plist out of the published dmg.
The bundle named upstream's executable:
CFBundleExecutable = Sparrow Finder runs this
Contents/MacOS/ contains: Shrike what actually ships
Finder looked for a file that is not there and called the app damaged. jpackage copies this plist verbatim from the resource directory, so it overrode the application name the build otherwise sets.
Two more things in the same file were upstream's:
CFBundleIconFilenamedSparrow.icnswhile the bundle shipsShrike.icns, so the icon was wrong too.CFBundleIdentifierand thebitcoin:,auth47:andlightning:handlers all claimedcom.sparrowwallet.sparrow. Two bundles claiming one identifier leaves macOS to choose between this and an installed Sparrow. The identifier is nowio.privkey.shrike.
This was not caused by having Sparrow installed, and it happened on a Mac without it. If you edited your own Info.plist as a workaround, this build needs no edit.
Confirmed in the artifact rather than the source tree: the published dmg now reads CFBundleExecutable Shrike against a bundle shipping MacOS/Shrike.
Verified
368 wallet and 611 drongo unit tests, nine end to end suites, each behaviour checked by reverting the code that implements it and confirming the covering test fails.
Reproducible: this commit built locally with Eclipse Temurin 25.0.2 produces an application tree whose 171 paths, every file and symlink, hash identically to the tree CI published in shrike-2.5.5-x86_64.tar.gz. Only the Linux x86_64 build was reproduced; the archive contents are compared rather than the installers.
Upgrading
.7 through .11 all declared Debian version 2.5.5-1, so apt compared them as equal. From .12 the revision carries the release number. Coming from .11 or earlier this still needs dpkg:
sudo dpkg -i shrike_2.5.5-14_amd64.deb
/opt/shrike/bin/Shrike --version # expect Shrike 2.5.5-blake2b.14Wallets and configuration in ~/.shrike are untouched.
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-14_amd64.deb, or -x86_64.tar.gz |
| Linux aarch64 | shrike_2.5.5-14_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 still reports the app as from an unidentified developer on first launch. That is the signing warning, not the damaged-bundle failure fixed above:
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.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project. Using it is entirely at your own risk, and you alone bear any loss of funds.
Shrike 2.5.5-blake2b.13 - only services that adopted the fork, and watch only wallets opt in
Shrike signing with the unified opt-in signature hash as Bitcoin Knots v29.4.1.knots20260508rc4 defines it, on upstream Sparrow 2.5.5.
Only services that have adopted the fork are offered
Shrike follows the fork, but it was still shipping services that have not adopted it. Past the activation height such a service holds neither this chain's blocks nor its mempool, so it does not merely lag: it answers about somewhere else.
Transaction broadcast is the one that mattered. With a Tor proxy configured, that path replaces the connected node rather than supplementing it, and every source it could use, blockstream.info, mempool.space and mempool.emzy.de alike, had not adopted the fork. An opted-in transaction is refused there, but a legacy one relays, which is the replay this wallet exists to prevent.
Fee rates were quietly wrong. Seven places fell back to mempool.space when no source had been chosen, which is the state a new install starts in. Two of them are the fee estimates, so an unconfigured wallet priced transactions against a mempool it never broadcasts into. Nobody reported it, because a wrong fee looks like a fee.
Public Electrum servers are withdrawn entirely. None of them have adopted the fork, and connecting to one shows blocks and balances that diverge from these past the activation height, which is the worst of these failures rather than the mildest. A config that named one from before is corrected when it is read, because the connection is made at startup, long before a settings screen could intervene. Connect a Knots node, or your own Electrum server indexing one.
Fee rates, block explorer links and broadcast now use mempool.guide, which runs the same API on this chain. Exchange rates still offer mempool.space, deliberately: that is a fiat price feed carrying no chain data, and mempool.guide's price endpoint returns nothing.
The update check is gone rather than disabled. Its only feed is Sparrow's, signed with Sparrow's key, and the status bar link it drove read "Sparrow x.y.z available" pointing at sparrowwallet.com/download. It could only ever advertise the wallet that has not adopted the fork.
A watch only wallet can opt in
The Replay protection control was drawn only for hardware keystores, so a watch only wallet signed by a patched device could never opt in, and the remedy offered was to re-import it as an airgapped wallet: rebuild your wallet to change one boolean.
The reasoning was that such a keystore signs nothing, so marking it changes nothing. True of this wallet signing and beside the point. The wallet is not deciding what it signs; it is deciding which hash type to declare in a PSBT it hands to something else, which is exactly what a marked airgapped keystore does. It cannot verify either claim, and the owner is the only one who knows.
The control is now drawn for a watch only keystore too, naming the signer rather than a device. It stays off by default and is never inferred: a signer that does not understand 0x21 may sign the legacy message against a PSBT declaring the new one and produce a signature invalid under both rule sets. A mark that turns out to be wrong is not believed either, because the send screen counts what was actually signed rather than repeating the declaration back.
A payment code keystore went the other way. It holds a BIP47 extended private key and signs in process like a software seed, so it needs no mark. It was being refused one, which meant BIP47 child wallets never opted in at all.
Upgrading
.7 through .11 all declared Debian version 2.5.5-1, so apt compared them as equal and reported no upgrade. From .12 the revision carries the release number. If you are on .11 or earlier, this one still needs dpkg:
sudo dpkg -i shrike_2.5.5-13_amd64.deb
/opt/shrike/bin/Shrike --version # expect Shrike 2.5.5-blake2b.13Wallets and configuration in ~/.shrike are untouched.
Verified
A wallet holding no key at all, proven against nodes. Both chains are built from one shared history so the same coins exist on each:
1. marked watch only wallet declared All + Unified, signed 0x21
by a wallet holding no key
2. post-fork node accepted and mined it
3. pre-fork node rejected:
mempool-script-verify-flag-failed
(Signature opts in to the hardfork, which is not active here)
4. the same wallet left unmarked declared All, signed 0x01,
and the pre-fork node accepted it
Step 4 is the control: the mark is the only difference between a spend that cannot be replayed and one that can.
The terminal and the headless shrikeserver are driven through a pty and read back, which they were not before. That check exists because withdrawing public servers guarded the graphical screen but not the terminal's own, whose dialog reads the server list by index and would have thrown on an empty one.
Each behavior above was checked by reverting the code that implements it and confirming the test covering it fails, then restoring. 364 wallet and 611 drongo unit tests, nine end to end suites.
Reproducible: this commit built locally with Eclipse Temurin 25.0.2 produces an application tree whose 171 paths, every file and symlink, hash identically to the tree CI published in shrike-2.5.5-x86_64.tar.gz. Only the Linux x86_64 build was reproduced; the archive contents are compared rather than the installers.
Also fixed
Verifying a download named the wrong signer. The first user id on a key was taken with no check, so a key that has rotated an address showed the old one. Verifying a Shrike release reported a revoked address rather than the one the release names, which reads as tampering. The verifier also looked for Sparrow's release and manifest filenames, so picking a downloaded release never found its signature beside it.
The welcome flow no longer offers a connection this build cannot make. It is Introduction, Bitcoin Knots node, private Electrum server, each demonstrating a state it can actually reach. The terminal titles itself Shrike rather than Sparrow.
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-13_amd64.deb, or -x86_64.tar.gz |
| Linux aarch64 | shrike_2.5.5-13_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.
No warranty
This is unofficial, unaudited software provided as is, with no warranty and no liability, under the same Apache 2.0 license it inherits. It is not a Sparrow release and is neither affiliated with nor supported by the Sparrow project. Using it is entirely at your own risk, and you alone bear any loss of funds.