Skip to content

refactor(core): semantic journalling #28880#2081

Merged
AnilChinchawale merged 1 commit into
XinFinOrg:dev-upgradefrom
gzliudan:journal_changes
Mar 7, 2026
Merged

refactor(core): semantic journalling #28880#2081
AnilChinchawale merged 1 commit into
XinFinOrg:dev-upgradefrom
gzliudan:journal_changes

Conversation

@gzliudan
Copy link
Copy Markdown
Collaborator

@gzliudan gzliudan commented Feb 25, 2026

Proposed changes

This is a follow-up to #1934, and a preparatory PR to a more thorough change in the journalling system.

API methods instead of append operations

This PR hides the journal-implementation details away, so that the statedb invokes methods like JournalCreate, instead of explicitly appending journal-events in a list. This means that it's up to the journal whether to implement it as a sequence of events or aggregate/merge events.

Snapshot-management inside the journal

This PR also makes it so that management of valid snapshots is moved inside the journal, exposed via the methods Snapshot() int and RevertToSnapshot(revid int, s *StateDB).

SetCode

JournalSetCode journals the setting of code: it is implicit that the previous values were "no code" and emptyCodeHash. Therefore, we can simplify the setCode journal.

Selfdestruct

The self-destruct journalling is a bit strange: we allow the selfdestruct operation to be journalled several times. This makes it so that we also are forced to store whether the account was already destructed.

What we can do instead, is to only journal the first destruction, and after that only journal balance-changes, but not journal the selfdestruct itself.

This simplifies the journalling, so that internals about state management does not leak into the journal-API.

Preimages

Preimages were, for some reason, integrated into the journal management, despite not being a consensus-critical data structure. This PR undoes that.
Ref: ethereum#28880

Types of changes

What types of changes does your code introduce to XDC network?
Put an in the boxes that apply

  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Changes that don't change source code or tests
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • revert: Revert something
  • style: Changes that do not affect the meaning of the code
  • test: Adding missing tests or correcting existing tests

Impacted Components

Which parts of the codebase does this PR touch?
Put an in the boxes that apply

  • Consensus
  • Account
  • Network
  • Geth
  • Smart Contract
  • External components
  • Not sure (Please specify below)

Checklist

Put an in the boxes once you have confirmed below actions (or provide reasons on not doing so) that

  • This PR has sufficient test coverage (unit/integration test) OR I have provided reason in the PR description for not having test coverage
  • Tested on a private network from the genesis block and monitored the chain operating correctly for multiple epochs.
  • Provide an end-to-end test plan in the PR description on how to manually test it on the devnet/testnet.
  • Tested the backwards compatibility.
  • Tested with XDC nodes running this version co-exist with those running the previous version.
  • Relevant documentation has been updated as part of this PR
  • N/A

Copilot AI review requested due to automatic review settings February 25, 2026 05:37
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 25, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 34c33c25-9590-487f-82c7-3fdaf3cae2a4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the state journaling system to make journal operations more semantic and to centralize snapshot/revision bookkeeping inside the journal, alongside some storage journaling semantics improvements and related test updates.

Changes:

  • Moves snapshot/revert revision tracking from StateDB into journal (snapshot, revertToSnapshot, reset, copy behavior).
  • Introduces more semantic journal helper methods (e.g., logChange, refundChange, storageChange, touchChange, access list helpers) and updates call sites.
  • Refines storage dirty/pending handling to better model “revert-to-origin” behavior, and updates snapshot/fuzz tests accordingly.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
core/state/statedb.go Delegates snapshot/revert and various mutations to semantic journal methods; changes AddPreimage behavior.
core/state/journal.go Adds revision tracking + snapshot/reset APIs; introduces semantic append helpers; adjusts change structs.
core/state/state_object.go Updates storage access/mutation flow to track original values and clean up dirty/pending slots when reverted.
core/state/statedb_test.go Renames an action label and adds a guard around SetCode in randomized snapshot tests.
core/state/statedb_fuzz_test.go Renames an action label in fuzz-driven state tests.
Comments suppressed due to low confidence (2)

core/state/statedb_test.go:350

  • The action label was renamed to "SetStorage", but the action still calls StateDB.SetState (set a single storage slot), not StateDB.SetStorage (replace entire storage). This makes snapshot test failure output misleading; consider renaming to something like "SetState"/"SetSlot" to match the invoked API.
			name: "SetStorage",
			fn: func(a testAction, s *StateDB) {
				var key, val common.Hash
				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
				s.SetState(addr, key, val)
			},

core/state/statedb_fuzz_test.go:79

  • The action label was renamed to "SetStorage", but the fuzz action still calls StateDB.SetState (set a single storage slot). This name collides with the existing StateDB.SetStorage API and can be confusing when interpreting fuzz traces; consider renaming to "SetState"/"SetSlot".
		{
			name: "SetStorage",
			fn: func(a testAction, s *StateDB) {
				var key, val common.Hash
				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/state/state_object.go Outdated
Comment thread core/state/journal.go
Comment thread core/state/statedb.go
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/state/statedb_test.go
Comment thread core/state/statedb_fuzz_test.go
Comment thread core/state/statedb_test.go
Comment on lines +135 to +139
func (s *stateObject) getState(key common.Hash) (common.Hash, common.Hash) {
origin := s.GetCommittedState(key)
value, dirty := s.dirtyStorage[key]
if dirty {
return value
return value, origin
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

getState now calls GetCommittedState before checking dirtyStorage, meaning a read-only GetState of an already-dirty slot still incurs the committed-state lookup (and potentially a trie read the first time). Consider restoring the fast path for GetState (check dirtyStorage first) and only loading the committed/origin value in the write path (SetState) when it’s actually needed for journalling.

Copilot uses AI. Check for mistakes.
Comment thread core/state/statedb.go
Comment on lines 743 to 747
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
logSize: s.logSize,
preimages: maps.Clone(s.preimages),
journal: s.journal.copy(),
validRevisions: slices.Clone(s.validRevisions),
nextRevisionId: s.nextRevisionId,
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

StateDB.Copy still states that snapshots of the copied state cannot be applied, but journal.copy() now clones validRevisions/nextRevisionId, which makes snapshot IDs and the revision stack carry over into the copy. Either reset snapshot metadata on copy (to preserve the documented behavior) or update the Copy docs/expectations accordingly.

Copilot uses AI. Check for mistakes.
This is a follow-up to ethereum#29520, and a preparatory PR to a more thorough
change in the journalling system.

This PR hides the journal-implementation details away, so that the
statedb invokes methods like `JournalCreate`, instead of explicitly
appending journal-events in a list. This means that it's up to the
journal whether to implement it as a sequence of events or
aggregate/merge events.

This PR also makes it so that management of valid snapshots is moved
inside the journal, exposed via the methods `Snapshot() int` and
`RevertToSnapshot(revid int, s *StateDB)`.

JournalSetCode journals the setting of code: it is implicit that the
previous values were "no code" and emptyCodeHash. Therefore, we can
simplify the setCode journal.

The self-destruct journalling is a bit strange: we allow the
selfdestruct operation to be journalled several times. This makes it so
that we also are forced to store whether the account was already
destructed.

What we can do instead, is to only journal the first destruction, and
after that only journal balance-changes, but not journal the
selfdestruct itself.

This simplifies the journalling, so that internals about state
management does not leak into the journal-API.

Preimages were, for some reason, integrated into the journal management,
despite not being a consensus-critical data structure. This PR undoes
that.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
@AnilChinchawale AnilChinchawale merged commit e02bc07 into XinFinOrg:dev-upgrade Mar 7, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants