Wallet Refactoring#11664
Conversation
|
Claude finished @svlachakis's task in 5m 40s —— View job PR Review: Wallet Refactoring
|
|
@claude review again, eth_sign error message is fine, it's matching the geth and our own eth_signTransaction. |
|
Claude finished @svlachakis's task in 2m 11s —— View job PR Review: Wallet Refactoring
SummaryGood shape. The shift from exception-based Previous Medium finding resolved:
Passphrase-based atomic sign removed: Deliberate breaking change, called out in the PR description. ✓ No remaining findings. PR is mergeable. |
|
Claude finished @svlachakis's task in 5m 8s —— View job PR Review: Wallet Refactoring
SummaryClean refactoring. The shift from exception-based No blocking findings. Previous Medium finding ( Correctness ChecksEIP-155 V adjustment ( ClefWallet V handling — legacy path takes Clef's raw EIP-155 V as-is; typed path adds ClefWallet No remaining callers of old Low
// IWallet.cs:34
ValueHash256 hash = ValueKeccak.Compute(Rlp.Encode(tx, true, true, chainId).Bytes);
Positive observations
PR is mergeable. No Critical, High, or Medium findings. |
|
@claude review again, extended trysign/tryseal even more |
|
Claude finished @svlachakis's task in 5m 2s —— View job PR Review: Wallet Refactoring
SummaryGood extension — the One Medium finding and a couple of Low observations below. Medium
See inline comment on Low
Per // Simplified:
if (!signed)
throw new InvalidOperationException($"Clique signer {_signer.Address} could not sign block {block.Number}.");
Correctness Checks
EIP-155 V — Positive Observations
|
|
@claude review again |
|
Claude finished @svlachakis's task in 4m 45s —— View job PR Review: Wallet Refactoring
SummaryAll three findings from the previous review round are resolved. No new Critical, High, or Medium findings. Prior Findings — All ResolvedMedium:
return acceptTxResult.Equals(AcceptTxResult.SignFailed)
? ResultWrapper<Hash256>.Fail("authentication needed: password or unlock", ErrorCodes.AccountLocked)
: ResultWrapper<Hash256>.Fail(acceptTxResult?.ToString() ?? string.Empty, ErrorCodes.TransactionRejected);The message is the bare Low: Removed — only Low:
Correctness Checks (New Code)
Observation (Pre-existing, not introduced by this PR)
No Critical, High, or Medium findings. PR is mergeable. |
| xdcBlockHeader.Validator = signer.Sign(hashStream.GetValueHash()).BytesWithRecovery; | ||
| ValueHash256 hash = hashStream.GetValueHash(); | ||
| if (!signer.TrySign(in hash, out Signature signature)) | ||
| throw new InvalidOperationException($"XDC signer {signer.Address} could not sign block {block.Number}."); |
There was a problem hiding this comment.
if we are throwing in the end then it wasn't worth the refactor?
There was a problem hiding this comment.
I made it completely exceptionless locally and I can push, but I'm not convinced it's the correct way to be to be honest to move on.
@ak88 has also this point #11664 (comment), @LukaszRozmej WDYT?
There was a problem hiding this comment.
I pushed completely exceptionless approach - but would appreciate your thoughts.
|
@claude does completely exceptionless approach make sense? please review. |
|
Claude finished @svlachakis's task in 4m 9s —— View job PR Review: Wallet Refactoring — Completely Exceptionless Approach
Does completely exceptionless make sense? Yes.The key architectural question is whether signing failures in consensus and wallet code are expected operational states or programmer errors. They are operational states — a locked account, missing key, or temporarily unavailable remote signer is not a bug. The The previous concern ("if we're throwing in the end, was the refactor worth it?") was valid for the pre-b268681 state, where Correctness of the null-return path in
|
| Location | Exception | Rationale |
|---|---|---|
ISigner.Sign() default |
InvalidOperationException |
Convenience assertion wrapper — caller already checked CanSign |
IHeaderSigner.Sign() default |
InvalidOperationException |
Same pattern |
ITxSealer.Seal() default |
InvalidOperationException |
Wraps TrySeal for callers that assert success |
ClefSigner.TrySign(Transaction) |
NotImplementedException |
Remote signer does not support tx signing — correct |
XdcSealer: genesis block / non-XDC header |
InvalidOperationException / ArgumentException |
Invariant violations — programmer errors, not operational failures |
These are all legitimate "this-should-not-happen" scenarios — the right type of case for exceptions.
Findings
Low — XdcSealerTests has no coverage for the new failure path
The only test (SealBlock_ShouldSignXdcBlockHeader) covers the success path. The new behavior — "signer has no key → SealBlock returns null rather than throwing" — has no test. Since this is a behavior change from the pre-refactor code (which threw), a regression test would be valuable:
[Test]
public async Task SealBlock_WithNoKey_ReturnsNull()
{
XdcSealer sealer = new(new Signer(0, (PrivateKey?)null, NullLogManager.Instance), NullLogManager.Instance);
Block block = Build.A.Block.WithHeader(Build.A.XdcBlockHeader().TestObject).TestObject;
Block? result = await sealer.SealBlock(block, CancellationToken.None);
Assert.That(result, Is.Null);
}Low — VotesManager.CastVote silently returns on sign failure
// VotesManager.cs:70
if (!TrySign(vote)) return Task.CompletedTask;No log at Warn or higher when a vote cannot be signed. For XDC consensus participation, a silent skip means the node silently stops voting. At minimum a Warn log (matching XdcSealer's pattern) would help operators diagnose a key configuration problem.
Positive observations
BlockProducerBasenull-seal handling is correct:FailedBlockSealsmetric + Info log.VotesManager.TrySignandTimeoutCertificateManager.SendTimeoutcorrectly skip without throwing.SignTransactionManager.SubmitTransactionSignlogs at Warn on failure — good.- Convenience
Sign()wrappers retained onISigner/IHeaderSigner/ITxSealerfor callers that assert must-succeed — this is the correct C#TryXxx/ assertion wrapper pattern. AcceptTxResult.SignFailed→ErrorCodes.AccountLockedcorrectly propagates signing failure to RPC callers.
No Critical, High, or Medium findings. PR is mergeable. The exceptionless approach is well-designed — it matches the existing AuRa/Clique sealer pattern, is handled correctly by the base block producer, and eliminates exception allocations on the failure path without losing observability.
|
@claude review again |
|
Claude finished @svlachakis's task in 2m 40s —— View job PR Review: Wallet Refactoring
SummaryAll findings from the previous round are resolved. The latest commit ( Prior Findings — All ResolvedLow:
Low: Warn log added: New Changes (Not Prior Findings)
No Critical, High, or Medium findings. PR is mergeable. |

Fixes Closes Resolves #11538
Changes
Types of changes
What types of changes does your code introduce?
Testing
Requires testing