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 )