Skip to content

Fix/rlp v2 audit followups - #472

Merged
andrewnguyen22 merged 4 commits into
mainfrom
fix/rlp-v2-audit-followups
Jul 21, 2026
Merged

Fix/rlp v2 audit followups#472
andrewnguyen22 merged 4 commits into
mainfrom
fix/rlp-v2-audit-followups

Conversation

@andrewnguyen22

Copy link
Copy Markdown
Collaborator

What this does

This adds RLP.V2 transactions with account-based nonce protection for Ethereum wallets.

RLP.V2 stores the signed nonce directly on the Canopy transaction and advances a nonce floor on the sender’s account after execution. The nonce does not need to be consecutive: committing nonce N invalidates that nonce and everything below it.

Legacy RLP and RLP.V2 use different Ethereum chain ID domains, so a signature for one cannot be reused as the other. Legacy decoding remains available for replaying historical blocks, while new legacy transactions are disabled at protocol version 2.

Ethereum RPC changes

  • eth_sendRawTransaction now creates RLP.V2 transactions.
  • eth_getTransactionCount reads the committed account nonce and includes local pending transactions for "pending".
  • Added eth_feeHistory and eth_maxPriorityFeePerGas for wallet compatibility.
  • Added same-nonce replacement support. Both the fee cap and tip cap must increase by at least 10%.
  • Replaced transactions are removed only after the replacement survives mempool insertion.
  • Stale entries in the short-lived RPC cache no longer block replacements.
  • The pending transaction cache is bounded and expires entries after two minutes.

Follow-up fixes

This also includes the issues found during review:

  • Drained accounts are deleted when their balance and nonce are both zero. RLP.V2 accounts with a committed nonce are retained.
  • Normal fee-based mempool eviction no longer goes through invalid-transaction handling.
  • Vesting math now avoids uint64 multiplication overflow.
  • Equal-fee mempool transactions keep their arrival order.
  • Plugin implementations preserve the new account nonce.
  • The transaction nonce uses protobuf field 10; plugin-specific transaction fields are safe from field 25 onward.

The Go, Python, TypeScript, Kotlin, and C# plugin schemas were updated together.

Rollout

Validators and configured plugins need to be upgraded together before RLP.V2 submissions begin. No account migration or nonce backfill is required.

RLP.V2 submission or replay during the transition window is an accepted rollout assumption.

@andrewnguyen22 andrewnguyen22 self-assigned this Jul 15, 2026
@andrewnguyen22 andrewnguyen22 added FSM Finite State Machine module RPC Plugin or 3rd party chain module labels Jul 15, 2026
Comment thread store/indexer.go Outdated
Comment thread cmd/rpc/eth.go
@rem1niscence

Copy link
Copy Markdown
Collaborator

tests failing with:

imports github.com/canopy-network/canopy/fsm from indexer.go: import cycle not allowed in test

@andrewnguyen22

andrewnguyen22 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

tests failing with:

imports github.com/canopy-network/canopy/fsm from indexer.go: import cycle not allowed in test

Fixed @rem1niscence

@rem1niscence rem1niscence left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although most of the review was focused on understanding the PR itself and styling issues as I lack the full implementation details to correct on logic. This seems pretty complete and throroughly tested. Just left a few questions to confirm behavior

Comment thread controller/tx.go
}
defer c.Mempool.L.Unlock()
for _, result := range c.Mempool.cachedResults {
if result == nil || result.Transaction == nil || result.Transaction.Memo != fsm.RLPV2Indicator ||

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the pending nonce is somewhat dependant on the mempool cache, is it expected that if an user is connected to a canopy node (A) of X chain to process eth txs and for whatever reason goes to a different node (B) to perform txs, if it returns back to the first node (A) those transactions will fail due to a lower nonce err?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is expected and how ethereum behaves

Comment thread fsm/state.go

const (
CurrentProtocolVersion = 1
CurrentProtocolVersion = 2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safe to assume that a protocol bump must be done right after merging this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A protocol bump doesn't need to be done immediately - this is in preparation if we do submit the protocol change transaction

@andrewnguyen22
andrewnguyen22 merged commit 3b338b2 into main Jul 21, 2026
2 checks passed
@andrewnguyen22
andrewnguyen22 deleted the fix/rlp-v2-audit-followups branch July 21, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FSM Finite State Machine module RPC Plugin or 3rd party chain module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants