You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An archive node is an instance of an Ethereum client configured to build an archive of all historical states. There are two queries that it needs to answer:
the account information at the given block
the storage information at the given block for the given account.
This means that both queries could be transformed into a query that:
starts with the account = @account equality,
then is followed by storage = @storage (for storage)
then is followed by block <= @block as the change might have been applied in the past
It should be possible then to use the same db structure where the key is encoded as a NibblePath by concatenating account + storage + block and mapping some payload to it. This concatenation would allow Paprika's prefixing behavior to potentially make the dataset smaller. Potentially a separate page type with a different flushing behavior and a different fan out could be applied.
From the consumption point of view, archive processing could be a sidecar that processes storage & state slots that are flushed by the Blockchain.FlusherTask method. Then, each block that is applied could be inspected and applied to a separate archive root. This could be done by extending RootPage by only one address that would point to the separate Archive tree.
Examples
eth_getBalance 0x1234567890ABCDEF 234234
find first key lower than 0x1234... + 0 + `234234
0 stands for balance
eth_getNonce 0x1234567890ABCDEF 234234
find first key lower than 0x1234... + 1 + `234234
1 stands for nonce
eth_gstorage 0x1234567890ABCDEF 0x1 234234
find id of the account, first lower than 0x1234... + 234234, save to id
find key lower than id + keccak(0x1) + 234234
Current state
Archive node sizes:
Nethermind: 15TB
Erigon/Reth have a few TB archive, not sure the correct number, but I guess 2-5 TB
Remarks
The application of the data could be done in a relaxed manner, where the flush to disk happens only now and then. There are options for this already.
Storing or calculating hashes, could be made optional. We could skip memoization of Merkle so that Branch is max 2 bytes instead of 512 bytes.
Split Account into Account.Balance, Account.CodeHash, Account.StorageRoot, Account.Nonce so that less frequently changed data are not overwritten over and over again.
Querying the state should take into consideration the transient in memory state and the archive.
The other option is to have the Archive totally separated. That could be considered, but there's something into having it embedded into the block processing, where the data are fresh, in-memory and ready to be stored by this archiving sidecar.
Archive should probably separate the archive tree so that the Merkle and the current state is kept where it is, where the archive is kept separately.
Archive SHOULD not use mmap for its storage. It's much too big. This means that manual buffer management will be needed. From writing point of view not that much will change as Paprika uses file write + file cache coherency. From the reading point of view and ownership this will change a lot requiring ownership and copying buffers.
The text was updated successfully, but these errors were encountered:
There should be a (slow) way to support deep reorganistations with archive storage.
I expect archive storage to be indexed by block (or each transactions within blocks), it would be good to have an option to prune archive storage, keeping some arbitrary number of blocks there (for example from only last year or month).
An archive node is an instance of an Ethereum client configured to build an archive of all historical states. There are two queries that it needs to answer:
account
information at the givenblock
storage
information at the givenblock
for the givenaccount
.This means that both queries could be transformed into a query that:
account = @account
equality,storage = @storage
(for storage)block <= @block
as the change might have been applied in the pastIt should be possible then to use the same db structure where the key is encoded as a
NibblePath
by concatenatingaccount + storage + block
and mapping some payload to it. This concatenation would allow Paprika's prefixing behavior to potentially make the dataset smaller. Potentially a separate page type with a different flushing behavior and a different fan out could be applied.From the consumption point of view, archive processing could be a sidecar that processes storage & state slots that are flushed by the
Blockchain.FlusherTask
method. Then, each block that is applied could be inspected and applied to a separate archive root. This could be done by extendingRootPage
by only one address that would point to the separateArchive
tree.Examples
eth_getBalance 0x1234567890ABCDEF 234234
0x1234...
+0
+ `2342340
stands forbalance
eth_getNonce 0x1234567890ABCDEF 234234
0x1234...
+1
+ `2342341
stands fornonce
eth_gstorage 0x1234567890ABCDEF 0x1 234234
0x1234...
+234234
, save toid
id
+keccak(0x1)
+234234
Current state
Archive node sizes:
15TB
2-5 TB
Remarks
Merkle
so thatBranch
is max 2 bytes instead of 512 bytes.Account
intoAccount.Balance
,Account.CodeHash
,Account.StorageRoot
,Account.Nonce
so that less frequently changed data are not overwritten over and over again.The text was updated successfully, but these errors were encountered: