github.com/ethereum/go-ethereum@v1.16.1/core/rawdb/accessors_state.go (about)

     1  // Copyright 2020 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 rawdb
    18  
    19  import (
    20  	"encoding/binary"
    21  	"errors"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/ethdb"
    25  	"github.com/ethereum/go-ethereum/log"
    26  )
    27  
    28  // ReadPreimage retrieves a single preimage of the provided hash.
    29  func ReadPreimage(db ethdb.KeyValueReader, hash common.Hash) []byte {
    30  	data, _ := db.Get(preimageKey(hash))
    31  	if len(data) == 0 {
    32  		preimageMissCounter.Inc(1)
    33  	} else {
    34  		preimageHitsCounter.Inc(1)
    35  	}
    36  	return data
    37  }
    38  
    39  // WritePreimages writes the provided set of preimages to the database.
    40  func WritePreimages(db ethdb.KeyValueWriter, preimages map[common.Hash][]byte) {
    41  	for hash, preimage := range preimages {
    42  		if err := db.Put(preimageKey(hash), preimage); err != nil {
    43  			log.Crit("Failed to store trie preimage", "err", err)
    44  		}
    45  	}
    46  	preimageCounter.Inc(int64(len(preimages)))
    47  }
    48  
    49  // ReadCode retrieves the contract code of the provided code hash.
    50  func ReadCode(db ethdb.KeyValueReader, hash common.Hash) []byte {
    51  	// Try with the prefixed code scheme first, if not then try with legacy
    52  	// scheme.
    53  	data := ReadCodeWithPrefix(db, hash)
    54  	if len(data) != 0 {
    55  		return data
    56  	}
    57  	data, _ = db.Get(hash.Bytes())
    58  	return data
    59  }
    60  
    61  // ReadCodeWithPrefix retrieves the contract code of the provided code hash.
    62  // The main difference between this function and ReadCode is this function
    63  // will only check the existence with latest scheme(with prefix).
    64  func ReadCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) []byte {
    65  	data, _ := db.Get(codeKey(hash))
    66  	return data
    67  }
    68  
    69  // HasCode checks if the contract code corresponding to the
    70  // provided code hash is present in the db.
    71  func HasCode(db ethdb.KeyValueReader, hash common.Hash) bool {
    72  	// Try with the prefixed code scheme first, if not then try with legacy
    73  	// scheme.
    74  	if ok := HasCodeWithPrefix(db, hash); ok {
    75  		return true
    76  	}
    77  	ok, _ := db.Has(hash.Bytes())
    78  	return ok
    79  }
    80  
    81  // HasCodeWithPrefix checks if the contract code corresponding to the
    82  // provided code hash is present in the db. This function will only check
    83  // presence using the prefix-scheme.
    84  func HasCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) bool {
    85  	ok, _ := db.Has(codeKey(hash))
    86  	return ok
    87  }
    88  
    89  // WriteCode writes the provided contract code database.
    90  func WriteCode(db ethdb.KeyValueWriter, hash common.Hash, code []byte) {
    91  	if err := db.Put(codeKey(hash), code); err != nil {
    92  		log.Crit("Failed to store contract code", "err", err)
    93  	}
    94  }
    95  
    96  // DeleteCode deletes the specified contract code from the database.
    97  func DeleteCode(db ethdb.KeyValueWriter, hash common.Hash) {
    98  	if err := db.Delete(codeKey(hash)); err != nil {
    99  		log.Crit("Failed to delete contract code", "err", err)
   100  	}
   101  }
   102  
   103  // ReadStateID retrieves the state id with the provided state root.
   104  func ReadStateID(db ethdb.KeyValueReader, root common.Hash) *uint64 {
   105  	data, err := db.Get(stateIDKey(root))
   106  	if err != nil || len(data) == 0 {
   107  		return nil
   108  	}
   109  	number := binary.BigEndian.Uint64(data)
   110  	return &number
   111  }
   112  
   113  // WriteStateID writes the provided state lookup to database.
   114  func WriteStateID(db ethdb.KeyValueWriter, root common.Hash, id uint64) {
   115  	var buff [8]byte
   116  	binary.BigEndian.PutUint64(buff[:], id)
   117  	if err := db.Put(stateIDKey(root), buff[:]); err != nil {
   118  		log.Crit("Failed to store state ID", "err", err)
   119  	}
   120  }
   121  
   122  // DeleteStateID deletes the specified state lookup from the database.
   123  func DeleteStateID(db ethdb.KeyValueWriter, root common.Hash) {
   124  	if err := db.Delete(stateIDKey(root)); err != nil {
   125  		log.Crit("Failed to delete state ID", "err", err)
   126  	}
   127  }
   128  
   129  // ReadPersistentStateID retrieves the id of the persistent state from the database.
   130  func ReadPersistentStateID(db ethdb.KeyValueReader) uint64 {
   131  	data, _ := db.Get(persistentStateIDKey)
   132  	if len(data) != 8 {
   133  		return 0
   134  	}
   135  	return binary.BigEndian.Uint64(data)
   136  }
   137  
   138  // WritePersistentStateID stores the id of the persistent state into database.
   139  func WritePersistentStateID(db ethdb.KeyValueWriter, number uint64) {
   140  	if err := db.Put(persistentStateIDKey, encodeBlockNumber(number)); err != nil {
   141  		log.Crit("Failed to store the persistent state ID", "err", err)
   142  	}
   143  }
   144  
   145  // ReadTrieJournal retrieves the serialized in-memory trie nodes of layers saved at
   146  // the last shutdown.
   147  func ReadTrieJournal(db ethdb.KeyValueReader) []byte {
   148  	data, _ := db.Get(trieJournalKey)
   149  	return data
   150  }
   151  
   152  // WriteTrieJournal stores the serialized in-memory trie nodes of layers to save at
   153  // shutdown.
   154  func WriteTrieJournal(db ethdb.KeyValueWriter, journal []byte) {
   155  	if err := db.Put(trieJournalKey, journal); err != nil {
   156  		log.Crit("Failed to store tries journal", "err", err)
   157  	}
   158  }
   159  
   160  // DeleteTrieJournal deletes the serialized in-memory trie nodes of layers saved at
   161  // the last shutdown.
   162  func DeleteTrieJournal(db ethdb.KeyValueWriter) {
   163  	if err := db.Delete(trieJournalKey); err != nil {
   164  		log.Crit("Failed to remove tries journal", "err", err)
   165  	}
   166  }
   167  
   168  // ReadStateHistoryMeta retrieves the metadata corresponding to the specified
   169  // state history. Compute the position of state history in freezer by minus
   170  // one since the id of first state history starts from one(zero for initial
   171  // state).
   172  func ReadStateHistoryMeta(db ethdb.AncientReaderOp, id uint64) []byte {
   173  	blob, err := db.Ancient(stateHistoryMeta, id-1)
   174  	if err != nil {
   175  		return nil
   176  	}
   177  	return blob
   178  }
   179  
   180  // ReadStateHistoryMetaList retrieves a batch of meta objects with the specified
   181  // start position and count. Compute the position of state history in freezer by
   182  // minus one since the id of first state history starts from one(zero for initial
   183  // state).
   184  func ReadStateHistoryMetaList(db ethdb.AncientReaderOp, start uint64, count uint64) ([][]byte, error) {
   185  	return db.AncientRange(stateHistoryMeta, start-1, count, 0)
   186  }
   187  
   188  // ReadStateAccountIndex retrieves the state root corresponding to the specified
   189  // state history. Compute the position of state history in freezer by minus one
   190  // since the id of first state history starts from one(zero for initial state).
   191  func ReadStateAccountIndex(db ethdb.AncientReaderOp, id uint64) []byte {
   192  	blob, err := db.Ancient(stateHistoryAccountIndex, id-1)
   193  	if err != nil {
   194  		return nil
   195  	}
   196  	return blob
   197  }
   198  
   199  // ReadStateStorageIndex retrieves the state root corresponding to the specified
   200  // state history. Compute the position of state history in freezer by minus one
   201  // since the id of first state history starts from one(zero for initial state).
   202  func ReadStateStorageIndex(db ethdb.AncientReaderOp, id uint64) []byte {
   203  	blob, err := db.Ancient(stateHistoryStorageIndex, id-1)
   204  	if err != nil {
   205  		return nil
   206  	}
   207  	return blob
   208  }
   209  
   210  // ReadStateAccountHistory retrieves the state root corresponding to the specified
   211  // state history. Compute the position of state history in freezer by minus one
   212  // since the id of first state history starts from one(zero for initial state).
   213  func ReadStateAccountHistory(db ethdb.AncientReaderOp, id uint64) []byte {
   214  	blob, err := db.Ancient(stateHistoryAccountData, id-1)
   215  	if err != nil {
   216  		return nil
   217  	}
   218  	return blob
   219  }
   220  
   221  // ReadStateStorageHistory retrieves the state root corresponding to the specified
   222  // state history. Compute the position of state history in freezer by minus one
   223  // since the id of first state history starts from one(zero for initial state).
   224  func ReadStateStorageHistory(db ethdb.AncientReaderOp, id uint64) []byte {
   225  	blob, err := db.Ancient(stateHistoryStorageData, id-1)
   226  	if err != nil {
   227  		return nil
   228  	}
   229  	return blob
   230  }
   231  
   232  // ReadStateHistory retrieves the state history from database with provided id.
   233  // Compute the position of state history in freezer by minus one since the id
   234  // of first state history starts from one(zero for initial state).
   235  func ReadStateHistory(db ethdb.AncientReaderOp, id uint64) ([]byte, []byte, []byte, []byte, []byte, error) {
   236  	meta, err := db.Ancient(stateHistoryMeta, id-1)
   237  	if err != nil {
   238  		return nil, nil, nil, nil, nil, err
   239  	}
   240  	accountIndex, err := db.Ancient(stateHistoryAccountIndex, id-1)
   241  	if err != nil {
   242  		return nil, nil, nil, nil, nil, err
   243  	}
   244  	storageIndex, err := db.Ancient(stateHistoryStorageIndex, id-1)
   245  	if err != nil {
   246  		return nil, nil, nil, nil, nil, err
   247  	}
   248  	accountData, err := db.Ancient(stateHistoryAccountData, id-1)
   249  	if err != nil {
   250  		return nil, nil, nil, nil, nil, err
   251  	}
   252  	storageData, err := db.Ancient(stateHistoryStorageData, id-1)
   253  	if err != nil {
   254  		return nil, nil, nil, nil, nil, err
   255  	}
   256  	return meta, accountIndex, storageIndex, accountData, storageData, nil
   257  }
   258  
   259  // ReadStateHistoryList retrieves a list of state histories from database with
   260  // specific range. Compute the position of state history in freezer by minus one
   261  // since the id of first state history starts from one(zero for initial state).
   262  func ReadStateHistoryList(db ethdb.AncientReaderOp, start uint64, count uint64) ([][]byte, [][]byte, [][]byte, [][]byte, [][]byte, error) {
   263  	metaList, err := db.AncientRange(stateHistoryMeta, start-1, count, 0)
   264  	if err != nil {
   265  		return nil, nil, nil, nil, nil, err
   266  	}
   267  	aIndexList, err := db.AncientRange(stateHistoryAccountIndex, start-1, count, 0)
   268  	if err != nil {
   269  		return nil, nil, nil, nil, nil, err
   270  	}
   271  	sIndexList, err := db.AncientRange(stateHistoryStorageIndex, start-1, count, 0)
   272  	if err != nil {
   273  		return nil, nil, nil, nil, nil, err
   274  	}
   275  	aDataList, err := db.AncientRange(stateHistoryAccountData, start-1, count, 0)
   276  	if err != nil {
   277  		return nil, nil, nil, nil, nil, err
   278  	}
   279  	sDataList, err := db.AncientRange(stateHistoryStorageData, start-1, count, 0)
   280  	if err != nil {
   281  		return nil, nil, nil, nil, nil, err
   282  	}
   283  	if len(metaList) != len(aIndexList) || len(metaList) != len(sIndexList) || len(metaList) != len(aDataList) || len(metaList) != len(sDataList) {
   284  		return nil, nil, nil, nil, nil, errors.New("state history is corrupted")
   285  	}
   286  	return metaList, aIndexList, sIndexList, aDataList, sDataList, nil
   287  }
   288  
   289  // WriteStateHistory writes the provided state history to database. Compute the
   290  // position of state history in freezer by minus one since the id of first state
   291  // history starts from one(zero for initial state).
   292  func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) error {
   293  	_, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
   294  		if err := op.AppendRaw(stateHistoryMeta, id-1, meta); err != nil {
   295  			return err
   296  		}
   297  		if err := op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex); err != nil {
   298  			return err
   299  		}
   300  		if err := op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex); err != nil {
   301  			return err
   302  		}
   303  		if err := op.AppendRaw(stateHistoryAccountData, id-1, accounts); err != nil {
   304  			return err
   305  		}
   306  		return op.AppendRaw(stateHistoryStorageData, id-1, storages)
   307  	})
   308  	return err
   309  }