feat(wallet): sr25519 signing standard#270
Conversation
Adds Polkadot/Substrate-compatible Sr25519 (Schnorr on Ristretto255)
📝 WalkthroughWalkthroughThis pull request adds comprehensive SR25519 (Schnorr on Ristretto255) signature support to the workspace. It introduces a new ChangesSR25519 Signature Support
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
crates/crypto/src/public_key.rs (1)
100-112: ⚡ Quick winLock the sr25519 implicit-account mapping down with a test vector.
This branch introduces a new externally visible address-derivation rule, but the test table below still has no
sr25519case. Please add at least one fixedto_implicit_account_idassertion for ansr25519:key so the"sr25519"prefix and hash slice stay stable.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/crypto/src/public_key.rs` around lines 100 - 112, Add a test vector asserting the new sr25519 implicit-account mapping so the "sr25519" prefix and keccak slice remain stable: locate the unit tests that assert to_implicit_account_id (the table of test cases used for other curve variants) and add at least one entry that constructs a PublicKey::Sr25519 with a fixed byte sequence and asserts its to_implicit_account_id equals the expected "0x..." hex string computed from keccak256([b"sr25519", pk].concat())[12..32]; reference the PublicKey::Sr25519 enum variant and the to_implicit_account_id behavior in the assertion.crates/crypto/src/signature.rs (1)
113-114: ⚡ Quick winAdd sr25519 parser regression cases.
The new
CurveType::Sr25519branch is not covered by theparse_ok/parse_invalid_lengthrstests below, so this path is easier to break than the existing curves.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/crypto/src/signature.rs` around lines 113 - 114, The new CurveType::Sr25519 branch (in signature.rs) lacks rstest coverage; add regression tests mirroring the existing parse_ok and parse_invalid_length cases for other curves to exercise checked_base58_decode_array and the CurveType::Sr25519 mapping. Create a parse_ok test entry with a valid sr25519 base58 string that decodes to the expected byte array mapped to CurveType::Sr25519, and a parse_invalid_length entry with a base58 string of wrong length to assert the parser rejects it; follow the same test names/structure used for the other curves so checked_base58_decode_array and the CurveType::Sr25519 branch are exercised.crates/signatures/sr25519/src/lib.rs (1)
53-67: ⚡ Quick winAdd a JSON round-trip test for the proof shape.
The wallet consumes this type over JSON, but the tests only construct it in Rust. A serde fixture here would lock down
flattenplusAsCurve<Sr25519>and catch wire-format regressions early.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/signatures/sr25519/src/lib.rs` around lines 53 - 67, Add a serde JSON round-trip test for the SignedSr25519Payload shape to ensure flatten + AsCurve<Sr25519> wire format stays stable: write a unit test that constructs a SignedSr25519Payload (using Sr25519 keypair/signature utilities from this crate), serialize it to JSON, compare against a checked-in JSON fixture (or write and then deserialize the fixture), then deserialize back and assert equality with the original; place the test near other sr25519 tests and reference the SignedSr25519Payload type, the payload field, public_key and signature fields to validate the flattened structure is preserved across serialization and deserialization.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/crypto/src/public_key.rs`:
- Around line 100-112: Add a test vector asserting the new sr25519
implicit-account mapping so the "sr25519" prefix and keccak slice remain stable:
locate the unit tests that assert to_implicit_account_id (the table of test
cases used for other curve variants) and add at least one entry that constructs
a PublicKey::Sr25519 with a fixed byte sequence and asserts its
to_implicit_account_id equals the expected "0x..." hex string computed from
keccak256([b"sr25519", pk].concat())[12..32]; reference the PublicKey::Sr25519
enum variant and the to_implicit_account_id behavior in the assertion.
In `@crates/crypto/src/signature.rs`:
- Around line 113-114: The new CurveType::Sr25519 branch (in signature.rs) lacks
rstest coverage; add regression tests mirroring the existing parse_ok and
parse_invalid_length cases for other curves to exercise
checked_base58_decode_array and the CurveType::Sr25519 mapping. Create a
parse_ok test entry with a valid sr25519 base58 string that decodes to the
expected byte array mapped to CurveType::Sr25519, and a parse_invalid_length
entry with a base58 string of wrong length to assert the parser rejects it;
follow the same test names/structure used for the other curves so
checked_base58_decode_array and the CurveType::Sr25519 branch are exercised.
In `@crates/signatures/sr25519/src/lib.rs`:
- Around line 53-67: Add a serde JSON round-trip test for the
SignedSr25519Payload shape to ensure flatten + AsCurve<Sr25519> wire format
stays stable: write a unit test that constructs a SignedSr25519Payload (using
Sr25519 keypair/signature utilities from this crate), serialize it to JSON,
compare against a checked-in JSON fixture (or write and then deserialize the
fixture), then deserialize back and assert equality with the original; place the
test near other sr25519 tests and reference the SignedSr25519Payload type, the
payload field, public_key and signature fields to validate the flattened
structure is preserved across serialization and deserialization.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 22a67744-4b64-4108-bee2-8c424481ad86
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (14)
Cargo.tomlcontracts/wallet/Cargo.tomlcontracts/wallet/src/contract/impl_.rscontracts/wallet/src/signature/mod.rscontracts/wallet/src/signature/sr25519.rscrates/crypto/Cargo.tomlcrates/crypto/src/curve/mod.rscrates/crypto/src/curve/sr25519.rscrates/crypto/src/lib.rscrates/crypto/src/parse.rscrates/crypto/src/public_key.rscrates/crypto/src/signature.rscrates/signatures/sr25519/Cargo.tomlcrates/signatures/sr25519/src/lib.rs
Adds Polkadot/Substrate-compatible Sr25519 (Schnorr on Ristretto255)
Re-cuts the curve work from #171 onto the current layout, wired wallet-only.
Changes
defuse-crypto— newSr25519Curvebehind asr25519feature(
schnorrkel = "0.11.5"dep). AddsSr25519PublicKey/Sr25519Signatureand
CurveType::Sr25519 = 3/PublicKey::Sr25519/Signature::Sr25519variants. Implicit account derivation:
0x{keccak256("sr25519" || pk)[12..32]}— same Eth-Implicit schema asP256, distinct prefix to avoid cross-curve collisions.crates/signatures/sr25519/(new) — generic payload crate matchingthe
sep53/tip191shape (Sr25519Payload { payload: String }+SignedSr25519Payload).verifyreproduces the Substrate<Bytes>...</Bytes>envelope that every Polkadot wallet (Polkadot.js,Talisman, Subwallet, Nova, …) applies automatically before signing.
Ships a real-wallet signature as a regression vector.
contracts/wallet—sr25519feature flag,cargo-nearreproduciblebuild variant, and a
SigningStandard<&RequestMessage>adapter. Theproofis a JSONSignedSr25519Payloadwhose innerpayloadis theJSON-encoded
RequestMessage; the adapter compares that toserde_json::to_string(msg)and callssigned.verify(). Registerswallet-sr25519v1.0.0 in contract metadata.Out of scope
MultiPayloadintegration from Add support for sr25519 signatures #171 — left for a follow-up.References
Summary by CodeRabbit