feat: implement BIP-340 Schnorr signing for secp256k1 - #545
Merged
Conversation
✅ Heimdall Review Status
|
Revert the manual rename of SchnorrBip340 back to SCHNORR_BIP340 in types/signature_type.go (auto-generated by OpenAPI Generator from spec which produces SCREAMING_SNAKE_CASE). Update all call-sites in asserter and keys packages accordingly. Run golines to reformat long lines so check-gen passes. Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
- Rename types.SCHNORR_BIP340 → types.SchnorrBip340 throughout asserter/ and keys/ to match the PascalCase rename in types/v1.7.2 - Bump go.mod to github.com/coinbase/rosetta-sdk-go/types v1.7.2 - Add explicit 32-byte length check in SchnorrBip340 Sign(): BIP-340 requires the message to be exactly 32 bytes; return a clear error rather than letting btcec fail silently - Add TestSchnorrBip340_SignNegative covering wrong-length inputs Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
jiayupu-cb
force-pushed
the
jiayu/feat-schnorr-bip340
branch
from
June 23, 2026 22:16
b8c5001 to
3bacb06
Compare
xiaying-peng
approved these changes
Jun 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes # .
Note on file count
99 of the 106 changed files are mechanical copyright-year updates (
2025 → 2026) acrosstypes/,client/, andserver/. These are auto-generated files —make check-genrunsaddlicenseinside Docker and stamps all regenerated files with the current year, so any PR opened in 2026 would include this diff. This is a pre-existing repo-wide issue that will be addressed separately.Files worth reviewing:
keys/signer_secp256k1.gokeys/signer_secp256k1_test.goasserter/construction.goasserter/construction_test.gogo.mod/go.sumMotivation
SchnorrBip340("schnorr_bip340") was already defined as aSignatureTypeconstant in the types module but was never implemented —
Sign()andVerify()both returned
ErrSignUnsupportedSignatureType. This PR completes theimplementation so callers can actually use BIP-340 Schnorr signatures (used by
Bitcoin Taproot key-path spending) through the Mesh SDK.
Solution
keys/signer_secp256k1.go— ImplementSignandVerifyfortypes.SchnorrBip340usinggithub.com/btcsuite/btcd/btcec/v2/schnorr, whichis a spec-compliant BIP-340 implementation:
Sign: validates the message is exactly 32 bytes (BIP-340 requirement), thencalls
schnorr.Sign(privKey, msg)— handles key-parity negation and tagged-hashnonce derivation internally. Returns 64 bytes (
bytes(R.x) || bytes(s)).Verify: parses the 33-byte compressed public key viabtcec.ParsePubKey,then verifies with
schnorr.Signature.Verify, which lifts the key to itseven-Y form per the BIP-340 spec.
asserter/construction.go— Addtypes.SchnorrBip340to theSignatureType()allowed-list so the asserter accepts it in payloads andreturned signatures.
go.mod— Bumpgithub.com/coinbase/rosetta-sdk-go/typesfromv1.7.1to
v1.7.2, which renames the constant fromSCHNORR_BIP340toSchnorrBip340for PascalCase consistency (see PR #546).
Tests added:
TestSignSecp256k1: sign withSchnorrBip340, assert 64-byte output.TestVerifySecp256k1: BIP-340 round-trip (sign → verify).TestSchnorrBip340_Bip341KeyPathVector: uses a tweaked private key and sighashfrom the BIP-341 wallet test vectors (
keyPathSpending[0],txinIndex=4,hashType=0 / SIGHASH_DEFAULT). Checks (1) that ourSignproduces a valid64-byte signature that self-verifies, and (2) that our
Verifyaccepts thespec's expected witness bytes — confirming interoperability with external
BIP-340 implementations.
TestSchnorrBip340_VerifyNegative: rejects garbage signature bytes, asignature over the wrong message, and a signature verified against the wrong
public key.
TestSchnorrBip340_SignNegative: rejects messages that are not exactly 32bytes (5, 31, 33, 64 bytes tested).
asserter/construction_test.go: explicit asserter test case fortypes.SchnorrBip340inTestSigningPayload.Open questions
None.