Add prefix for validator wrapper (#4402)

* add separate prefix for validator wrapper

* update comments

* make read/write backward compatible

* add validator codes to stats

* goimports

* goimports accessor_state
pull/4409/head
Gheis Mohammadi 2 years ago committed by GitHub
parent 7d47d9e8a9
commit 53161ca33c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      core/genesis.go
  2. 54
      core/rawdb/accessors_state.go
  3. 4
      core/rawdb/database.go
  4. 23
      core/rawdb/schema.go
  5. 47
      core/state/database.go
  6. 2
      core/state/dump.go
  7. 6
      core/state/iterator.go
  8. 2
      core/state/iterator_test.go
  9. 2
      core/state/journal.go
  10. 2
      core/state/prefeth.go
  11. 43
      core/state/state_object.go
  12. 8
      core/state/state_test.go
  13. 27
      core/state/statedb.go
  14. 44
      core/state/statedb_test.go
  15. 6
      core/state/trie_prefetcher_test.go
  16. 2
      core/vm/contracts_write.go
  17. 10
      core/vm/evm.go
  18. 2
      core/vm/gas_table_test.go
  19. 4
      core/vm/instructions.go
  20. 6
      core/vm/interface.go
  21. 8
      core/vm/logger_test.go
  22. 2
      core/vm/runtime/runtime.go
  23. 4
      core/vm/runtime/runtime_test.go
  24. 2
      hmy/tracers/block_tracer.go
  25. 2
      hmy/tracers/tracer.go
  26. 4
      rosetta/services/block.go
  27. 2
      rosetta/services/construction_check.go
  28. 2
      rpc/contract.go
  29. 6
      staking/availability/measure_test.go

@ -247,7 +247,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db), nil)
for addr, account := range g.Alloc {
statedb.AddBalance(addr, account.Balance)
statedb.SetCode(addr, account.Code)
statedb.SetCode(addr, account.Code, false)
statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage {
statedb.SetState(addr, key, value)

@ -93,3 +93,57 @@ func DeleteCode(db ethdb.KeyValueWriter, hash common.Hash) {
utils.Logger().Error().Err(err).Msg("Failed to delete contract code")
}
}
// ReadValidatorCode retrieves the validator code of the provided code hash.
func ReadValidatorCode(db ethdb.KeyValueReader, hash common.Hash) []byte {
// Try with the prefixed code scheme first, if not then try with legacy
// scheme.
data := ReadValidatorCodeWithPrefix(db, hash)
if len(data) != 0 {
return data
}
data, _ = db.Get(hash.Bytes())
return data
}
// ReadValidatorCodeWithPrefix retrieves the validator code of the provided code hash.
// The main difference between this function and ReadValidatorCode is this function
// will only check the existence with latest scheme(with prefix).
func ReadValidatorCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) []byte {
data, _ := db.Get(validatorCodeKey(hash))
return data
}
// HasValidatorCode checks if the validator code corresponding to the
// provided code hash is present in the db.
func HasValidatorCode(db ethdb.KeyValueReader, hash common.Hash) bool {
// Try with the prefixed code scheme first, if not then try with legacy
// scheme.
if ok := HasValidatorCodeWithPrefix(db, hash); ok {
return true
}
ok, _ := db.Has(hash.Bytes())
return ok
}
// HasValidatorCodeWithPrefix checks if the validator code corresponding to the
// provided code hash is present in the db. This function will only check
// presence using the prefix-scheme.
func HasValidatorCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) bool {
ok, _ := db.Has(validatorCodeKey(hash))
return ok
}
// WriteValidatorCode writes the provided validator code to database.
func WriteValidatorCode(db ethdb.KeyValueWriter, hash common.Hash, code []byte) {
if err := db.Put(validatorCodeKey(hash), code); err != nil {
utils.Logger().Error().Err(err).Msg("Failed to store validator code")
}
}
// DeleteValidatorCode deletes the specified validator code from the database.
func DeleteValidatorCode(db ethdb.KeyValueWriter, hash common.Hash) {
if err := db.Delete(validatorCodeKey(hash)); err != nil {
utils.Logger().Error().Err(err).Msg("Failed to delete validator code")
}
}

