feat: enable attestation signing with validator key#1210
Conversation
Add ValidatorSigner for signing attestation payloads with validator's key. Returns EVM-compatible 65-byte signatures verifiable by smart contracts. - Thread-safe singleton pattern - Keccak256 hashing + secp256k1 ECDSA signing - Initialize from node key file in engineReadyHook - tests 100% pass resolves: #1206
WalkthroughAdds a thread-safe singleton ValidatorSigner for secp256k1 signing, exposes public key/address accessors, provides initialization and test-reset helpers, integrates signer initialization into tn_attestation's engineReadyHook (loading node key), and adds unit tests for signer and engine readiness behaviors. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Node as Node Startup
participant Conf as App Config
participant Key as Key Loader
participant VS as ValidatorSigner (singleton)
participant Ext as tn_attestation
Node->>Ext: engineReadyHook(app, service)
Ext->>Conf: RootDir()
alt Root dir available
Ext->>Key: LoadNodeKey(NodeKeyFilePath(rootDir))
alt Key loaded
Ext->>VS: InitializeValidatorSigner(privateKey)
alt Init ok
Ext->>VS: GetValidatorSigner()
VS-->>Ext: signer (address)
Ext-->>Node: ready (logs validator address)
else Init error
Ext-->>Node: error
end
else Load error
Ext-->>Node: warn and return
end
else No root dir
Ext-->>Node: warn and return
end
sequenceDiagram
autonumber
participant Caller as Attestation Flow
participant VS as ValidatorSigner
participant Eth as go-ethereum crypto
Caller->>VS: SignKeccak256(payload)
alt Signer initialized and payload non-empty
VS->>Eth: keccak256(payload)
Eth-->>VS: hash
VS->>Eth: Sign(hash)
Eth-->>VS: 65-byte signature (R||S||V)
VS-->>Caller: signature
else Error
VS-->>Caller: error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
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 |
Time Submission Status
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
extensions/tn_attestation/signer_test.go (1)
255-272: Optional: assert V byte is EVM-compatible (27 or 28) to harden the testStrengthen the EVM compatibility check by validating signature[64] ∈ {27, 28}. This catches accidental normalization to 0/1 that many Solidity ecrecover helpers don’t accept.
Example:
require.Equal(t, 65, len(signature)) v := signature[64] assert.True(t, v == 27 || v == 28, "V must be 27 or 28, got %d", v)extensions/tn_attestation/signer.go (1)
45-50: Fix V-byte documentation (geth returns 27/28), keep code as-isgo-ethereum’s crypto.Sign returns [R||S||V] where V is 27 or 28 (not 0/1). Ecrecover expects 27/28 in most Solidity helpers.
Apply:
-// - V: 1 byte (recovery ID, 27 or 28 for legacy compatibility) +// - V: 1 byte (recovery ID, 27 or 28 for EVM compatibility) ... -// V is already in the correct format (0 or 1, internally adjusted to 27/28 by ecrecover) +// V is returned as 27 or 28 by go-ethereum's crypto.Sign and is EVM-compatible.Also applies to: 71-73
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
extensions/tn_attestation/signer.go(1 hunks)extensions/tn_attestation/signer_test.go(1 hunks)extensions/tn_attestation/tn_attestation.go(2 hunks)extensions/tn_attestation/tn_attestation_test.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
extensions/tn_attestation/tn_attestation.go (3)
extensions/tn_attestation/constants.go (1)
ExtensionName(3-3)extensions/tn_attestation/queue.go (1)
GetAttestationQueue(115-120)extensions/tn_attestation/signer.go (2)
InitializeValidatorSigner(103-109)GetValidatorSigner(113-115)
extensions/tn_attestation/tn_attestation_test.go (1)
extensions/tn_attestation/signer.go (2)
ResetValidatorSignerForTesting(119-122)GetValidatorSigner(113-115)
extensions/tn_attestation/signer_test.go (1)
extensions/tn_attestation/signer.go (4)
NewValidatorSigner(26-43)ResetValidatorSignerForTesting(119-122)InitializeValidatorSigner(103-109)GetValidatorSigner(113-115)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: lint
- GitHub Check: acceptance-test
🔇 Additional comments (1)
extensions/tn_attestation/tn_attestation_test.go (1)
113-121: Integer range loops are supported under Go 1.24.1
go.mod declaresgo 1.24.1, sofor i := range 10,for range 100, and similar loops compile without change.
Add ValidatorSigner for signing attestation payloads with validator's key. Returns EVM-compatible 65-byte signatures verifiable by smart contracts.
resolves: #1206
Summary by CodeRabbit
New Features
Tests