github.com/ledgerwatch/erigon-lib@v1.0.0/kv/tables.go (about)

     1  /*
     2     Copyright 2021 Erigon contributors
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package kv
    18  
    19  import (
    20  	"fmt"
    21  	"sort"
    22  	"strings"
    23  
    24  	"github.com/ledgerwatch/erigon-lib/gointerfaces/types"
    25  )
    26  
    27  // DBSchemaVersion versions list
    28  // 5.0 - BlockTransaction table now has canonical ids (txs of non-canonical blocks moving to NonCanonicalTransaction table)
    29  // 6.0 - BlockTransaction table now has system-txs before and after block (records are absent if block has no system-tx, but sequence increasing)
    30  // 6.1 - Canonical/NonCanonical/BadBlock transations now stored in same table: kv.EthTx. Add kv.BadBlockNumber table
    31  var DBSchemaVersion = types.VersionReply{Major: 6, Minor: 1, Patch: 0}
    32  
    33  // ChaindataTables
    34  
    35  // Dictionary:
    36  // "Plain State" - state where keys arent' hashed. "CurrentState" - same, but keys are hashed. "PlainState" used for blocks execution. "CurrentState" used mostly for Merkle root calculation.
    37  // "incarnation" - uint64 number - how much times given account was SelfDestruct'ed.
    38  
    39  /*
    40  PlainState logical layout:
    41  
    42  	Contains Accounts:
    43  	  key - address (unhashed)
    44  	  value - account encoded for storage
    45  	Contains Storage:
    46  	  key - address (unhashed) + incarnation + storage key (unhashed)
    47  	  value - storage value(common.hash)
    48  
    49  Physical layout:
    50  
    51  	PlainState and HashedStorage utilises DupSort feature of MDBX (store multiple values inside 1 key).
    52  
    53  -------------------------------------------------------------
    54  
    55  	key              |            value
    56  
    57  -------------------------------------------------------------
    58  [acc_hash]              | [acc_value]
    59  [acc_hash]+[inc]        | [storage1_hash]+[storage1_value]
    60  
    61  	| [storage2_hash]+[storage2_value] // this value has no own key. it's 2nd value of [acc_hash]+[inc] key.
    62  	| [storage3_hash]+[storage3_value]
    63  	| ...
    64  
    65  [acc_hash]+[old_inc]    | [storage1_hash]+[storage1_value]
    66  
    67  	| ...
    68  
    69  [acc2_hash]             | [acc2_value]
    70  
    71  	...
    72  */
    73  const PlainState = "PlainState"
    74  
    75  // PlainContractCode -
    76  // key - address+incarnation
    77  // value - code hash
    78  const PlainContractCode = "PlainCodeHash"
    79  
    80  /*
    81  AccountChangeSet and StorageChangeSet - of block N store values of state before block N changed them.
    82  Because values "after" change stored in PlainState.
    83  Logical format:
    84  
    85  	key - blockNum_u64 + key_in_plain_state
    86  	value - value_in_plain_state_before_blockNum_changes
    87  
    88  Example: If block N changed account A from value X to Y. Then:
    89  
    90  	AccountChangeSet has record: bigEndian(N) + A -> X
    91  	PlainState has record: A -> Y
    92  
    93  See also: docs/programmers_guide/db_walkthrough.MD#table-history-of-accounts
    94  
    95  As you can see if block N changes much accounts - then all records have repetitive prefix `bigEndian(N)`.
    96  MDBX can store such prefixes only once - by DupSort feature (see `docs/programmers_guide/dupsort.md`).
    97  Both buckets are DupSort-ed and have physical format:
    98  AccountChangeSet:
    99  
   100  	key - blockNum_u64
   101  	value - address + account(encoded)
   102  
   103  StorageChangeSet:
   104  
   105  	key - blockNum_u64 + address + incarnation_u64
   106  	value - plain_storage_key + value
   107  */
   108  const AccountChangeSet = "AccountChangeSet"
   109  const StorageChangeSet = "StorageChangeSet"
   110  
   111  const (
   112  
   113  	//HashedAccounts
   114  	// key - address hash
   115  	// value - account encoded for storage
   116  	// Contains Storage:
   117  	//key - address hash + incarnation + storage key hash
   118  	//value - storage value(common.hash)
   119  	HashedAccounts = "HashedAccount"
   120  	HashedStorage  = "HashedStorage"
   121  )
   122  
   123  /*
   124  AccountsHistory and StorageHistory - indices designed to serve next 2 type of requests:
   125  1. what is smallest block number >= X where account A changed
   126  2. get last shard of A - to append there new block numbers
   127  
   128  Task 1. is part of "get historical state" operation (see `core/state:GetAsOf`):
   129  If `db.Seek(A+bigEndian(X))` returns non-last shard -
   130  
   131  	then get block number from shard value Y := RoaringBitmap(shard_value).GetGte(X)
   132  	and with Y go to ChangeSets: db.Get(ChangeSets, Y+A)
   133  
   134  If `db.Seek(A+bigEndian(X))` returns last shard -
   135  
   136  	then we go to PlainState: db.Get(PlainState, A)
   137  
   138  Format:
   139    - index split to shards by 2Kb - RoaringBitmap encoded sorted list of block numbers
   140      (to avoid performance degradation of popular accounts or look deep into history.
   141      Also 2Kb allows avoid Overflow pages inside DB.)
   142    - if shard is not last - then key has suffix 8 bytes = bigEndian(max_block_num_in_this_shard)
   143    - if shard is last - then key has suffix 8 bytes = 0xFF
   144  
   145  It allows:
   146    - server task 1. by 1 db operation db.Seek(A+bigEndian(X))
   147    - server task 2. by 1 db operation db.Get(A+0xFF)
   148  
   149  see also: docs/programmers_guide/db_walkthrough.MD#table-change-sets
   150  
   151  AccountsHistory:
   152  
   153  	key - address + shard_id_u64
   154  	value - roaring bitmap  - list of block where it changed
   155  
   156  StorageHistory
   157  
   158  	key - address + storage_key + shard_id_u64
   159  	value - roaring bitmap - list of block where it changed
   160  */
   161  const E2AccountsHistory = "AccountHistory"
   162  const E2StorageHistory = "StorageHistory"
   163  
   164  const (
   165  
   166  	//key - contract code hash
   167  	//value - contract code
   168  	Code = "Code"
   169  
   170  	//key - addressHash+incarnation
   171  	//value - code hash
   172  	ContractCode = "HashedCodeHash"
   173  
   174  	// IncarnationMap for deleted accounts
   175  	//key - address
   176  	//value - incarnation of account when it was last deleted
   177  	IncarnationMap = "IncarnationMap"
   178  
   179  	//TEVMCode -
   180  	//key - contract code hash
   181  	//value - contract TEVM code
   182  	ContractTEVMCode = "TEVMCode"
   183  )
   184  
   185  /*
   186  TrieOfAccounts and TrieOfStorage
   187  hasState,groups - mark prefixes existing in hashed_account table
   188  hasTree - mark prefixes existing in trie_account table (not related with branchNodes)
   189  hasHash - mark prefixes which hashes are saved in current trie_account record (actually only hashes of branchNodes can be saved)
   190  @see UnmarshalTrieNode
   191  @see integrity.Trie
   192  
   193  +-----------------------------------------------------------------------------------------------------+
   194  | DB record: 0x0B, hasState: 0b1011, hasTree: 0b1001, hasHash: 0b1001, hashes: [x,x]                  |
   195  +-----------------------------------------------------------------------------------------------------+
   196  
   197  	|                                           |                               |
   198  	v                                           |                               v
   199  
   200  +---------------------------------------------+             |            +--------------------------------------+
   201  | DB record: 0x0B00, hasState: 0b10001        |             |            | DB record: 0x0B03, hasState: 0b10010 |
   202  | hasTree: 0, hasHash: 0b10000, hashes: [x]   |             |            | hasTree: 0, hasHash: 0, hashes: []   |
   203  +---------------------------------------------+             |            +--------------------------------------+
   204  
   205  	|                    |                              |                         |                  |
   206  	v                    v                              v                         v                  v
   207  
   208  +------------------+    +----------------------+     +---------------+        +---------------+  +---------------+
   209  | Account:         |    | BranchNode: 0x0B0004 |     | Account:      |        | Account:      |  | Account:      |
   210  | 0x0B0000...      |    | has no record in     |     | 0x0B01...     |        | 0x0B0301...   |  | 0x0B0304...   |
   211  | in HashedAccount |    |     TrieAccount      |     |               |        |               |  |               |
   212  +------------------+    +----------------------+     +---------------+        +---------------+  +---------------+
   213  
   214  	                           |                |
   215  	                           v                v
   216  			           +---------------+  +---------------+
   217  			           | Account:      |  | Account:      |
   218  			           | 0x0B000400... |  | 0x0B000401... |
   219  			           +---------------+  +---------------+
   220  
   221  Invariants:
   222  - hasTree is subset of hasState
   223  - hasHash is subset of hasState
   224  - first level in account_trie always exists if hasState>0
   225  - TrieStorage record of account.root (length=40) must have +1 hash - it's account.root
   226  - each record in TrieAccount table must have parent (may be not direct) and this parent must have correct bit in hasTree bitmap
   227  - if hasState has bit - then HashedAccount table must have record according to this bit
   228  - each TrieAccount record must cover some state (means hasState is always > 0)
   229  - TrieAccount records with length=1 can satisfy (hasBranch==0&&hasHash==0) condition
   230  - Other records in TrieAccount and TrieStorage must (hasTree!=0 || hasHash!=0)
   231  */
   232  const TrieOfAccounts = "TrieAccount"
   233  const TrieOfStorage = "TrieStorage"
   234  
   235  // Mapping [block number] => [Verkle Root]
   236  const VerkleRoots = "VerkleRoots"
   237  
   238  // Mapping [Verkle Root] => [Rlp-Encoded Verkle Node]
   239  const VerkleTrie = "VerkleTrie"
   240  
   241  const (
   242  	// DatabaseInfo is used to store information about data layout.
   243  	DatabaseInfo = "DbInfo"
   244  
   245  	// Naming:
   246  	//   NeaderNumber - Ethereum-specific block number. All nodes have same BlockNum.
   247  	//   NeaderID - auto-increment ID. Depends on order in which node see headers.
   248  	//      Invariant: for all headers in snapshots Number == ID. It means no reason to store Num/ID for this headers in DB.
   249  	//   Same about: TxNum/TxID, BlockNum/BlockID
   250  	HeaderNumber    = "HeaderNumber"           // header_hash -> header_num_u64
   251  	BadHeaderNumber = "BadHeaderNumber"        // header_hash -> header_num_u64
   252  	HeaderCanonical = "CanonicalHeader"        // block_num_u64 -> header hash
   253  	Headers         = "Header"                 // block_num_u64 + hash -> header (RLP)
   254  	HeaderTD        = "HeadersTotalDifficulty" // block_num_u64 + hash -> td (RLP)
   255  
   256  	BlockBody = "BlockBody" // block_num_u64 + hash -> block body
   257  
   258  	// Naming:
   259  	//  TxNum - Ethereum canonical transaction number - same across all nodes.
   260  	//  TxnID - auto-increment ID - can be differrent across all nodes
   261  	//  BlockNum/BlockID - same
   262  	//
   263  	// EthTx - stores all transactions of Canonical/NonCanonical/Bad blocks
   264  	// TxnID (auto-increment ID) - means nodes in network will have different ID of same transactions
   265  	// Snapshots (frozen data): using TxNum (not TxnID)
   266  	//
   267  	// During ReOrg - txs are not removed/updated
   268  	//
   269  	// Also this table has system-txs before and after block: if
   270  	// block has no system-tx - records are absent, but TxnID increasing
   271  	//
   272  	// In Erigon3: table MaxTxNum storing TxNum (not TxnID). History/Indices are using TxNum (not TxnID).
   273  	EthTx           = "BlockTransaction"        // tx_id_u64 -> rlp(tx)
   274  	NonCanonicalTxs = "NonCanonicalTransaction" // tbl_sequence_u64 -> rlp(tx)
   275  	MaxTxNum        = "MaxTxNum"                // block_number_u64 -> max_tx_num_in_block_u64
   276  
   277  	Receipts = "Receipt"        // block_num_u64 -> canonical block receipts (non-canonical are not stored)
   278  	Log      = "TransactionLog" // block_num_u64 + txId -> logs of transaction
   279  
   280  	// Stores bitmap indices - in which block numbers saw logs of given 'address' or 'topic'
   281  	// [addr or topic] + [2 bytes inverted shard number] -> bitmap(blockN)
   282  	// indices are sharded - because some bitmaps are >1Mb and when new incoming blocks process it
   283  	//	 updates ~300 of bitmaps - by append small amount new values. It cause much big writes (MDBX does copy-on-write).
   284  	//
   285  	// if last existing shard size merge it with delta
   286  	// if serialized size of delta > ShardLimit - break down to multiple shards
   287  	// shard number - it's biggest value in bitmap
   288  	LogTopicIndex   = "LogTopicIndex"
   289  	LogAddressIndex = "LogAddressIndex"
   290  
   291  	// CallTraceSet is the name of the table that contain the mapping of block number to the set (sorted) of all accounts
   292  	// touched by call traces. It is DupSort-ed table
   293  	// 8-byte BE block number -> account address -> two bits (one for "from", another for "to")
   294  	CallTraceSet = "CallTraceSet"
   295  	// Indices for call traces - have the same format as LogTopicIndex and LogAddressIndex
   296  	// Store bitmap indices - in which block number we saw calls from (CallFromIndex) or to (CallToIndex) some addresses
   297  	CallFromIndex = "CallFromIndex"
   298  	CallToIndex   = "CallToIndex"
   299  
   300  	// Cumulative indexes for estimation of stage execution
   301  	CumulativeGasIndex         = "CumulativeGasIndex"
   302  	CumulativeTransactionIndex = "CumulativeTransactionIndex"
   303  
   304  	TxLookup = "BlockTransactionLookup" // hash -> transaction/receipt lookup metadata
   305  
   306  	ConfigTable = "Config" // config prefix for the db
   307  
   308  	// Progress of sync stages: stageName -> stageData
   309  	SyncStageProgress = "SyncStage"
   310  
   311  	Clique             = "Clique"
   312  	CliqueSeparate     = "CliqueSeparate"
   313  	CliqueSnapshot     = "CliqueSnapshot"
   314  	CliqueLastSnapshot = "CliqueLastSnapshot"
   315  
   316  	// Proof-of-stake
   317  	// Beacon chain head that is been executed at the current time
   318  	CurrentExecutionPayload = "CurrentExecutionPayload"
   319  
   320  	// Node database tables (see nodedb.go)
   321  
   322  	// NodeRecords stores P2P node records (ENR)
   323  	NodeRecords = "NodeRecord"
   324  	// Inodes stores P2P discovery service info about the nodes
   325  	Inodes = "Inode"
   326  
   327  	// Transaction senders - stored separately from the block bodies
   328  	Senders = "TxSender" // block_num_u64 + blockHash -> sendersList (no serialization format, every 20 bytes is new sender)
   329  
   330  	// headBlockKey tracks the latest know full block's hash.
   331  	HeadBlockKey = "LastBlock"
   332  
   333  	HeadHeaderKey = "LastHeader"
   334  
   335  	// headBlockHash, safeBlockHash, finalizedBlockHash of the latest Engine API forkchoice
   336  	LastForkchoice = "LastForkchoice"
   337  
   338  	// TransitionBlockKey tracks the last proof-of-work block
   339  	TransitionBlockKey = "TransitionBlock"
   340  
   341  	// migrationName -> serialized SyncStageProgress and SyncStageUnwind buckets
   342  	// it stores stages progress to understand in which context was executed migration
   343  	// in case of bug-report developer can ask content of this bucket
   344  	Migrations = "Migration"
   345  
   346  	Sequence = "Sequence" // tbl_name -> seq_u64
   347  
   348  	Epoch        = "DevEpoch"        // block_num_u64+block_hash->transition_proof
   349  	PendingEpoch = "DevPendingEpoch" // block_num_u64+block_hash->transition_proof
   350  
   351  	Issuance = "Issuance" // block_num_u64->RLP(issuance+burnt[0 if < london])
   352  
   353  	StateAccounts   = "StateAccounts"
   354  	StateStorage    = "StateStorage"
   355  	StateCode       = "StateCode"
   356  	StateCommitment = "StateCommitment"
   357  
   358  	// BOR
   359  
   360  	BorReceipts  = "BorReceipt"
   361  	BorFinality  = "BorFinality"
   362  	BorTxLookup  = "BlockBorTransactionLookup" // transaction_hash -> block_num_u64
   363  	BorSeparate  = "BorSeparate"               // persisted snapshots of the Validator Sets, with their proposer priorities
   364  	BorEvents    = "BorEvents"                 // event_id -> event_payload
   365  	BorEventNums = "BorEventNums"              // block_num -> event_id (first event_id in that block)
   366  	BorSpans     = "BorSpans"                  // span_id -> span (in JSON encoding)
   367  
   368  	// Downloader
   369  	BittorrentCompletion = "BittorrentCompletion"
   370  	BittorrentInfo       = "BittorrentInfo"
   371  
   372  	// Domains/Histry/InvertedIndices
   373  	// Contants have "Tbl" prefix, to avoid collision with actual Domain names
   374  	// This constants is very rarely used in APP, but Domain/History/Idx names are widely used
   375  	TblAccountKeys        = "AccountKeys"
   376  	TblAccountVals        = "AccountVals"
   377  	TblAccountHistoryKeys = "AccountHistoryKeys"
   378  	TblAccountHistoryVals = "AccountHistoryVals"
   379  	TblAccountIdx         = "AccountIdx"
   380  
   381  	TblStorageKeys        = "StorageKeys"
   382  	TblStorageVals        = "StorageVals"
   383  	TblStorageHistoryKeys = "StorageHistoryKeys"
   384  	TblStorageHistoryVals = "StorageHistoryVals"
   385  	TblStorageIdx         = "StorageIdx"
   386  
   387  	TblCodeKeys        = "CodeKeys"
   388  	TblCodeVals        = "CodeVals"
   389  	TblCodeHistoryKeys = "CodeHistoryKeys"
   390  	TblCodeHistoryVals = "CodeHistoryVals"
   391  	TblCodeIdx         = "CodeIdx"
   392  
   393  	TblCommitmentKeys        = "CommitmentKeys"
   394  	TblCommitmentVals        = "CommitmentVals"
   395  	TblCommitmentHistoryKeys = "CommitmentHistoryKeys"
   396  	TblCommitmentHistoryVals = "CommitmentHistoryVals"
   397  	TblCommitmentIdx         = "CommitmentIdx"
   398  
   399  	TblLogAddressKeys = "LogAddressKeys"
   400  	TblLogAddressIdx  = "LogAddressIdx"
   401  	TblLogTopicsKeys  = "LogTopicsKeys"
   402  	TblLogTopicsIdx   = "LogTopicsIdx"
   403  
   404  	TblTracesFromKeys = "TracesFromKeys"
   405  	TblTracesFromIdx  = "TracesFromIdx"
   406  	TblTracesToKeys   = "TracesToKeys"
   407  	TblTracesToIdx    = "TracesToIdx"
   408  
   409  	Snapshots = "Snapshots" // name -> hash
   410  
   411  	//State Reconstitution
   412  	RAccountKeys = "RAccountKeys"
   413  	RAccountIdx  = "RAccountIdx"
   414  	RStorageKeys = "RStorageKeys"
   415  	RStorageIdx  = "RStorageIdx"
   416  	RCodeKeys    = "RCodeKeys"
   417  	RCodeIdx     = "RCodeIdx"
   418  
   419  	PlainStateR    = "PlainStateR"    // temporary table for PlainState reconstitution
   420  	PlainStateD    = "PlainStateD"    // temporary table for PlainStare reconstitution, deletes
   421  	CodeR          = "CodeR"          // temporary table for Code reconstitution
   422  	CodeD          = "CodeD"          // temporary table for Code reconstitution, deletes
   423  	PlainContractR = "PlainContractR" // temporary table for PlainContract reconstitution
   424  	PlainContractD = "PlainContractD" // temporary table for PlainContract reconstitution, deletes
   425  
   426  	// Erigon-CL Objects
   427  
   428  	// [slot] => [Beacon state]
   429  	BeaconState = "BeaconState"
   430  	// [slot] => [signature + block without execution payload]
   431  	BeaconBlocks = "BeaconBlock"
   432  	// [slot] => [attestation list (custom encoding)]
   433  	Attestetations = "Attestetations"
   434  	// [slot] => [Finalized block root]
   435  	FinalizedBlockRoots = "FinalizedBlockRoots"
   436  	// [Root (block root/state root/eth1 root)] => Slot
   437  	RootSlotIndex = "RootSlotIndex"
   438  
   439  	// LightClientStore => LightClientStore object
   440  	// LightClientFinalityUpdate => latest finality update
   441  	// LightClientOptimisticUpdate => latest optimistic update
   442  	LightClient = "LightClient"
   443  	// Period (one every 27 hours) => LightClientUpdate
   444  	LightClientUpdates = "LightClientUpdates"
   445  )
   446  
   447  // Keys
   448  var (
   449  	//StorageModeTEVM - does not translate EVM to TEVM
   450  	StorageModeTEVM = []byte("smTEVM")
   451  
   452  	PruneTypeOlder  = []byte("older")
   453  	PruneTypeBefore = []byte("before")
   454  
   455  	PruneHistory        = []byte("pruneHistory")
   456  	PruneHistoryType    = []byte("pruneHistoryType")
   457  	PruneReceipts       = []byte("pruneReceipts")
   458  	PruneReceiptsType   = []byte("pruneReceiptsType")
   459  	PruneTxIndex        = []byte("pruneTxIndex")
   460  	PruneTxIndexType    = []byte("pruneTxIndexType")
   461  	PruneCallTraces     = []byte("pruneCallTraces")
   462  	PruneCallTracesType = []byte("pruneCallTracesType")
   463  
   464  	DBSchemaVersionKey = []byte("dbVersion")
   465  
   466  	BittorrentPeerID            = "peerID"
   467  	CurrentHeadersSnapshotHash  = []byte("CurrentHeadersSnapshotHash")
   468  	CurrentHeadersSnapshotBlock = []byte("CurrentHeadersSnapshotBlock")
   469  	CurrentBodiesSnapshotHash   = []byte("CurrentBodiesSnapshotHash")
   470  	CurrentBodiesSnapshotBlock  = []byte("CurrentBodiesSnapshotBlock")
   471  	PlainStateVersion           = []byte("PlainStateVersion")
   472  
   473  	LightClientStore            = []byte("LightClientStore")
   474  	LightClientFinalityUpdate   = []byte("LightClientFinalityUpdate")
   475  	LightClientOptimisticUpdate = []byte("LightClientOptimisticUpdate")
   476  )
   477  
   478  // ChaindataTables - list of all buckets. App will panic if some bucket is not in this list.
   479  // This list will be sorted in `init` method.
   480  // ChaindataTablesCfg - can be used to find index in sorted version of ChaindataTables list by name
   481  var ChaindataTables = []string{
   482  	E2AccountsHistory,
   483  	E2StorageHistory,
   484  	Code,
   485  	ContractCode,
   486  	HeaderNumber,
   487  	BadHeaderNumber,
   488  	BlockBody,
   489  	Receipts,
   490  	TxLookup,
   491  	ConfigTable,
   492  	CurrentExecutionPayload,
   493  	DatabaseInfo,
   494  	IncarnationMap,
   495  	ContractTEVMCode,
   496  	CliqueSeparate,
   497  	CliqueLastSnapshot,
   498  	CliqueSnapshot,
   499  	SyncStageProgress,
   500  	PlainState,
   501  	PlainContractCode,
   502  	AccountChangeSet,
   503  	StorageChangeSet,
   504  	Senders,
   505  	HeadBlockKey,
   506  	HeadHeaderKey,
   507  	LastForkchoice,
   508  	Migrations,
   509  	LogTopicIndex,
   510  	LogAddressIndex,
   511  	CallTraceSet,
   512  	CallFromIndex,
   513  	CallToIndex,
   514  	CumulativeGasIndex,
   515  	CumulativeTransactionIndex,
   516  	Log,
   517  	Sequence,
   518  	EthTx,
   519  	NonCanonicalTxs,
   520  	TrieOfAccounts,
   521  	TrieOfStorage,
   522  	HashedAccounts,
   523  	HashedStorage,
   524  	HeaderCanonical,
   525  	Headers,
   526  	HeaderTD,
   527  	Epoch,
   528  	PendingEpoch,
   529  	Issuance,
   530  	StateAccounts,
   531  	StateStorage,
   532  	StateCode,
   533  	StateCommitment,
   534  	BorReceipts,
   535  	BorFinality,
   536  	BorTxLookup,
   537  	BorSeparate,
   538  	BorEvents,
   539  	BorEventNums,
   540  	BorSpans,
   541  	TblAccountKeys,
   542  	TblAccountVals,
   543  	TblAccountHistoryKeys,
   544  	TblAccountHistoryVals,
   545  	TblAccountIdx,
   546  
   547  	TblStorageKeys,
   548  	TblStorageVals,
   549  	TblStorageHistoryKeys,
   550  	TblStorageHistoryVals,
   551  	TblStorageIdx,
   552  
   553  	TblCodeKeys,
   554  	TblCodeVals,
   555  	TblCodeHistoryKeys,
   556  	TblCodeHistoryVals,
   557  	TblCodeIdx,
   558  
   559  	TblCommitmentKeys,
   560  	TblCommitmentVals,
   561  	TblCommitmentHistoryKeys,
   562  	TblCommitmentHistoryVals,
   563  	TblCommitmentIdx,
   564  
   565  	TblLogAddressKeys,
   566  	TblLogAddressIdx,
   567  	TblLogTopicsKeys,
   568  	TblLogTopicsIdx,
   569  
   570  	TblTracesFromKeys,
   571  	TblTracesFromIdx,
   572  	TblTracesToKeys,
   573  	TblTracesToIdx,
   574  
   575  	Snapshots,
   576  	MaxTxNum,
   577  
   578  	RAccountKeys,
   579  	RAccountIdx,
   580  	RStorageKeys,
   581  	RStorageIdx,
   582  	RCodeKeys,
   583  	RCodeIdx,
   584  
   585  	VerkleRoots,
   586  	VerkleTrie,
   587  	// Beacon stuff
   588  	BeaconState,
   589  	BeaconBlocks,
   590  	FinalizedBlockRoots,
   591  	RootSlotIndex,
   592  	Attestetations,
   593  	LightClient,
   594  	LightClientUpdates,
   595  }
   596  
   597  const (
   598  	RecentLocalTransaction = "RecentLocalTransaction" // sequence_u64 -> tx_hash
   599  	PoolTransaction        = "PoolTransaction"        // txHash -> sender_id_u64+tx_rlp
   600  	PoolInfo               = "PoolInfo"               // option_key -> option_value
   601  )
   602  
   603  var TxPoolTables = []string{
   604  	RecentLocalTransaction,
   605  	PoolTransaction,
   606  	PoolInfo,
   607  }
   608  var SentryTables = []string{}
   609  var DownloaderTables = []string{
   610  	BittorrentCompletion,
   611  	BittorrentInfo,
   612  }
   613  var ReconTables = []string{
   614  	PlainStateR,
   615  	PlainStateD,
   616  	CodeR,
   617  	CodeD,
   618  	PlainContractR,
   619  	PlainContractD,
   620  }
   621  
   622  // ChaindataDeprecatedTables - list of buckets which can be programmatically deleted - for example after migration
   623  var ChaindataDeprecatedTables = []string{
   624  	Clique,
   625  	TransitionBlockKey,
   626  }
   627  
   628  type CmpFunc func(k1, k2, v1, v2 []byte) int
   629  
   630  type TableCfg map[string]TableCfgItem
   631  type Bucket string
   632  
   633  type DBI uint
   634  type TableFlags uint
   635  
   636  const (
   637  	Default    TableFlags = 0x00
   638  	ReverseKey TableFlags = 0x02
   639  	DupSort    TableFlags = 0x04
   640  	IntegerKey TableFlags = 0x08
   641  	IntegerDup TableFlags = 0x20
   642  	ReverseDup TableFlags = 0x40
   643  )
   644  
   645  type TableCfgItem struct {
   646  	Flags TableFlags
   647  	// AutoDupSortKeysConversion - enables some keys transformation - to change db layout without changing app code.
   648  	// Use it wisely - it helps to do experiments with DB format faster, but better reduce amount of Magic in app.
   649  	// If good DB format found, push app code to accept this format and then disable this property.
   650  	AutoDupSortKeysConversion bool
   651  	IsDeprecated              bool
   652  	DBI                       DBI
   653  	// DupFromLen - if user provide key of this length, then next transformation applied:
   654  	// v = append(k[DupToLen:], v...)
   655  	// k = k[:DupToLen]
   656  	// And opposite at retrieval
   657  	// Works only if AutoDupSortKeysConversion enabled
   658  	DupFromLen int
   659  	DupToLen   int
   660  }
   661  
   662  var ChaindataTablesCfg = TableCfg{
   663  	HashedStorage: {
   664  		Flags:                     DupSort,
   665  		AutoDupSortKeysConversion: true,
   666  		DupFromLen:                72,
   667  		DupToLen:                  40,
   668  	},
   669  	AccountChangeSet: {Flags: DupSort},
   670  	StorageChangeSet: {Flags: DupSort},
   671  	PlainState: {
   672  		Flags:                     DupSort,
   673  		AutoDupSortKeysConversion: true,
   674  		DupFromLen:                60,
   675  		DupToLen:                  28,
   676  	},
   677  	CallTraceSet: {Flags: DupSort},
   678  
   679  	TblAccountKeys:           {Flags: DupSort},
   680  	TblAccountHistoryKeys:    {Flags: DupSort},
   681  	TblAccountHistoryVals:    {Flags: DupSort},
   682  	TblAccountIdx:            {Flags: DupSort},
   683  	TblStorageKeys:           {Flags: DupSort},
   684  	TblStorageHistoryKeys:    {Flags: DupSort},
   685  	TblStorageHistoryVals:    {Flags: DupSort},
   686  	TblStorageIdx:            {Flags: DupSort},
   687  	TblCodeKeys:              {Flags: DupSort},
   688  	TblCodeHistoryKeys:       {Flags: DupSort},
   689  	TblCodeIdx:               {Flags: DupSort},
   690  	TblCommitmentKeys:        {Flags: DupSort},
   691  	TblCommitmentHistoryKeys: {Flags: DupSort},
   692  	TblCommitmentIdx:         {Flags: DupSort},
   693  	TblLogAddressKeys:        {Flags: DupSort},
   694  	TblLogAddressIdx:         {Flags: DupSort},
   695  	TblLogTopicsKeys:         {Flags: DupSort},
   696  	TblLogTopicsIdx:          {Flags: DupSort},
   697  	TblTracesFromKeys:        {Flags: DupSort},
   698  	TblTracesFromIdx:         {Flags: DupSort},
   699  	TblTracesToKeys:          {Flags: DupSort},
   700  	TblTracesToIdx:           {Flags: DupSort},
   701  	RAccountKeys:             {Flags: DupSort},
   702  	RAccountIdx:              {Flags: DupSort},
   703  	RStorageKeys:             {Flags: DupSort},
   704  	RStorageIdx:              {Flags: DupSort},
   705  	RCodeKeys:                {Flags: DupSort},
   706  	RCodeIdx:                 {Flags: DupSort},
   707  }
   708  
   709  var TxpoolTablesCfg = TableCfg{}
   710  var SentryTablesCfg = TableCfg{}
   711  var DownloaderTablesCfg = TableCfg{}
   712  var ReconTablesCfg = TableCfg{
   713  	PlainStateD:    {Flags: DupSort},
   714  	CodeD:          {Flags: DupSort},
   715  	PlainContractD: {Flags: DupSort},
   716  }
   717  
   718  func TablesCfgByLabel(label Label) TableCfg {
   719  	switch label {
   720  	case ChainDB:
   721  		return ChaindataTablesCfg
   722  	case TxPoolDB:
   723  		return TxpoolTablesCfg
   724  	case SentryDB:
   725  		return SentryTablesCfg
   726  	case DownloaderDB:
   727  		return DownloaderTablesCfg
   728  	default:
   729  		panic(fmt.Sprintf("unexpected label: %s", label))
   730  	}
   731  }
   732  func sortBuckets() {
   733  	sort.SliceStable(ChaindataTables, func(i, j int) bool {
   734  		return strings.Compare(ChaindataTables[i], ChaindataTables[j]) < 0
   735  	})
   736  }
   737  
   738  func init() {
   739  	reinit()
   740  }
   741  
   742  func reinit() {
   743  	sortBuckets()
   744  
   745  	for _, name := range ChaindataTables {
   746  		_, ok := ChaindataTablesCfg[name]
   747  		if !ok {
   748  			ChaindataTablesCfg[name] = TableCfgItem{}
   749  		}
   750  	}
   751  
   752  	for _, name := range ChaindataDeprecatedTables {
   753  		_, ok := ChaindataTablesCfg[name]
   754  		if !ok {
   755  			ChaindataTablesCfg[name] = TableCfgItem{}
   756  		}
   757  		tmp := ChaindataTablesCfg[name]
   758  		tmp.IsDeprecated = true
   759  		ChaindataTablesCfg[name] = tmp
   760  	}
   761  
   762  	for _, name := range TxPoolTables {
   763  		_, ok := TxpoolTablesCfg[name]
   764  		if !ok {
   765  			TxpoolTablesCfg[name] = TableCfgItem{}
   766  		}
   767  	}
   768  
   769  	for _, name := range SentryTables {
   770  		_, ok := SentryTablesCfg[name]
   771  		if !ok {
   772  			SentryTablesCfg[name] = TableCfgItem{}
   773  		}
   774  	}
   775  
   776  	for _, name := range DownloaderTables {
   777  		_, ok := DownloaderTablesCfg[name]
   778  		if !ok {
   779  			DownloaderTablesCfg[name] = TableCfgItem{}
   780  		}
   781  	}
   782  
   783  	for _, name := range ReconTables {
   784  		_, ok := ReconTablesCfg[name]
   785  		if !ok {
   786  			ReconTablesCfg[name] = TableCfgItem{}
   787  		}
   788  	}
   789  }
   790  
   791  // Temporal
   792  
   793  const (
   794  	AccountsDomain Domain = "AccountsDomain"
   795  	StorageDomain  Domain = "StorageDomain"
   796  	CodeDomain     Domain = "CodeDomain"
   797  )
   798  
   799  const (
   800  	AccountsHistory History = "AccountsHistory"
   801  	StorageHistory  History = "StorageHistory"
   802  	CodeHistory     History = "CodeHistory"
   803  )
   804  
   805  const (
   806  	AccountsHistoryIdx InvertedIdx = "AccountsHistoryIdx"
   807  	StorageHistoryIdx  InvertedIdx = "StorageHistoryIdx"
   808  	CodeHistoryIdx     InvertedIdx = "CodeHistoryIdx"
   809  
   810  	LogTopicIdx   InvertedIdx = "LogTopicIdx"
   811  	LogAddrIdx    InvertedIdx = "LogAddrIdx"
   812  	TracesFromIdx InvertedIdx = "TracesFromIdx"
   813  	TracesToIdx   InvertedIdx = "TracesToIdx"
   814  )