@ -316,6 +316,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
hashNumPairings stat
tries stat
codes stat
validatorCodes stat
txLookups stat
accountSnaps stat
storageSnaps stat
@ -359,6 +360,8 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
tries.Add(size)
case bytes.HasPrefix(key, CodePrefix) && len(key) == len(CodePrefix)+common.HashLength:
codes.Add(size)
case bytes.HasPrefix(key, ValidatorCodePrefix) && len(key) == len(ValidatorCodePrefix)+common.HashLength:
validatorCodes.Add(size)
case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength):
txLookups.Add(size)
case bytes.HasPrefix(key, SnapshotAccountPrefix) && len(key) == (len(SnapshotAccountPrefix)+common.HashLength):
@ -422,6 +425,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
{"Key-Value store", "Transaction index", txLookups.Size(), txLookups.Count()},
{"Key-Value store", "Bloombit index", bloomBits.Size(), bloomBits.Count()},
{"Key-Value store", "Contract codes", codes.Size(), codes.Count()},
{"Key-Value store", "Validator codes", validatorCodes.Size(), validatorCodes.Count()},
{"Key-Value store", "Trie nodes", tries.Size(), tries.Count()},
{"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()},
{"Key-Value store", "Account snapshot", accountSnaps.Size(), accountSnaps.Count()},

@ -126,10 +126,11 @@ var (
snapdbInfoKey = []byte("SnapdbInfo")
// Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes).
SnapshotAccountPrefix = []byte("a") // SnapshotAccountPrefix + account hash -> account trie value
SnapshotStoragePrefix = []byte("o") // SnapshotStoragePrefix + account hash + storage hash -> storage trie value
CodePrefix = []byte("c") // CodePrefix + code hash -> account code -> We not using this at the moment
skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header
SnapshotAccountPrefix = []byte("a") // SnapshotAccountPrefix + account hash -> account trie value
SnapshotStoragePrefix = []byte("o") // SnapshotStoragePrefix + account hash + storage hash -> storage trie value
CodePrefix = []byte("c") // CodePrefix + code hash -> account code
ValidatorCodePrefix = []byte("vc") // ValidatorCodePrefix + code hash -> validator code
skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header
// Path-based trie node scheme.
trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node
@ -196,6 +197,20 @@ func IsCodeKey(key []byte) (bool, []byte) {
return false, nil
}
// validatorCodeKey = ValidatorCodePrefix + hash
func validatorCodeKey(hash common.Hash) []byte {
return append(ValidatorCodePrefix, hash.Bytes()...)
}
// IsValidatorCodeKey reports whether the given byte slice is the key of validator code,
// if so return the raw code hash as well.
func IsValidatorCodeKey(key []byte) (bool, []byte) {
if bytes.HasPrefix(key, ValidatorCodePrefix) && len(key) == common.HashLength+len(ValidatorCodePrefix) {
return true, key[len(ValidatorCodePrefix):]
}
return false, nil
}
// genesisStateSpecKey = genesisPrefix + hash
func genesisStateSpecKey(hash common.Hash) []byte {
return append(genesisPrefix, hash.Bytes()...)

@ -53,6 +53,12 @@ type Database interface {
// ContractCodeSize retrieves a particular contracts code's size.
ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
// ValidatorCode retrieves a particular validator's code.
ValidatorCode(addrHash, codeHash common.Hash) ([]byte, error)
// ValidatorCodeSize retrieves a particular validator code's size.
ValidatorCodeSize(addrHash, codeHash common.Hash) (int, error)
// DiskDB returns the underlying key-value disk database.
DiskDB() ethdb.KeyValueStore
@ -234,6 +240,47 @@ func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, erro
return len(code), err
}
// ValidatorCodeSize retrieves a particular validators code's size.
func (db *cachingDB) ValidatorCodeSize(addrHash, codeHash common.Hash) (int, error) {
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
return cached, nil
}
code, err := db.ValidatorCode(addrHash, codeHash)
return len(code), err
}
// ValidatorCode retrieves a particular validator's code.
func (db *cachingDB) ValidatorCode(addrHash, codeHash common.Hash) ([]byte, error) {
code, _ := db.codeCache.Get(codeHash)
if len(code) > 0 {
return code, nil
}
code = rawdb.ReadValidatorCode(db.disk, codeHash)
if len(code) > 0 {
db.codeCache.Add(codeHash, code)
db.codeSizeCache.Add(codeHash, len(code))
return code, nil
}
return nil, errors.New("not found")
}
// ValidatorCodeWithPrefix retrieves a particular validator's code. If the
// code can't be found in the cache, then check the existence with **new**
// db scheme.
func (db *cachingDB) ValidatorCodeWithPrefix(addrHash, codeHash common.Hash) ([]byte, error) {
code, _ := db.codeCache.Get(codeHash)
if len(code) > 0 {
return code, nil
}
code = rawdb.ReadValidatorCodeWithPrefix(db.disk, codeHash)
if len(code) > 0 {
db.codeCache.Add(codeHash, code)
db.codeSizeCache.Add(codeHash, len(code))
return code, nil
}
return nil, errors.New("not found")
}
// DiskDB returns the underlying key-value disk database.
func (db *cachingDB) DiskDB() ethdb.KeyValueStore {
return db.disk

@ -165,7 +165,7 @@ func (s *DB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte)
addr := common.BytesToAddress(addrBytes)
obj := newObject(s, addr, data)
if !conf.SkipCode {
account.Code = obj.Code(s.db)
account.Code = obj.Code(s.db, false)
}
if !conf.SkipStorage {
account.Storage = make(map[common.Hash]string)

@ -124,6 +124,12 @@ func (it *NodeIterator) step() error {
if err != nil {
return fmt.Errorf("code %x: %v", account.CodeHash, err)
}
if it.code == nil || len(it.code) == 0 {
it.code, err = it.state.db.ValidatorCode(addrHash, common.BytesToHash(account.CodeHash))
if err != nil {
return fmt.Errorf("code %x: %v", account.CodeHash, err)
}
}
}
it.accountHash = it.stateIt.Parent()
return nil

@ -54,7 +54,7 @@ func makeTestState() (ethdb.Database, Database, common.Hash, []*testAccount) {
acc.nonce = uint64(42 * i)
if i%3 == 0 {
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i}, false)
acc.code = []byte{i, i, i, i, i}
}
if i%5 == 0 {

@ -217,7 +217,7 @@ func (ch nonceChange) dirtied() *common.Address {
}
func (ch codeChange) revert(s *DB) {
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode, false)
}
func (ch codeChange) dirtied() *common.Address {

@ -100,7 +100,7 @@ func (s *DB) prefetchWorker(job *prefetchJob, jobs chan *prefetchJob) {
addr := common.BytesToAddress(addrBytes)
obj := newObject(s, addr, data)
if data.CodeHash != nil {
obj.Code(s.db)
obj.Code(s.db, false)
}
// build account trie tree

@ -93,9 +93,10 @@ type Object struct {
// Cache flags.
// When an object is marked suicided it will be delete from the trie
// during the "update" phase of the state transition.
dirtyCode bool // true if the code was updated
suicided bool
deleted bool
validatorWrapper bool // true if the code belongs to validator wrapper
dirtyCode bool // true if the code was updated
suicided bool
deleted bool
}
// empty returns whether the account is considered empty.
@ -497,14 +498,24 @@ func (s *Object) Address() common.Address {
return s.address
}
// Code returns the contract code associated with this object, if any.
func (s *Object) Code(db Database) []byte {
// Code returns the contract/validator code associated with this object, if any.
func (s *Object) Code(db Database, isValidatorCode bool) []byte {
if s.code != nil {
return s.code
}
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
return nil
}
if s.validatorWrapper || isValidatorCode {
code, err := db.ValidatorCode(s.addrHash, common.BytesToHash(s.CodeHash()))
if err != nil {
s.setError(fmt.Errorf("can't load validator code hash %x: %v", s.CodeHash(), err))
}
if code != nil {
s.code = code
return code
}
}
code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash()))
if err != nil {
s.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err))
@ -513,16 +524,25 @@ func (s *Object) Code(db Database) []byte {
return code
}
// CodeSize returns the size of the contract code associated with this object,
// CodeSize returns the size of the contract/validator code associated with this object,
// or zero if none. This method is an almost mirror of Code, but uses a cache
// inside the database to avoid loading codes seen recently.
func (s *Object) CodeSize(db Database) int {
func (s *Object) CodeSize(db Database, isValidatorCode bool) int {
if s.code != nil {
return len(s.code)
}
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
return 0
}
if s.validatorWrapper || isValidatorCode {
size, err := db.ValidatorCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))
if err != nil {
s.setError(fmt.Errorf("can't load validator code size %x: %v", s.CodeHash(), err))
}
if size > 0 {
return size
}
}
size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))
if err != nil {
s.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err))
@ -530,20 +550,21 @@ func (s *Object) CodeSize(db Database) int {
return size
}
func (s *Object) SetCode(codeHash common.Hash, code []byte) {
prevcode := s.Code(s.db.db)
func (s *Object) SetCode(codeHash common.Hash, code []byte, isValidatorCode bool) {
prevcode := s.Code(s.db.db, isValidatorCode)
s.db.journal.append(codeChange{
account: &s.address,
prevhash: s.CodeHash(),
prevcode: prevcode,
})
s.setCode(codeHash, code)
s.setCode(codeHash, code, isValidatorCode)
}
func (s *Object) setCode(codeHash common.Hash, code []byte) {
func (s *Object) setCode(codeHash common.Hash, code []byte, isValidatorCode bool) {
s.code = code
s.data.CodeHash = codeHash[:]
s.dirtyCode = true
s.validatorWrapper = isValidatorCode
}
func (s *Object) SetNonce(nonce uint64) {

@ -48,7 +48,7 @@ func TestDump(t *testing.T) {
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
obj1.AddBalance(big.NewInt(22))
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}, false)
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
obj3.SetBalance(big.NewInt(44))
@ -166,7 +166,7 @@ func TestSnapshot2(t *testing.T) {
so0 := state.getStateObject(stateobjaddr0)
so0.SetBalance(big.NewInt(42))
so0.SetNonce(43)
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}, false)
so0.suicided = false
so0.deleted = false
state.setStateObject(so0)
@ -178,7 +178,7 @@ func TestSnapshot2(t *testing.T) {
so1 := state.getStateObject(stateobjaddr1)
so1.SetBalance(big.NewInt(52))
so1.SetNonce(53)
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}, false)
so1.suicided = true
so1.deleted = true
state.setStateObject(so1)
@ -194,7 +194,7 @@ func TestSnapshot2(t *testing.T) {
so0Restored := state.getStateObject(stateobjaddr0)
// Update lazily-loaded values before comparing.
so0Restored.GetState(state.db, storageaddr)
so0Restored.Code(state.db)
so0Restored.Code(state.db, false)
// non-deleted is equal (restored)
compareStateObjects(so0Restored, so0, t)

@ -342,18 +342,18 @@ func (db *DB) BlockHash() common.Hash {
return db.bhash
}
func (db *DB) GetCode(addr common.Address) []byte {
func (db *DB) GetCode(addr common.Address, isValidatorCode bool) []byte {
Object := db.getStateObject(addr)
if Object != nil {
return Object.Code(db.db)
return Object.Code(db.db, isValidatorCode)
}
return nil
}
func (db *DB) GetCodeSize(addr common.Address) int {
func (db *DB) GetCodeSize(addr common.Address, isValidatorCode bool) int {
Object := db.getStateObject(addr)
if Object != nil {
return Object.CodeSize(db.db)
return Object.CodeSize(db.db, isValidatorCode)
}
return 0
}
@ -475,10 +475,10 @@ func (db *DB) SetNonce(addr common.Address, nonce uint64) {
}
}
func (db *DB) SetCode(addr common.Address, code []byte) {
func (db *DB) SetCode(addr common.Address, code []byte, isValidatorCode bool) {
Object := db.GetOrNewStateObject(addr)
if Object != nil {
Object.SetCode(crypto.Keccak256Hash(code), code)
Object.SetCode(crypto.Keccak256Hash(code), code, isValidatorCode)
}
}
@ -1053,7 +1053,11 @@ func (db *DB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
if obj := db.stateObjects[addr]; !obj.deleted {
// Write any contract code associated with the state object
if obj.code != nil && obj.dirtyCode {
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
if obj.validatorWrapper {
rawdb.WriteValidatorCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
} else {
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
}
obj.dirtyCode = false
}
// Write any storage changes in the state object to its storage trie
@ -1237,9 +1241,12 @@ func (db *DB) ValidatorWrapper(
return copyValidatorWrapperIfNeeded(cached, sendOriginal, copyDelegations), nil
}
by := db.GetCode(addr)
by := db.GetCode(addr, true)
if len(by) == 0 {
return nil, ErrAddressNotPresent
by = db.GetCode(addr, false)
if len(by) == 0 {
return nil, ErrAddressNotPresent
}
}
val := stk.ValidatorWrapper{}
if err := rlp.DecodeBytes(by, &val); err != nil {
@ -1285,7 +1292,7 @@ func (db *DB) UpdateValidatorWrapper(
return err
}
// has revert in-built for the code field
db.SetCode(addr, by)
db.SetCode(addr, by, true)
// update cache
db.stateValidators[addr] = val
return nil

@ -50,7 +50,7 @@ func TestUpdateLeaks(t *testing.T) {
state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
}
if i%3 == 0 {
state.SetCode(addr, []byte{i, i, i, i, i})
state.SetCode(addr, []byte{i, i, i, i, i}, false)
}
}
@ -84,7 +84,7 @@ func TestIntermediateLeaks(t *testing.T) {
state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak})
}
if i%3 == 0 {
state.SetCode(addr, []byte{i, i, i, i, i, tweak})
state.SetCode(addr, []byte{i, i, i, i, i, tweak}, false)
}
}
@ -286,7 +286,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
code := make([]byte, 16)
binary.BigEndian.PutUint64(code, uint64(a.args[0]))
binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
s.SetCode(addr, code)
s.SetCode(addr, code, false)
},
args: make([]int64, 2),
},
@ -452,9 +452,9 @@ func (test *snapshotTest) checkEqual(state, checkstate *DB) error {
checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr))
checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
checkeq("GetCode", state.GetCode(addr, false), checkstate.GetCode(addr, false))
checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr))
checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
checkeq("GetCodeSize", state.GetCodeSize(addr, false), checkstate.GetCodeSize(addr, false))
// Check storage.
if obj := state.getStateObject(addr); obj != nil {
state.ForEachStorage(addr, func(key, value common.Hash) bool {
@ -525,14 +525,14 @@ func TestCopyCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
state.SetBalance(addr, big.NewInt(42)) // Change the account trie
state.SetCode(addr, []byte("hello")) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
state.SetBalance(addr, big.NewInt(42)) // Change the account trie
state.SetCode(addr, []byte("hello"), false) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := state.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := state.GetState(addr, skey); val != sval {
@ -546,7 +546,7 @@ func TestCopyCommitCopy(t *testing.T) {
if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := copyOne.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := copyOne.GetState(addr, skey); val != sval {
@ -560,7 +560,7 @@ func TestCopyCommitCopy(t *testing.T) {
if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := copyOne.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := copyOne.GetState(addr, skey); val != sval {
@ -574,7 +574,7 @@ func TestCopyCommitCopy(t *testing.T) {
if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
}
if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := copyTwo.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := copyTwo.GetState(addr, skey); val != sval {
@ -597,14 +597,14 @@ func TestCopyCopyCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
state.SetBalance(addr, big.NewInt(42)) // Change the account trie
state.SetCode(addr, []byte("hello")) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
state.SetBalance(addr, big.NewInt(42)) // Change the account trie
state.SetCode(addr, []byte("hello"), false) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := state.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := state.GetState(addr, skey); val != sval {
@ -618,7 +618,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
}
if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := copyOne.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := copyOne.GetState(addr, skey); val != sval {
@ -632,7 +632,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := copyTwo.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := copyTwo.GetState(addr, skey); val != sval {
@ -645,7 +645,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := copyTwo.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := copyTwo.GetState(addr, skey); val != sval {
@ -659,7 +659,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
}
if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
if code := copyThree.GetCode(addr, false); !bytes.Equal(code, []byte("hello")) {
t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello"))
}
if val := copyThree.GetState(addr, skey); val != sval {
@ -717,10 +717,10 @@ func TestMissingTrieNodes(t *testing.T) {
addr := common.BytesToAddress([]byte("so"))
{
state.SetBalance(addr, big.NewInt(1))
state.SetCode(addr, []byte{1, 2, 3})
state.SetCode(addr, []byte{1, 2, 3}, false)
a2 := common.BytesToAddress([]byte("another"))
state.SetBalance(a2, big.NewInt(100))
state.SetCode(a2, []byte{1, 2, 4})
state.SetCode(a2, []byte{1, 2, 4}, false)
root, _ = state.Commit(false)
t.Logf("root: %x", root)
// force-flush

@ -33,9 +33,9 @@ func filledStateDB() *DB {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
state.SetBalance(addr, big.NewInt(42)) // Change the account trie
state.SetCode(addr, []byte("hello")) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
state.SetBalance(addr, big.NewInt(42)) // Change the account trie
state.SetCode(addr, []byte("hello"), false) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
for i := 0; i < 100; i++ {
sk := common.BigToHash(big.NewInt(int64(i)))
state.SetState(addr, sk, sk) // Change the storage trie

@ -242,7 +242,7 @@ func (c *crossShardXferPrecompile) RunWriteCapable(
return nil, err
}
// validate not a contract (toAddress can still be a contract)
if len(evm.StateDB.GetCode(fromAddress)) > 0 && !evm.IsValidator(evm.StateDB, fromAddress) {
if len(evm.StateDB.GetCode(fromAddress, false)) > 0 && !evm.IsValidator(evm.StateDB, fromAddress) {
return nil, errors.New("cross shard xfer not yet implemented for contracts")
}
// can't have too many shards

@ -336,7 +336,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value, txType)
codeHash := evm.StateDB.GetCodeHash(addr)
code := evm.StateDB.GetCode(addr)
code := evm.StateDB.GetCode(addr, false)
// If address is a validator address, then it's not a smart contract address
// we don't use its code and codeHash fields
if evm.Context.IsValidator(evm.StateDB, addr) {
@ -402,7 +402,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// EVM. The contract is a scoped environment for this execution context
// only.
contract := NewContract(caller, to, value, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr, false))
ret, err = run(evm, contract, input, false)
if err != nil {
@ -435,7 +435,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// Initialise a new contract and make initialise the delegate values
contract := NewContract(caller, to, nil, gas).AsDelegate()
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr, false))
ret, err = run(evm, contract, input, false)
if err != nil {
@ -468,7 +468,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// EVM. The contract is a scoped environment for this execution context
// only.
contract := NewContract(caller, to, new(big.Int), gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr, false))
// We do an AddBalance of zero here, just in order to trigger a touch.
// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
@ -553,7 +553,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if err == nil && !maxCodeSizeExceeded {
createDataGas := uint64(len(ret)) * params.CreateDataGas
if contract.UseGas(createDataGas) {
evm.StateDB.SetCode(address, ret)
evm.StateDB.SetCode(address, ret, false)
} else {
err = ErrCodeStoreOutOfGas
}

@ -85,7 +85,7 @@ func TestEIP2200(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
statedb.CreateAccount(address)
statedb.SetCode(address, hexutil.MustDecode(tt.input))
statedb.SetCode(address, hexutil.MustDecode(tt.input), false)
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
statedb.Finalise(true) // Push the state into the "original" slot

@ -488,7 +488,7 @@ func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
slot.SetUint64(0)
return nil, nil
}
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(common.BigToAddress(slot))))
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(common.BigToAddress(slot), false)))
return nil, nil
}
@ -528,7 +528,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
// for EOAs that are not validators, statedb returns nil
code = nil
} else {
code = interpreter.evm.StateDB.GetCode(addr)
code = interpreter.evm.StateDB.GetCode(addr, false)
}
codeCopy := getDataBig(code, codeOffset, length)
memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)

@ -38,9 +38,9 @@ type StateDB interface {
SetNonce(common.Address, uint64)
GetCodeHash(common.Address) common.Hash
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
GetCodeSize(common.Address) int
GetCode(common.Address, bool) []byte
SetCode(common.Address, []byte, bool)
GetCodeSize(common.Address, bool) int
ValidatorWrapper(common.Address, bool, bool) (*staking.ValidatorWrapper, error)
UpdateValidatorWrapper(common.Address, *staking.ValidatorWrapper) error

@ -28,10 +28,10 @@ type dummyContractRef struct {
calledForEach bool
}
func (dummyContractRef) ReturnGas(*big.Int) {}
func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode(common.Hash, []byte) {}
func (dummyContractRef) ReturnGas(*big.Int) {}
func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode(common.Hash, []byte, bool) {}
func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) {
d.calledForEach = true
}

@ -112,7 +112,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.DB, error) {
)
cfg.State.CreateAccount(address)
// set the receiver's (the executing contract) code for execution.
cfg.State.SetCode(address, code)
cfg.State.SetCode(address, code, false)
// Call the code with the given configuration.
ret, _, err := vmenv.Call(
sender,

@ -105,7 +105,7 @@ func TestCall(t *testing.T) {
byte(vm.PUSH1), 32,
byte(vm.PUSH1), 0,
byte(vm.RETURN),
})
}, false)
ret, _, err := Call(address, nil, &Config{State: state})
if err != nil {
@ -158,7 +158,7 @@ func benchmarkEVMCreate(bench *testing.B, code string) {
)
statedb.CreateAccount(sender)
statedb.SetCode(receiver, common.FromHex(code))
statedb.SetCode(receiver, common.FromHex(code), false)
runtimeConfig := Config{
Origin: sender,
State: statedb,

@ -353,7 +353,7 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
ret := stackPeek(0)
if ret.Sign() != 0 {
call.to = common.BigToAddress(ret)
call.output = env.StateDB.GetCode(call.to)
call.output = env.StateDB.GetCode(call.to, false)
} else if call.err == nil {
call.err = errors.New("internal failure")
}

@ -210,7 +210,7 @@ func (dw *dbWrapper) pushObject(vm *duktape.Context) {
// Push the wrapper for statedb.GetCode
vm.PushGoFunction(func(ctx *duktape.Context) int {
code := dw.db.GetCode(common.BytesToAddress(popSlice(ctx)))
code := dw.db.GetCode(common.BytesToAddress(popSlice(ctx)), false)
ptr := ctx.PushFixedBuffer(len(code))
copy(makeSlice(ptr, uint(len(code))), code)

@ -178,11 +178,11 @@ func (s *BlockAPI) BlockTransaction(
// check for contract related operations, if it is a plain transaction.
if txInfo.tx.To() != nil {
// possible call to existing contract so fetch relevant data
contractInfo.ContractCode = state.GetCode(*txInfo.tx.To())
contractInfo.ContractCode = state.GetCode(*txInfo.tx.To(), false)
contractInfo.ContractAddress = txInfo.tx.To()
} else {
// contract creation, so address is in receipt
contractInfo.ContractCode = state.GetCode(txInfo.receipt.ContractAddress)
contractInfo.ContractCode = state.GetCode(txInfo.receipt.ContractAddress, false)
contractInfo.ContractAddress = &txInfo.receipt.ContractAddress
}
contractInfo.ExecutionResult, rosettaError = s.getTransactionTrace(ctx, blk, txInfo)

@ -289,7 +289,7 @@ func (s *ConstructAPI) ConstructionMetadata(
GasPrice: sugNativePrice,
GasLimit: estGasUsed,
Transaction: options.TransactionMetadata,
ContractCode: state.GetCode(contractAddress),
ContractCode: state.GetCode(contractAddress, false),
EvmErrorMessage: evmErrorMsg,
EvmReturn: evmReturn,
})

@ -123,7 +123,7 @@ func (s *PublicContractService) GetCode(
DoMetricRPCQueryInfo(GetCode, FailedNumber)
return nil, err
}
code := state.GetCode(address)
code := state.GetCode(address, false)
// Response output is the same for all versions
return code, state.Error()

@ -434,8 +434,8 @@ func (ctx *incStateTestCtx) checkAddrIncStateByType(addr common.Address, typeInc
// checkHmyNodeStateChangeByAddr checks the state change for hmy nodes. Since hmy nodes does not
// have wrapper, it is supposed to be unchanged in code field
func (ctx *incStateTestCtx) checkHmyNodeStateChangeByAddr(addr common.Address) error {
snapCode := ctx.snapState.GetCode(addr)
curCode := ctx.state.GetCode(addr)
snapCode := ctx.snapState.GetCode(addr, false)
curCode := ctx.state.GetCode(addr, false)
if !reflect.DeepEqual(snapCode, curCode) {
return errors.New("code not expected")
}
@ -618,7 +618,7 @@ func (state testStateDB) UpdateValidatorWrapper(addr common.Address, wrapper *st
return nil
}
func (state testStateDB) GetCode(addr common.Address) []byte {
func (state testStateDB) GetCode(addr common.Address, isValidatorCode bool) []byte {
wrapper, ok := state[addr]
if !ok {
return nil

Loading…
Cancel
Save