github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/triedb/pathdb/history.go (about) 1 // Copyright 2022 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/> 16 17 package pathdb 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "errors" 23 "fmt" 24 "slices" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/core/rawdb" 29 "github.com/ethereum/go-ethereum/ethdb" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/trie/triestate" 32 ) 33 34 // State history records the state changes involved in executing a block. The 35 // state can be reverted to the previous version by applying the associated 36 // history object (state reverse diff). State history objects are kept to 37 // guarantee that the system can perform state rollbacks in case of deep reorg. 38 // 39 // Each state transition will generate a state history object. Note that not 40 // every block has a corresponding state history object. If a block performs 41 // no state changes whatsoever, no state is created for it. Each state history 42 // will have a sequentially increasing number acting as its unique identifier. 43 // 44 // The state history is written to disk (ancient store) when the corresponding 45 // diff layer is merged into the disk layer. At the same time, system can prune 46 // the oldest histories according to config. 47 // 48 // Disk State 49 // ^ 50 // | 51 // +------------+ +---------+ +---------+ +---------+ 52 // | Init State |---->| State 1 |---->| ... |---->| State n | 53 // +------------+ +---------+ +---------+ +---------+ 54 // 55 // +-----------+ +------+ +-----------+ 56 // | History 1 |----> | ... |---->| History n | 57 // +-----------+ +------+ +-----------+ 58 // 59 // # Rollback 60 // 61 // If the system wants to roll back to a previous state n, it needs to ensure 62 // all history objects from n+1 up to the current disk layer are existent. The 63 // history objects are applied to the state in reverse order, starting from the 64 // current disk layer. 65 66 const ( 67 accountIndexSize = common.AddressLength + 13 // The length of encoded account index 68 slotIndexSize = common.HashLength + 5 // The length of encoded slot index 69 historyMetaSize = 9 + 2*common.HashLength // The length of encoded history meta 70 71 stateHistoryVersion = uint8(0) // initial version of state history structure. 72 ) 73 74 // Each state history entry is consisted of five elements: 75 // 76 // # metadata 77 // This object contains a few meta fields, such as the associated state root, 78 // block number, version tag and so on. This object may contain an extra 79 // accountHash list which means the storage changes belong to these accounts 80 // are not complete due to large contract destruction. The incomplete history 81 // can not be used for rollback and serving archive state request. 82 // 83 // # account index 84 // This object contains some index information of account. For example, offset 85 // and length indicate the location of the data belonging to the account. Besides, 86 // storageOffset and storageSlots indicate the storage modification location 87 // belonging to the account. 88 // 89 // The size of each account index is *fixed*, and all indexes are sorted 90 // lexicographically. Thus binary search can be performed to quickly locate a 91 // specific account. 92 // 93 // # account data 94 // Account data is a concatenated byte stream composed of all account data. 95 // The account data can be solved by the offset and length info indicated 96 // by corresponding account index. 97 // 98 // fixed size 99 // ^ ^ 100 // / \ 101 // +-----------------+-----------------+----------------+-----------------+ 102 // | Account index 1 | Account index 2 | ... | Account index N | 103 // +-----------------+-----------------+----------------+-----------------+ 104 // | 105 // | length 106 // offset |----------------+ 107 // v v 108 // +----------------+----------------+----------------+----------------+ 109 // | Account data 1 | Account data 2 | ... | Account data N | 110 // +----------------+----------------+----------------+----------------+ 111 // 112 // # storage index 113 // This object is similar with account index. It's also fixed size and contains 114 // the location info of storage slot data. 115 // 116 // # storage data 117 // Storage data is a concatenated byte stream composed of all storage slot data. 118 // The storage slot data can be solved by the location info indicated by 119 // corresponding account index and storage slot index. 120 // 121 // fixed size 122 // ^ ^ 123 // / \ 124 // +-----------------+-----------------+----------------+-----------------+ 125 // | Account index 1 | Account index 2 | ... | Account index N | 126 // +-----------------+-----------------+----------------+-----------------+ 127 // | 128 // | storage slots 129 // storage offset |-----------------------------------------------------+ 130 // v v 131 // +-----------------+-----------------+-----------------+ 132 // | storage index 1 | storage index 2 | storage index 3 | 133 // +-----------------+-----------------+-----------------+ 134 // | length 135 // offset |-------------+ 136 // v v 137 // +-------------+ 138 // | slot data 1 | 139 // +-------------+ 140 141 // accountIndex describes the metadata belonging to an account. 142 type accountIndex struct { 143 address common.Address // The address of account 144 length uint8 // The length of account data, size limited by 255 145 offset uint32 // The offset of item in account data table 146 storageOffset uint32 // The offset of storage index in storage index table 147 storageSlots uint32 // The number of mutated storage slots belonging to the account 148 } 149 150 // encode packs account index into byte stream. 151 func (i *accountIndex) encode() []byte { 152 var buf [accountIndexSize]byte 153 copy(buf[:], i.address.Bytes()) 154 buf[common.AddressLength] = i.length 155 binary.BigEndian.PutUint32(buf[common.AddressLength+1:], i.offset) 156 binary.BigEndian.PutUint32(buf[common.AddressLength+5:], i.storageOffset) 157 binary.BigEndian.PutUint32(buf[common.AddressLength+9:], i.storageSlots) 158 return buf[:] 159 } 160 161 // decode unpacks account index from byte stream. 162 func (i *accountIndex) decode(blob []byte) { 163 i.address = common.BytesToAddress(blob[:common.AddressLength]) 164 i.length = blob[common.AddressLength] 165 i.offset = binary.BigEndian.Uint32(blob[common.AddressLength+1:]) 166 i.storageOffset = binary.BigEndian.Uint32(blob[common.AddressLength+5:]) 167 i.storageSlots = binary.BigEndian.Uint32(blob[common.AddressLength+9:]) 168 } 169 170 // slotIndex describes the metadata belonging to a storage slot. 171 type slotIndex struct { 172 hash common.Hash // The hash of slot key 173 length uint8 // The length of storage slot, up to 32 bytes defined in protocol 174 offset uint32 // The offset of item in storage slot data table 175 } 176 177 // encode packs slot index into byte stream. 178 func (i *slotIndex) encode() []byte { 179 var buf [slotIndexSize]byte 180 copy(buf[:common.HashLength], i.hash.Bytes()) 181 buf[common.HashLength] = i.length 182 binary.BigEndian.PutUint32(buf[common.HashLength+1:], i.offset) 183 return buf[:] 184 } 185 186 // decode unpack slot index from the byte stream. 187 func (i *slotIndex) decode(blob []byte) { 188 i.hash = common.BytesToHash(blob[:common.HashLength]) 189 i.length = blob[common.HashLength] 190 i.offset = binary.BigEndian.Uint32(blob[common.HashLength+1:]) 191 } 192 193 // meta describes the meta data of state history object. 194 type meta struct { 195 version uint8 // version tag of history object 196 parent common.Hash // prev-state root before the state transition 197 root common.Hash // post-state root after the state transition 198 block uint64 // associated block number 199 } 200 201 // encode packs the meta object into byte stream. 202 func (m *meta) encode() []byte { 203 buf := make([]byte, historyMetaSize) 204 buf[0] = m.version 205 copy(buf[1:1+common.HashLength], m.parent.Bytes()) 206 copy(buf[1+common.HashLength:1+2*common.HashLength], m.root.Bytes()) 207 binary.BigEndian.PutUint64(buf[1+2*common.HashLength:historyMetaSize], m.block) 208 return buf[:] 209 } 210 211 // decode unpacks the meta object from byte stream. 212 func (m *meta) decode(blob []byte) error { 213 if len(blob) < 1 { 214 return errors.New("no version tag") 215 } 216 switch blob[0] { 217 case stateHistoryVersion: 218 if len(blob) != historyMetaSize { 219 return fmt.Errorf("invalid state history meta, len: %d", len(blob)) 220 } 221 m.version = blob[0] 222 m.parent = common.BytesToHash(blob[1 : 1+common.HashLength]) 223 m.root = common.BytesToHash(blob[1+common.HashLength : 1+2*common.HashLength]) 224 m.block = binary.BigEndian.Uint64(blob[1+2*common.HashLength : historyMetaSize]) 225 return nil 226 default: 227 return fmt.Errorf("unknown version %d", blob[0]) 228 } 229 } 230 231 // history represents a set of state changes belong to a block along with 232 // the metadata including the state roots involved in the state transition. 233 // State history objects in disk are linked with each other by a unique id 234 // (8-bytes integer), the oldest state history object can be pruned on demand 235 // in order to control the storage size. 236 type history struct { 237 meta *meta // Meta data of history 238 accounts map[common.Address][]byte // Account data keyed by its address hash 239 accountList []common.Address // Sorted account hash list 240 storages map[common.Address]map[common.Hash][]byte // Storage data keyed by its address hash and slot hash 241 storageList map[common.Address][]common.Hash // Sorted slot hash list 242 } 243 244 // newHistory constructs the state history object with provided state change set. 245 func newHistory(root common.Hash, parent common.Hash, block uint64, states *triestate.Set) *history { 246 var ( 247 accountList []common.Address 248 storageList = make(map[common.Address][]common.Hash) 249 ) 250 for addr := range states.Accounts { 251 accountList = append(accountList, addr) 252 } 253 slices.SortFunc(accountList, common.Address.Cmp) 254 255 for addr, slots := range states.Storages { 256 slist := make([]common.Hash, 0, len(slots)) 257 for slotHash := range slots { 258 slist = append(slist, slotHash) 259 } 260 slices.SortFunc(slist, common.Hash.Cmp) 261 storageList[addr] = slist 262 } 263 return &history{ 264 meta: &meta{ 265 version: stateHistoryVersion, 266 parent: parent, 267 root: root, 268 block: block, 269 }, 270 accounts: states.Accounts, 271 accountList: accountList, 272 storages: states.Storages, 273 storageList: storageList, 274 } 275 } 276 277 // encode serializes the state history and returns four byte streams represent 278 // concatenated account/storage data, account/storage indexes respectively. 279 func (h *history) encode() ([]byte, []byte, []byte, []byte) { 280 var ( 281 slotNumber uint32 // the number of processed slots 282 accountData []byte // the buffer for concatenated account data 283 storageData []byte // the buffer for concatenated storage data 284 accountIndexes []byte // the buffer for concatenated account index 285 storageIndexes []byte // the buffer for concatenated storage index 286 ) 287 for _, addr := range h.accountList { 288 accIndex := accountIndex{ 289 address: addr, 290 length: uint8(len(h.accounts[addr])), 291 offset: uint32(len(accountData)), 292 } 293 slots, exist := h.storages[addr] 294 if exist { 295 // Encode storage slots in order 296 for _, slotHash := range h.storageList[addr] { 297 sIndex := slotIndex{ 298 hash: slotHash, 299 length: uint8(len(slots[slotHash])), 300 offset: uint32(len(storageData)), 301 } 302 storageData = append(storageData, slots[slotHash]...) 303 storageIndexes = append(storageIndexes, sIndex.encode()...) 304 } 305 // Fill up the storage meta in account index 306 accIndex.storageOffset = slotNumber 307 accIndex.storageSlots = uint32(len(slots)) 308 slotNumber += uint32(len(slots)) 309 } 310 accountData = append(accountData, h.accounts[addr]...) 311 accountIndexes = append(accountIndexes, accIndex.encode()...) 312 } 313 return accountData, storageData, accountIndexes, storageIndexes 314 } 315 316 // decoder wraps the byte streams for decoding with extra meta fields. 317 type decoder struct { 318 accountData []byte // the buffer for concatenated account data 319 storageData []byte // the buffer for concatenated storage data 320 accountIndexes []byte // the buffer for concatenated account index 321 storageIndexes []byte // the buffer for concatenated storage index 322 323 lastAccount *common.Address // the address of last resolved account 324 lastAccountRead uint32 // the read-cursor position of account data 325 lastSlotIndexRead uint32 // the read-cursor position of storage slot index 326 lastSlotDataRead uint32 // the read-cursor position of storage slot data 327 } 328 329 // verify validates the provided byte streams for decoding state history. A few 330 // checks will be performed to quickly detect data corruption. The byte stream 331 // is regarded as corrupted if: 332 // 333 // - account indexes buffer is empty(empty state set is invalid) 334 // - account indexes/storage indexer buffer is not aligned 335 // 336 // note, these situations are allowed: 337 // 338 // - empty account data: all accounts were not present 339 // - empty storage set: no slots are modified 340 func (r *decoder) verify() error { 341 if len(r.accountIndexes)%accountIndexSize != 0 || len(r.accountIndexes) == 0 { 342 return fmt.Errorf("invalid account index, len: %d", len(r.accountIndexes)) 343 } 344 if len(r.storageIndexes)%slotIndexSize != 0 { 345 return fmt.Errorf("invalid storage index, len: %d", len(r.storageIndexes)) 346 } 347 return nil 348 } 349 350 // readAccount parses the account from the byte stream with specified position. 351 func (r *decoder) readAccount(pos int) (accountIndex, []byte, error) { 352 // Decode account index from the index byte stream. 353 var index accountIndex 354 if (pos+1)*accountIndexSize > len(r.accountIndexes) { 355 return accountIndex{}, nil, errors.New("account data buffer is corrupted") 356 } 357 index.decode(r.accountIndexes[pos*accountIndexSize : (pos+1)*accountIndexSize]) 358 359 // Perform validation before parsing account data, ensure 360 // - account is sorted in order in byte stream 361 // - account data is strictly encoded with no gap inside 362 // - account data is not out-of-slice 363 if r.lastAccount != nil { // zero address is possible 364 if bytes.Compare(r.lastAccount.Bytes(), index.address.Bytes()) >= 0 { 365 return accountIndex{}, nil, errors.New("account is not in order") 366 } 367 } 368 if index.offset != r.lastAccountRead { 369 return accountIndex{}, nil, errors.New("account data buffer is gaped") 370 } 371 last := index.offset + uint32(index.length) 372 if uint32(len(r.accountData)) < last { 373 return accountIndex{}, nil, errors.New("account data buffer is corrupted") 374 } 375 data := r.accountData[index.offset:last] 376 377 r.lastAccount = &index.address 378 r.lastAccountRead = last 379 380 return index, data, nil 381 } 382 383 // readStorage parses the storage slots from the byte stream with specified account. 384 func (r *decoder) readStorage(accIndex accountIndex) ([]common.Hash, map[common.Hash][]byte, error) { 385 var ( 386 last common.Hash 387 list []common.Hash 388 storage = make(map[common.Hash][]byte) 389 ) 390 for j := 0; j < int(accIndex.storageSlots); j++ { 391 var ( 392 index slotIndex 393 start = (accIndex.storageOffset + uint32(j)) * uint32(slotIndexSize) 394 end = (accIndex.storageOffset + uint32(j+1)) * uint32(slotIndexSize) 395 ) 396 // Perform validation before parsing storage slot data, ensure 397 // - slot index is not out-of-slice 398 // - slot data is not out-of-slice 399 // - slot is sorted in order in byte stream 400 // - slot indexes is strictly encoded with no gap inside 401 // - slot data is strictly encoded with no gap inside 402 if start != r.lastSlotIndexRead { 403 return nil, nil, errors.New("storage index buffer is gapped") 404 } 405 if uint32(len(r.storageIndexes)) < end { 406 return nil, nil, errors.New("storage index buffer is corrupted") 407 } 408 index.decode(r.storageIndexes[start:end]) 409 410 if bytes.Compare(last.Bytes(), index.hash.Bytes()) >= 0 { 411 return nil, nil, errors.New("storage slot is not in order") 412 } 413 if index.offset != r.lastSlotDataRead { 414 return nil, nil, errors.New("storage data buffer is gapped") 415 } 416 sEnd := index.offset + uint32(index.length) 417 if uint32(len(r.storageData)) < sEnd { 418 return nil, nil, errors.New("storage data buffer is corrupted") 419 } 420 storage[index.hash] = r.storageData[r.lastSlotDataRead:sEnd] 421 list = append(list, index.hash) 422 423 last = index.hash 424 r.lastSlotIndexRead = end 425 r.lastSlotDataRead = sEnd 426 } 427 return list, storage, nil 428 } 429 430 // decode deserializes the account and storage data from the provided byte stream. 431 func (h *history) decode(accountData, storageData, accountIndexes, storageIndexes []byte) error { 432 var ( 433 accounts = make(map[common.Address][]byte) 434 storages = make(map[common.Address]map[common.Hash][]byte) 435 accountList []common.Address 436 storageList = make(map[common.Address][]common.Hash) 437 438 r = &decoder{ 439 accountData: accountData, 440 storageData: storageData, 441 accountIndexes: accountIndexes, 442 storageIndexes: storageIndexes, 443 } 444 ) 445 if err := r.verify(); err != nil { 446 return err 447 } 448 for i := 0; i < len(accountIndexes)/accountIndexSize; i++ { 449 // Resolve account first 450 accIndex, accData, err := r.readAccount(i) 451 if err != nil { 452 return err 453 } 454 accounts[accIndex.address] = accData 455 accountList = append(accountList, accIndex.address) 456 457 // Resolve storage slots 458 slotList, slotData, err := r.readStorage(accIndex) 459 if err != nil { 460 return err 461 } 462 if len(slotList) > 0 { 463 storageList[accIndex.address] = slotList 464 storages[accIndex.address] = slotData 465 } 466 } 467 h.accounts = accounts 468 h.accountList = accountList 469 h.storages = storages 470 h.storageList = storageList 471 return nil 472 } 473 474 // readHistory reads and decodes the state history object by the given id. 475 func readHistory(reader ethdb.AncientReader, id uint64) (*history, error) { 476 blob := rawdb.ReadStateHistoryMeta(reader, id) 477 if len(blob) == 0 { 478 return nil, fmt.Errorf("state history not found %d", id) 479 } 480 var m meta 481 if err := m.decode(blob); err != nil { 482 return nil, err 483 } 484 var ( 485 dec = history{meta: &m} 486 accountData = rawdb.ReadStateAccountHistory(reader, id) 487 storageData = rawdb.ReadStateStorageHistory(reader, id) 488 accountIndexes = rawdb.ReadStateAccountIndex(reader, id) 489 storageIndexes = rawdb.ReadStateStorageIndex(reader, id) 490 ) 491 if err := dec.decode(accountData, storageData, accountIndexes, storageIndexes); err != nil { 492 return nil, err 493 } 494 return &dec, nil 495 } 496 497 // writeHistory persists the state history with the provided state set. 498 func writeHistory(writer ethdb.AncientWriter, dl *diffLayer) error { 499 // Short circuit if state set is not available. 500 if dl.states == nil { 501 return errors.New("state change set is not available") 502 } 503 var ( 504 start = time.Now() 505 history = newHistory(dl.rootHash(), dl.parentLayer().rootHash(), dl.block, dl.states) 506 ) 507 accountData, storageData, accountIndex, storageIndex := history.encode() 508 dataSize := common.StorageSize(len(accountData) + len(storageData)) 509 indexSize := common.StorageSize(len(accountIndex) + len(storageIndex)) 510 511 // Write history data into five freezer table respectively. 512 rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData) 513 514 historyDataBytesMeter.Mark(int64(dataSize)) 515 historyIndexBytesMeter.Mark(int64(indexSize)) 516 historyBuildTimeMeter.UpdateSince(start) 517 log.Debug("Stored state history", "id", dl.stateID(), "block", dl.block, "data", dataSize, "index", indexSize, "elapsed", common.PrettyDuration(time.Since(start))) 518 519 return nil 520 } 521 522 // checkHistories retrieves a batch of meta objects with the specified range 523 // and performs the callback on each item. 524 func checkHistories(reader ethdb.AncientReader, start, count uint64, check func(*meta) error) error { 525 for count > 0 { 526 number := count 527 if number > 10000 { 528 number = 10000 // split the big read into small chunks 529 } 530 blobs, err := rawdb.ReadStateHistoryMetaList(reader, start, number) 531 if err != nil { 532 return err 533 } 534 for _, blob := range blobs { 535 var dec meta 536 if err := dec.decode(blob); err != nil { 537 return err 538 } 539 if err := check(&dec); err != nil { 540 return err 541 } 542 } 543 count -= uint64(len(blobs)) 544 start += uint64(len(blobs)) 545 } 546 return nil 547 } 548 549 // truncateFromHead removes the extra state histories from the head with the given 550 // parameters. It returns the number of items removed from the head. 551 func truncateFromHead(db ethdb.Batcher, store ethdb.AncientStore, nhead uint64) (int, error) { 552 ohead, err := store.Ancients() 553 if err != nil { 554 return 0, err 555 } 556 otail, err := store.Tail() 557 if err != nil { 558 return 0, err 559 } 560 // Ensure that the truncation target falls within the specified range. 561 if ohead < nhead || nhead < otail { 562 return 0, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", otail, ohead, nhead) 563 } 564 // Short circuit if nothing to truncate. 565 if ohead == nhead { 566 return 0, nil 567 } 568 // Load the meta objects in range [nhead+1, ohead] 569 blobs, err := rawdb.ReadStateHistoryMetaList(store, nhead+1, ohead-nhead) 570 if err != nil { 571 return 0, err 572 } 573 batch := db.NewBatch() 574 for _, blob := range blobs { 575 var m meta 576 if err := m.decode(blob); err != nil { 577 return 0, err 578 } 579 rawdb.DeleteStateID(batch, m.root) 580 } 581 if err := batch.Write(); err != nil { 582 return 0, err 583 } 584 ohead, err = store.TruncateHead(nhead) 585 if err != nil { 586 return 0, err 587 } 588 return int(ohead - nhead), nil 589 } 590 591 // truncateFromTail removes the extra state histories from the tail with the given 592 // parameters. It returns the number of items removed from the tail. 593 func truncateFromTail(db ethdb.Batcher, store ethdb.AncientStore, ntail uint64) (int, error) { 594 ohead, err := store.Ancients() 595 if err != nil { 596 return 0, err 597 } 598 otail, err := store.Tail() 599 if err != nil { 600 return 0, err 601 } 602 // Ensure that the truncation target falls within the specified range. 603 if otail > ntail || ntail > ohead { 604 return 0, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", otail, ohead, ntail) 605 } 606 // Short circuit if nothing to truncate. 607 if otail == ntail { 608 return 0, nil 609 } 610 // Load the meta objects in range [otail+1, ntail] 611 blobs, err := rawdb.ReadStateHistoryMetaList(store, otail+1, ntail-otail) 612 if err != nil { 613 return 0, err 614 } 615 batch := db.NewBatch() 616 for _, blob := range blobs { 617 var m meta 618 if err := m.decode(blob); err != nil { 619 return 0, err 620 } 621 rawdb.DeleteStateID(batch, m.root) 622 } 623 if err := batch.Write(); err != nil { 624 return 0, err 625 } 626 otail, err = store.TruncateTail(ntail) 627 if err != nil { 628 return 0, err 629 } 630 return int(ntail - otail), nil 631 }