Skip to content

Commit 55eb047

Browse files
committed
fix: comment formatting
1 parent 129b472 commit 55eb047

File tree

3 files changed

+81
-46
lines changed

3 files changed

+81
-46
lines changed

libevm/triedb/firewood/account_trie.go

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ import (
3333

3434
var _ state.Trie = (*AccountTrie)(nil)
3535

36-
// AccountTrie implements state.Trie for managing account states.
37-
// There are a couple caveats to the current implementation:
38-
// 1. `Commit` is not used as expected in the state package. The `StorageTrie` doesn't return
39-
// values, and we thus rely on the `AccountTrie`.
40-
// 2. The `Hash` method actually creates the proposal, since Firewood cannot calculate
41-
// the hash of the trie without committing it. It is immediately dropped, and this
42-
// can likely be optimized.
36+
// AccountTrie implements [state.Trie] for managing account states.
37+
// Although it fulfills the [state.Trie] interface, it has some important differences:
38+
// 1. [AccountTrie.Commit] is not used as expected in the state package. The `StorageTrie` doesn't return
39+
// values, and we thus rely on the `AccountTrie`. Additionally, no [trienode.NodeSet] is
40+
// actually constructed, since Firewood manages nodes internally and the list of changes
41+
// is not needed externally.
42+
// 2. The [AccountTrie.Hash] method actually creates the [ffi.Proposal], since Firewood cannot calculate
43+
// the hash of the trie without committing it.
4344
//
4445
// Note this is not concurrent safe.
4546
type AccountTrie struct {
@@ -207,8 +208,10 @@ func (a *AccountTrie) DeleteStorage(addr common.Address, key []byte) error {
207208
}
208209

209210
// Hash returns the current hash of the state trie.
210-
// This will create a proposal and drop it, so it is not efficient to call for each transaction.
211+
// This will create the necessary proposals to guarantee that the changes can
212+
// later be committed. All new proposals will be tracked by the [Database].
211213
// If there are no changes since the last call, the cached root is returned.
214+
// On error, the zero hash is returned.
212215
func (a *AccountTrie) Hash() common.Hash {
213216
hash, err := a.hash()
214217
if err != nil {
@@ -231,9 +234,9 @@ func (a *AccountTrie) hash() (common.Hash, error) {
231234
return a.root, nil
232235
}
233236

234-
// Commit returns the new root hash of the trie and a NodeSet containing all modified accounts and storage slots.
235-
// The format of the NodeSet is different than in go-ethereum's trie implementation due to Firewood's design.
236-
// This boolean is ignored, as it is a relic of the StateTrie implementation.
237+
// Commit returns the new root hash of the trie and an empty [trienode.NodeSet].
238+
// The boolean input is ignored, as it is a relic of the StateTrie implementation.
239+
// If the changes are not yet already tracked by the [Database], they are created.
237240
func (a *AccountTrie) Commit(bool) (common.Hash, *trienode.NodeSet, error) {
238241
// Get the hash of the trie.
239242
hash, err := a.hash()
@@ -248,29 +251,35 @@ func (a *AccountTrie) Commit(bool) (common.Hash, *trienode.NodeSet, error) {
248251
}
249252

250253
// UpdateContractCode implements state.Trie.
251-
// Contract code is controlled by rawdb, so we don't need to do anything here.
254+
// Contract code is controlled by `rawdb`, so we don't need to do anything here.
255+
// This always returns nil.
252256
func (*AccountTrie) UpdateContractCode(common.Address, common.Hash, []byte) error {
253257
return nil
254258
}
255259

256260
// GetKey implements state.Trie.
257261
// This should not be used, since any user should not be accessing by raw key.
262+
// It always returns nil.
258263
func (*AccountTrie) GetKey([]byte) []byte {
259264
return nil
260265
}
261266

262267
// NodeIterator implements state.Trie.
263268
// Firewood does not support iterating over internal nodes.
269+
// This always returns an error.
264270
func (*AccountTrie) NodeIterator([]byte) (trie.NodeIterator, error) {
265271
return nil, errors.New("NodeIterator not implemented for Firewood")
266272
}
267273

268274
// Prove implements state.Trie.
269-
// Firewood does not yet support providing key proofs.
275+
// Firewood does not support providing key proofs.
276+
// This always returns an error.
270277
func (*AccountTrie) Prove([]byte, ethdb.KeyValueWriter) error {
271278
return errors.New("Prove not implemented for Firewood")
272279
}
273280

281+
// Copy creates a deep copy of the [AccountTrie].
282+
// The [database.Reader] is shared, since it is read-only.
274283
func (a *AccountTrie) Copy() *AccountTrie {
275284
// Create a new AccountTrie with the same root and reader
276285
newTrie := &AccountTrie{

libevm/triedb/firewood/firewood.go

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,12 @@ var (
5353
_ triedb.DBOverride = (*Database)(nil)
5454
)
5555

56-
// A Database is an implementation of [triedb.DBOverride].
56+
// Database is a triedb.DBOverride implementation backed by Firewood.
57+
// It acts as a HashDB for backwards compatibility with most of the blockchain code.
5758
type Database struct {
5859
// The underlying Firewood database, used for storing proposals and revisions.
59-
// This must be exported so other packages (e.g. state sync) can access firewood-specific methods.
60+
// This is exported as read-only, with knowledge that the consumer will not close it
61+
// and the latest state can be modified at any time.
6062
Firewood *ffi.Database
6163

6264
proposals
@@ -71,7 +73,7 @@ type proposals struct {
7173
// in the case of duplicate state roots.
7274
// The root of the tree is stored here, and represents the top-most layer on disk.
7375
tree *proposal
74-
// possibleProposals temporarily holds proposals created during a trie update.
76+
// possible temporarily holds proposals created during a trie update.
7577
// This is cleared after the update is complete and the proposals have been sent to the database.
7678
possible []*proposal
7779
}
@@ -95,22 +97,35 @@ type proposalMeta struct {
9597
height uint64
9698
}
9799

100+
// Config provides necessary parameters for creating a Firewood database.
98101
type Config struct {
99-
ChainDir string
100-
CleanCacheSize int
102+
DatabasePath string
103+
CacheSizeBytes uint
101104
FreeListCacheEntries uint
102-
Revisions uint
103-
ReadCacheStrategy ffi.CacheStrategy
105+
MaxRevisions uint
106+
CacheStrategy ffi.CacheStrategy
104107
}
105108

106-
// Note that `FilePath` is not specified, and must always be set by the user.
107-
var Defaults = Config{
108-
CleanCacheSize: 1024 * 1024, // 1MB
109-
FreeListCacheEntries: 40_000,
110-
Revisions: 100,
111-
ReadCacheStrategy: ffi.CacheAllReads,
109+
// DefaultConfig returns a default Config with the given directory.
110+
// The default config is:
111+
// - CacheSizeBytes: 1MB
112+
// - FreeListCacheEntries: 40,000
113+
// - MaxRevisions: 100
114+
// - CacheStrategy: [ffi.CacheAllReads]
115+
func DefaultConfig(dir string) Config {
116+
return Config{
117+
DatabasePath: dir,
118+
CacheSizeBytes: 1024 * 1024, // 1MB
119+
FreeListCacheEntries: 40_000,
120+
MaxRevisions: 100,
121+
CacheStrategy: ffi.CacheAllReads,
122+
}
112123
}
113124

125+
// BackendConstructor implements the [triedb.DBConstructor] interface.
126+
// It creates a new Firewood database with the given configuration.
127+
// Since Firewood uses its own on-disk format, the provided ethdb.Database is ignored.
128+
// Any error during creation will cause the program to exit.
114129
func (c Config) BackendConstructor(ethdb.Database) triedb.DBOverride {
115130
db, err := New(c)
116131
if err != nil {
@@ -119,26 +134,26 @@ func (c Config) BackendConstructor(ethdb.Database) triedb.DBOverride {
119134
return db
120135
}
121136

122-
// New creates a new Firewood database with the given disk database and configuration.
123-
// Any error during creation will cause the program to exit.
137+
// New creates a new Firewood database with the given configuration.
138+
// The database will not be opened on error.
124139
func New(config Config) (*Database, error) {
125-
if err := validateDir(config.ChainDir); err != nil {
140+
if err := validateDir(config.DatabasePath); err != nil {
126141
return nil, err
127142
}
128143

129-
logPath := filepath.Join(config.ChainDir, logFileName)
144+
logPath := filepath.Join(config.DatabasePath, logFileName)
130145
if err := ffi.StartLogs(&ffi.LogConfig{Path: logPath}); err != nil {
131146
// This shouldn't be a fatal error, as this can only be called once per thread.
132147
// Specifically, this will return an error in unit tests.
133148
log.Warn("firewood: error starting logs", "error", err)
134149
}
135150

136-
dbPath := filepath.Join(config.ChainDir, dbFileName)
151+
dbPath := filepath.Join(config.DatabasePath, dbFileName)
137152
fw, err := ffi.New(dbPath, &ffi.Config{
138-
NodeCacheEntries: uint(config.CleanCacheSize) / 256, // TODO(alarso16): 256 bytes may not be accurate
153+
NodeCacheEntries: config.CacheSizeBytes / 256, // TODO(alarso16): 256 bytes per node may not be accurate
139154
FreeListCacheEntries: config.FreeListCacheEntries,
140-
Revisions: config.Revisions,
141-
ReadCacheStrategy: config.ReadCacheStrategy,
155+
Revisions: config.MaxRevisions,
156+
ReadCacheStrategy: config.CacheStrategy,
142157
})
143158
if err != nil {
144159
return nil, err
@@ -176,7 +191,7 @@ func validateDir(dir string) error {
176191
switch info, err := os.Stat(dir); {
177192
case os.IsNotExist(err):
178193
log.Info("Database directory not found, creating", "path", dir)
179-
if err := os.MkdirAll(dir, 0o755); err != nil {
194+
if err := os.MkdirAll(dir, 0o750); err != nil {
180195
return fmt.Errorf("creating database directory: %v", err)
181196
}
182197
return nil
@@ -222,6 +237,8 @@ func (*Database) Size() (common.StorageSize, common.StorageSize) {
222237
return 0, 0
223238
}
224239

240+
// Reference is no-op because proposals are only referenced when created.
241+
// Additionally, internal nodes do not need tracked by consumers.
225242
func (*Database) Reference(common.Hash, common.Hash) {}
226243

227244
// Dereference is no-op because unused proposals are dereferenced when no longer valid.
@@ -238,6 +255,11 @@ func (*Database) Cap(common.StorageSize) error {
238255
return nil
239256
}
240257

258+
// Close closes the database, freeing all associated resources.
259+
// This may hang for a short period while waiting for finalizers to complete.
260+
// If it does not close as expected, this indicates that there are still references
261+
// to proposals or revisions in memory, and an error will be returned.
262+
// The database should not be used after calling Close.
241263
func (db *Database) Close() error {
242264
p := &db.proposals
243265
p.Lock()
@@ -253,6 +275,11 @@ func (db *Database) Close() error {
253275
return db.Firewood.Close(context.Background())
254276
}
255277

278+
// Update updates the database to the given root at the given height.
279+
// The parent block hash and block hash must be provided in the options.
280+
// A proposal must have already been created from [AccountTrie.Commit] with the same root,
281+
// parent root, and height.
282+
// If no such proposal exists, an error will be returned.
256283
func (db *Database) Update(root, parent common.Hash, height uint64, _ *trienode.MergedNodeSet, _ *triestate.Set, opts ...stateconf.TrieDBUpdateOption) error {
257284
// We require block hashes to be provided for all blocks in production.
258285
// However, many tests cannot reasonably provide a block blockHash for genesis, so we allow it to be omitted.
@@ -360,7 +387,7 @@ func find[S ~[]E, E comparable](s S, fn func(E) bool) (E, bool) {
360387
// Any time this is called, we expect either:
361388
// 1. The root is the same as the current root of the database (empty block during bootstrapping)
362389
// 2. We have created a valid propsal with that root, and it is of height +1 above the proposal tree root.
363-
// Additionally, this should be unique.
390+
// Additionally, this will be unique.
364391
//
365392
// Afterward, we know that no other proposal at this height can be committed, so we can dereference all
366393
// children in the the other branches of the proposal tree.

libevm/triedb/firewood/storage_trie.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,33 @@ import (
2121
"github.com/ava-labs/libevm/trie/trienode"
2222
)
2323

24+
// StorageTrie is a wrapper around an AccountTrie for Firewood.
25+
// Firewood does not require a separate storage trie, as all storage changes
26+
// are managed by the account trie.
2427
type StorageTrie struct {
2528
*AccountTrie
2629
}
2730

28-
// `NewStorageTrie` returns a wrapper around an `AccountTrie` since Firewood
29-
// does not require a separate storage trie. All changes are managed by the account trie.
31+
// NewStorageTrie returns a wrapper around an [AccountTrie].
3032
func NewStorageTrie(accountTrie *AccountTrie) (*StorageTrie, error) {
3133
return &StorageTrie{
3234
AccountTrie: accountTrie,
3335
}, nil
3436
}
3537

36-
// Actual commit is handled by the account trie.
37-
// Return the old storage root as if there was no change since Firewood
38-
// will manage the hash calculations without it.
39-
// All changes are managed by the account trie.
38+
// Commit is a no-op for storage tries, as all changes are managed by the account trie.
39+
// It always returns a nil NodeSet and zero hash.
4040
func (*StorageTrie) Commit(bool) (common.Hash, *trienode.NodeSet, error) {
4141
return common.Hash{}, nil, nil
4242
}
4343

44-
// Firewood doesn't require tracking storage roots inside of an account.
45-
// They will be updated in place when hashing of the proposal takes place.
44+
// Hash returns an empty hash, as the storage roots are managed internally to Firewood.
4645
func (*StorageTrie) Hash() common.Hash {
4746
return common.Hash{}
4847
}
4948

50-
// Copy should never be called on a storage trie, as it is just a wrapper around the account trie.
51-
// Each storage trie should be re-opened with the account trie separately.
49+
// Copy returns nil, as storage tries do not need to be copied separately.
50+
// All usage of a copied storage trie should first ensure it is non-nil.
5251
func (*StorageTrie) Copy() *StorageTrie {
5352
return nil
5453
}

0 commit comments

Comments
 (0)