feat: dual code hash (#583)

* add crypto/codehash/codehash.go

fix

* init EmptyCodeHash

* fix

* WIP

* fix

* ???

* minor

* update light/trie.go

* update cmd/geth/snapshot.go

* update core/state/dump.go

* update core/state/snapshot/conversion.go

* update core/state/snapshot/generate.go

* update core/state/pruner/pruner.go

* update core/state/iterator.go

* update core/state/sync.go

* update core/state/state_object.go

* update core/state/statedb.go

* update core/vm/interface.go

* update core/vm/evm.go

* update core/vm/instructions.go

* update core/vm/contract.go

* update core/state_transition.go

* update les/server_requests.go

* update eth/protocols/snap/sync.go

* update internal/ethapi/api.go

* update cmd/geth/snapshot.go

* update ethclient/gethclient/gethclient.go

* gofmt

* fix `(s *stateObject) SetCode`

* fix tests

* minor

* minor

minor
This commit is contained in:
HAOYUatHZ 2023-12-01 14:02:09 +08:00 committed by GitHub
parent b639349788
commit 8c5bae2e69
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 366 additions and 290 deletions

View file

@ -261,11 +261,11 @@ func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
expHashes: 0, expHashes: 0,
}, },
{ {
nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash}, nBytes: 10000, hashes: []common.Hash{types.EmptyKeccakCodeHash},
expHashes: 1, expHashes: 1,
}, },
{ {
nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash}, nBytes: 10000, hashes: []common.Hash{types.EmptyKeccakCodeHash, types.EmptyKeccakCodeHash, types.EmptyKeccakCodeHash},
expHashes: 3, expHashes: 3,
}, },
// The existing bytecodes // The existing bytecodes
@ -357,7 +357,7 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
for i := 1; i <= 65; i++ { for i := 1; i <= 65; i++ {
accPaths = append(accPaths, pathTo(i)) accPaths = append(accPaths, pathTo(i))
} }
empty := types.EmptyCodeHash empty := types.EmptyKeccakCodeHash
for i, tc := range []trieNodesTest{ for i, tc := range []trieNodesTest{
{ {
root: s.chain.RootAt(999), root: s.chain.RootAt(999),

View file

@ -338,9 +338,9 @@ func traverseState(ctx *cli.Context) error {
return storageIter.Err return storageIter.Err
} }
} }
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(acc.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.KeccakCodeHash)) {
log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash)) log.Error("Code is missing", "hash", common.BytesToHash(acc.KeccakCodeHash))
return errors.New("missing code") return errors.New("missing code")
} }
codes += 1 codes += 1
@ -496,8 +496,8 @@ func traverseRawState(ctx *cli.Context) error {
return storageIter.Error() return storageIter.Error()
} }
} }
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(acc.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.KeccakCodeHash)) {
log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey())) log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey()))
return errors.New("missing code") return errors.New("missing code")
} }
@ -568,14 +568,15 @@ func dumpState(ctx *cli.Context) error {
return err return err
} }
da := &state.DumpAccount{ da := &state.DumpAccount{
Balance: account.Balance.String(), Balance: account.Balance.String(),
Nonce: account.Nonce, Nonce: account.Nonce,
Root: account.Root.Bytes(), Root: account.Root.Bytes(),
CodeHash: account.CodeHash, KeccakCodeHash: account.KeccakCodeHash,
SecureKey: accIt.Hash().Bytes(), PoseidonCodeHash: account.PoseidonCodeHash,
SecureKey: accIt.Hash().Bytes(),
} }
if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { if !conf.SkipCode && !bytes.Equal(account.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash)) da.Code = rawdb.ReadCode(db, common.BytesToHash(account.KeccakCodeHash))
} }
if !conf.SkipStorage { if !conf.SkipStorage {
da.Storage = make(map[common.Hash]string) da.Storage = make(map[common.Hash]string)

View file

@ -49,14 +49,15 @@ type DumpCollector interface {
// DumpAccount represents an account in the state. // DumpAccount represents an account in the state.
type DumpAccount struct { type DumpAccount struct {
Balance string `json:"balance"` Balance string `json:"balance"`
Nonce uint64 `json:"nonce"` Nonce uint64 `json:"nonce"`
Root hexutil.Bytes `json:"root"` Root hexutil.Bytes `json:"root"`
CodeHash hexutil.Bytes `json:"codeHash"` KeccakCodeHash hexutil.Bytes `json:"keccakCodeHash"`
Code hexutil.Bytes `json:"code,omitempty"` PoseidonCodeHash hexutil.Bytes `json:"poseidonCodeHash"`
Storage map[common.Hash]string `json:"storage,omitempty"` Code hexutil.Bytes `json:"code,omitempty"`
Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode Storage map[common.Hash]string `json:"storage,omitempty"`
SecureKey hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode
SecureKey hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key
} }
@ -105,14 +106,15 @@ type iterativeDump struct {
// OnAccount implements DumpCollector interface // OnAccount implements DumpCollector interface
func (d iterativeDump) OnAccount(addr *common.Address, account DumpAccount) { func (d iterativeDump) OnAccount(addr *common.Address, account DumpAccount) {
dumpAccount := &DumpAccount{ dumpAccount := &DumpAccount{
Balance: account.Balance, Balance: account.Balance,
Nonce: account.Nonce, Nonce: account.Nonce,
Root: account.Root, Root: account.Root,
CodeHash: account.CodeHash, KeccakCodeHash: account.KeccakCodeHash,
Code: account.Code, PoseidonCodeHash: account.PoseidonCodeHash,
Storage: account.Storage, Code: account.Code,
SecureKey: account.SecureKey, Storage: account.Storage,
Address: addr, SecureKey: account.SecureKey,
Address: addr,
} }
d.Encode(dumpAccount) d.Encode(dumpAccount)
} }
@ -151,11 +153,12 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
panic(err) panic(err)
} }
account := DumpAccount{ account := DumpAccount{
Balance: data.Balance.String(), Balance: data.Balance.String(),
Nonce: data.Nonce, Nonce: data.Nonce,
Root: data.Root[:], Root: data.Root[:],
CodeHash: data.CodeHash, KeccakCodeHash: data.KeccakCodeHash,
SecureKey: it.Key, PoseidonCodeHash: data.PoseidonCodeHash,
SecureKey: it.Key,
} }
var ( var (
addrBytes = s.trie.GetKey(it.Key) addrBytes = s.trie.GetKey(it.Key)

View file

@ -134,11 +134,11 @@ func (it *nodeIterator) step() error {
if !it.dataIt.Next(true) { if !it.dataIt.Next(true) {
it.dataIt = nil it.dataIt = nil
} }
if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(account.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
it.codeHash = common.BytesToHash(account.CodeHash) it.codeHash = common.BytesToHash(account.KeccakCodeHash)
it.code, err = it.state.db.ContractCode(address, common.BytesToHash(account.CodeHash)) it.code, err = it.state.db.ContractCode(address, common.BytesToHash(account.KeccakCodeHash))
if err != nil { if err != nil {
return fmt.Errorf("code %x: %v", account.CodeHash, err) return fmt.Errorf("code %x: %v", account.KeccakCodeHash, err)
} }
} }
it.accountHash = it.stateIt.Parent() it.accountHash = it.stateIt.Parent()

View file

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

View file

@ -451,8 +451,8 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
return storageIter.Error() return storageIter.Error()
} }
} }
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(acc.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
stateBloom.Put(acc.CodeHash, nil) stateBloom.Put(acc.KeccakCodeHash, nil)
} }
} }
} }

View file

@ -74,7 +74,7 @@ func GenerateTrie(snaptree *Tree, root common.Hash, src ethdb.Database, dst ethd
scheme := snaptree.triedb.Scheme() scheme := snaptree.triedb.Scheme()
got, err := generateTrieRoot(dst, scheme, acctIt, common.Hash{}, stackTrieGenerate, func(dst ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { got, err := generateTrieRoot(dst, scheme, acctIt, common.Hash{}, stackTrieGenerate, func(dst ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) {
// Migrate the code first, commit the contract code into the tmp db. // Migrate the code first, commit the contract code into the tmp db.
if codeHash != types.EmptyCodeHash { if codeHash != types.EmptyKeccakCodeHash {
code := rawdb.ReadCode(src, codeHash) code := rawdb.ReadCode(src, codeHash)
if len(code) == 0 { if len(code) == 0 {
return common.Hash{}, errors.New("failed to read contract code") return common.Hash{}, errors.New("failed to read contract code")
@ -317,7 +317,7 @@ func generateTrieRoot(db ethdb.KeyValueWriter, scheme string, it Iterator, accou
return stop(err) return stop(err)
} }
go func(hash common.Hash) { go func(hash common.Hash) {
subroot, err := leafCallback(db, hash, common.BytesToHash(account.CodeHash), stats) subroot, err := leafCallback(db, hash, common.BytesToHash(account.KeccakCodeHash), stats)
if err != nil { if err != nil {
results <- err results <- err
return return

View file

@ -586,8 +586,11 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er
if accMarker == nil || !bytes.Equal(account[:], accMarker) { if accMarker == nil || !bytes.Equal(account[:], accMarker) {
dataLen := len(val) // Approximate size, saves us a round of RLP-encoding dataLen := len(val) // Approximate size, saves us a round of RLP-encoding
if !write { if !write {
if bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) { if bytes.Equal(acc.KeccakCodeHash, types.EmptyKeccakCodeHash[:]) {
dataLen -= 32 // TODO: codesize
// dataLen = dataLen - 32 - 32 - 8
// account for keccakCodeHash, poseidonCodeHash
dataLen = dataLen - 32 - 32
} }
if acc.Root == types.EmptyRootHash { if acc.Root == types.EmptyRootHash {
dataLen -= 32 dataLen -= 32

View file

@ -58,9 +58,9 @@ func testGeneration(t *testing.T, scheme string) {
var helper = newHelper(scheme) var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false) stRoot := helper.makeStorageTrie(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
@ -97,16 +97,16 @@ func testGenerateExistentState(t *testing.T, scheme string) {
var helper = newHelper(scheme) var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
root, snap := helper.CommitAndGenerate() root, snap := helper.CommitAndGenerate()
@ -259,28 +259,28 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
helper := newHelper(scheme) helper := newHelper(scheme)
// Account one, empty root but non-empty database // Account one, empty root but non-empty database
helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
// Account two, non empty root but empty database // Account two, non empty root but empty database
stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
// Miss slots // Miss slots
{ {
// Account three, non empty root but misses slots in the beginning // Account three, non empty root but misses slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
// Account four, non empty root but misses slots in the middle // Account four, non empty root but misses slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
// Account five, non empty root but misses slots in the end // Account five, non empty root but misses slots in the end
helper.makeStorageTrie(hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
} }
@ -288,22 +288,22 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{ {
// Account six, non empty root but wrong slots in the beginning // Account six, non empty root but wrong slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
// Account seven, non empty root but wrong slots in the middle // Account seven, non empty root but wrong slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
// Account eight, non empty root but wrong slots in the end // Account eight, non empty root but wrong slots in the end
helper.makeStorageTrie(hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-8", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-8", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
// Account 9, non empty root but rotated slots // Account 9, non empty root but rotated slots
helper.makeStorageTrie(hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-9", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-9", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
} }
@ -311,17 +311,17 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{ {
// Account 10, non empty root but extra slots in the beginning // Account 10, non empty root but extra slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-10", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-10", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
// Account 11, non empty root but extra slots in the middle // Account 11, non empty root but extra slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-11", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-11", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
// Account 12, non empty root but extra slots in the end // Account 12, non empty root but extra slots in the end
helper.makeStorageTrie(hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-12", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-12", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
} }
@ -366,25 +366,25 @@ func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) {
// Missing accounts, only in the trie // Missing accounts, only in the trie
{ {
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // Beginning
helper.addTrieAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle helper.addTrieAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // Middle
helper.addTrieAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End helper.addTrieAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // End
} }
// Wrong accounts // Wrong accounts
{ {
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: common.Hex2Bytes("0x1234"), PoseidonCodeHash: common.Hex2Bytes("0x1234")})
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
} }
// Extra accounts, only in the snap // Extra accounts, only in the snap
{ {
helper.addSnapAccount("acc-0", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning helper.addSnapAccount("acc-0", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // before the beginning
helper.addSnapAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle helper.addSnapAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: common.Hex2Bytes("0x1234"), PoseidonCodeHash: common.Hex2Bytes("0x1234")}) // Middle
helper.addSnapAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end helper.addSnapAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // after the end
} }
root, snap := helper.CommitAndGenerate() root, snap := helper.CommitAndGenerate()
@ -418,9 +418,9 @@ func testGenerateCorruptAccountTrie(t *testing.T, scheme string) {
// without any storage slots to keep the test smaller. // without any storage slots to keep the test smaller.
helper := newHelper(scheme) helper := newHelper(scheme)
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
@ -462,11 +462,11 @@ func testGenerateMissingStorageTrie(t *testing.T, scheme string) {
acc3 = hashData([]byte("acc-3")) acc3 = hashData([]byte("acc-3"))
helper = newHelper(scheme) helper = newHelper(scheme)
) )
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit() root := helper.Commit()
@ -502,11 +502,11 @@ func testGenerateCorruptStorageTrie(t *testing.T, scheme string) {
// two of which also has the same 3-slot storage trie attached. // two of which also has the same 3-slot storage trie attached.
helper := newHelper(scheme) helper := newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit() root := helper.Commit()
@ -546,7 +546,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"}, []string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true, true,
) )
acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@ -566,7 +566,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"}, []string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true, true,
) )
acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte("acc-2")) key := hashData([]byte("acc-2"))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val) rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@ -622,7 +622,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3"}, []string{"val-1", "val-2", "val-3"},
true, true,
) )
acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@ -636,7 +636,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
{ {
// 100 accounts exist only in snapshot // 100 accounts exist only in snapshot
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
acc := &types.StateAccount{Balance: big.NewInt(int64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} acc := &types.StateAccount{Balance: big.NewInt(int64(i)), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte(fmt.Sprintf("acc-%d", i))) key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val) rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@ -678,7 +678,7 @@ func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) {
} }
helper := newHelper(scheme) helper := newHelper(scheme)
{ {
acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val) helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val) helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val)
@ -720,7 +720,7 @@ func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) {
} }
helper := newHelper(scheme) helper := newHelper(scheme)
{ {
acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val) helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
@ -764,7 +764,7 @@ func testGenerateFromEmptySnap(t *testing.T, scheme string) {
for i := 0; i < 400; i++ { for i := 0; i < 400; i++ {
stRoot := helper.makeStorageTrie(hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount(fmt.Sprintf("acc-%d", i), helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
&types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
} }
root, snap := helper.CommitAndGenerate() root, snap := helper.CommitAndGenerate()
t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4 t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
@ -806,7 +806,7 @@ func testGenerateWithIncompleteStorage(t *testing.T, scheme string) {
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
accKey := fmt.Sprintf("acc-%d", i) accKey := fmt.Sprintf("acc-%d", i)
stRoot := helper.makeStorageTrie(hashData([]byte(accKey)), stKeys, stVals, true) stRoot := helper.makeStorageTrie(hashData([]byte(accKey)), stKeys, stVals, true)
helper.addAccount(accKey, &types.StateAccount{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount(accKey, &types.StateAccount{Balance: big.NewInt(int64(i)), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
var moddedKeys []string var moddedKeys []string
var moddedVals []string var moddedVals []string
for ii := 0; ii < 8; ii++ { for ii := 0; ii < 8; ii++ {
@ -903,11 +903,11 @@ func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string
var helper = newHelper(scheme) var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
@ -943,11 +943,11 @@ func testGenerateBrokenSnapshotWithDanglingStorage(t *testing.T, scheme string)
var helper = newHelper(scheme) var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
populateDangling(helper.diskdb) populateDangling(helper.diskdb)

View file

@ -44,10 +44,11 @@ func randomHash() common.Hash {
// randomAccount generates a random account and returns it RLP encoded. // randomAccount generates a random account and returns it RLP encoded.
func randomAccount() []byte { func randomAccount() []byte {
a := &types.StateAccount{ a := &types.StateAccount{
Balance: big.NewInt(rand.Int63()), Balance: big.NewInt(rand.Int63()),
Nonce: rand.Uint64(), Nonce: rand.Uint64(),
Root: randomHash(), Root: randomHash(),
CodeHash: types.EmptyCodeHash[:], KeccakCodeHash: types.EmptyKeccakCodeHash[:],
PoseidonCodeHash: types.EmptyPoseidonCodeHash[:],
} }
data, _ := rlp.EncodeToBytes(a) data, _ := rlp.EncodeToBytes(a)
return data return data

View file

@ -105,7 +105,8 @@ func CheckJournalAccount(db ethdb.KeyValueStore, hash common.Hash) error {
fmt.Printf("\taccount.nonce: %d\n", account.Nonce) fmt.Printf("\taccount.nonce: %d\n", account.Nonce)
fmt.Printf("\taccount.balance: %x\n", account.Balance) fmt.Printf("\taccount.balance: %x\n", account.Balance)
fmt.Printf("\taccount.root: %x\n", account.Root) fmt.Printf("\taccount.root: %x\n", account.Root)
fmt.Printf("\taccount.codehash: %x\n", account.CodeHash) fmt.Printf("\taccount.keccak_codehash: %x\n", account.KeccakCodeHash)
fmt.Printf("\taccount.poseidon_codehash: %x\n", account.PoseidonCodeHash)
} }
// Check storage // Check storage
{ {
@ -136,7 +137,8 @@ func CheckJournalAccount(db ethdb.KeyValueStore, hash common.Hash) error {
fmt.Printf("\taccount.nonce: %d\n", account.Nonce) fmt.Printf("\taccount.nonce: %d\n", account.Nonce)
fmt.Printf("\taccount.balance: %x\n", account.Balance) fmt.Printf("\taccount.balance: %x\n", account.Balance)
fmt.Printf("\taccount.root: %x\n", account.Root) fmt.Printf("\taccount.root: %x\n", account.Root)
fmt.Printf("\taccount.codehash: %x\n", account.CodeHash) fmt.Printf("\taccount.keccakcodehash: %x\n", account.KeccakCodeHash)
fmt.Printf("\taccount.poseidoncodehash: %x\n", account.PoseidonCodeHash)
} }
if _, ok := destructs[hash]; ok { if _, ok := destructs[hash]; ok {
fmt.Printf("\t Destructed!") fmt.Printf("\t Destructed!")

View file

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/codehash"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
@ -93,7 +94,8 @@ type stateObject struct {
// empty returns whether the account is considered empty. // empty returns whether the account is considered empty.
func (s *stateObject) empty() bool { func (s *stateObject) empty() bool {
return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes()) // note: if KeccakCodeHash is empty then PoseidonCodeHash and CodeSize will also be empty
return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes())
} }
// newObject creates a state object. // newObject creates a state object.
@ -469,12 +471,12 @@ func (s *stateObject) Code() []byte {
if s.code != nil { if s.code != nil {
return s.code return s.code
} }
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { if bytes.Equal(s.KeccakCodeHash(), types.EmptyKeccakCodeHash.Bytes()) {
return nil return nil
} }
code, err := s.db.db.ContractCode(s.address, common.BytesToHash(s.CodeHash())) code, err := s.db.db.ContractCode(s.address, common.BytesToHash(s.KeccakCodeHash()))
if err != nil { if err != nil {
s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.KeccakCodeHash(), err))
} }
s.code = code s.code = code
return code return code
@ -487,29 +489,29 @@ func (s *stateObject) CodeSize() int {
if s.code != nil { if s.code != nil {
return len(s.code) return len(s.code)
} }
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { if bytes.Equal(s.KeccakCodeHash(), types.EmptyKeccakCodeHash.Bytes()) {
return 0 return 0
} }
size, err := s.db.db.ContractCodeSize(s.address, common.BytesToHash(s.CodeHash())) size, err := s.db.db.ContractCodeSize(s.address, common.BytesToHash(s.KeccakCodeHash()))
if err != nil { if err != nil {
s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) s.db.setError(fmt.Errorf("can't load code size %x: %v", s.KeccakCodeHash(), err))
} }
return size return size
} }
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { func (s *stateObject) SetCode(code []byte) {
prevcode := s.Code() prevcode := s.Code()
s.db.journal.append(codeChange{ s.db.journal.append(codeChange{
account: &s.address, account: &s.address,
prevhash: s.CodeHash(),
prevcode: prevcode, prevcode: prevcode,
}) })
s.setCode(codeHash, code) s.setCode(code)
} }
func (s *stateObject) setCode(codeHash common.Hash, code []byte) { func (s *stateObject) setCode(code []byte) {
s.code = code s.code = code
s.data.CodeHash = codeHash[:] s.data.KeccakCodeHash = codehash.KeccakCodeHash(code).Bytes()
s.data.PoseidonCodeHash = codehash.PoseidonCodeHash(code).Bytes()
s.dirtyCode = true s.dirtyCode = true
} }
@ -525,8 +527,12 @@ func (s *stateObject) setNonce(nonce uint64) {
s.data.Nonce = nonce s.data.Nonce = nonce
} }
func (s *stateObject) CodeHash() []byte { func (s *stateObject) PoseidonCodeHash() []byte {
return s.data.CodeHash return s.data.PoseidonCodeHash
}
func (s *stateObject) KeccakCodeHash() []byte {
return s.data.KeccakCodeHash
} }
func (s *stateObject) Balance() *big.Int { func (s *stateObject) Balance() *big.Int {

View file

@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
@ -51,7 +50,7 @@ func TestDump(t *testing.T) {
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01})) obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
obj1.AddBalance(big.NewInt(22)) obj1.AddBalance(big.NewInt(22))
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) 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([]byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02})) obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
obj3.SetBalance(big.NewInt(44)) obj3.SetBalance(big.NewInt(44))
@ -105,7 +104,7 @@ func TestIterativeDump(t *testing.T) {
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01})) obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
obj1.AddBalance(big.NewInt(22)) obj1.AddBalance(big.NewInt(22))
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) 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([]byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02})) obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
obj3.SetBalance(big.NewInt(44)) obj3.SetBalance(big.NewInt(44))
obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00})) obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00}))
@ -207,7 +206,7 @@ func TestSnapshot2(t *testing.T) {
so0 := state.getStateObject(stateobjaddr0) so0 := state.getStateObject(stateobjaddr0)
so0.SetBalance(big.NewInt(42)) so0.SetBalance(big.NewInt(42))
so0.SetNonce(43) so0.SetNonce(43)
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) so0.SetCode([]byte{'c', 'a', 'f', 'e'})
so0.selfDestructed = false so0.selfDestructed = false
so0.deleted = false so0.deleted = false
state.setStateObject(so0) state.setStateObject(so0)
@ -219,7 +218,7 @@ func TestSnapshot2(t *testing.T) {
so1 := state.getStateObject(stateobjaddr1) so1 := state.getStateObject(stateobjaddr1)
so1.SetBalance(big.NewInt(52)) so1.SetBalance(big.NewInt(52))
so1.SetNonce(53) so1.SetNonce(53)
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}) so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'})
so1.selfDestructed = true so1.selfDestructed = true
so1.deleted = true so1.deleted = true
state.setStateObject(so1) state.setStateObject(so1)
@ -259,8 +258,8 @@ func compareStateObjects(so0, so1 *stateObject, t *testing.T) {
if so0.data.Root != so1.data.Root { if so0.data.Root != so1.data.Root {
t.Errorf("Root mismatch: have %x, want %x", so0.data.Root[:], so1.data.Root[:]) t.Errorf("Root mismatch: have %x, want %x", so0.data.Root[:], so1.data.Root[:])
} }
if !bytes.Equal(so0.CodeHash(), so1.CodeHash()) { if !bytes.Equal(so0.KeccakCodeHash(), so1.KeccakCodeHash()) {
t.Fatalf("CodeHash mismatch: have %v, want %v", so0.CodeHash(), so1.CodeHash()) t.Fatalf("CodeHash mismatch: have %v, want %v", so0.KeccakCodeHash(), so1.KeccakCodeHash())
} }
if !bytes.Equal(so0.code, so1.code) { if !bytes.Equal(so0.code, so1.code) {
t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code) t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)

View file

@ -329,12 +329,20 @@ func (s *StateDB) GetCodeSize(addr common.Address) int {
return 0 return 0
} }
func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { func (s *StateDB) GetPoseidonCodeHash(addr common.Address) common.Hash {
stateObject := s.getStateObject(addr) stateObject := s.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
return common.Hash{} return common.Hash{}
} }
return common.BytesToHash(stateObject.CodeHash()) return common.BytesToHash(stateObject.PoseidonCodeHash())
}
func (s *StateDB) GetKeccakCodeHash(addr common.Address) common.Hash {
stateObject := s.getStateObject(addr)
if stateObject == nil {
return common.Hash{}
}
return common.BytesToHash(stateObject.KeccakCodeHash())
} }
// GetState retrieves a value from the given account's storage trie. // GetState retrieves a value from the given account's storage trie.
@ -405,7 +413,7 @@ func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
func (s *StateDB) SetCode(addr common.Address, code []byte) { func (s *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := s.GetOrNewStateObject(addr) stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetCode(crypto.Keccak256Hash(code), code) stateObject.SetCode(code)
} }
} }
@ -510,7 +518,7 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err)) s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
} }
if obj.dirtyCode { if obj.dirtyCode {
s.trie.UpdateContractCode(obj.Address(), common.BytesToHash(obj.CodeHash()), obj.code) s.trie.UpdateContractCode(obj.Address(), common.BytesToHash(obj.KeccakCodeHash()), obj.code)
} }
// Cache the data until commit. Note, this update mechanism is not symmetric // Cache the data until commit. Note, this update mechanism is not symmetric
// to the deletion, because whereas it is enough to track account updates // to the deletion, because whereas it is enough to track account updates
@ -575,13 +583,15 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
return nil return nil
} }
data = &types.StateAccount{ data = &types.StateAccount{
Nonce: acc.Nonce, Nonce: acc.Nonce,
Balance: acc.Balance, Balance: acc.Balance,
CodeHash: acc.CodeHash, KeccakCodeHash: acc.KeccakCodeHash,
Root: common.BytesToHash(acc.Root), PoseidonCodeHash: acc.PoseidonCodeHash,
Root: common.BytesToHash(acc.Root),
} }
if len(data.CodeHash) == 0 { if len(data.KeccakCodeHash) == 0 {
data.CodeHash = types.EmptyCodeHash.Bytes() data.KeccakCodeHash = types.EmptyKeccakCodeHash.Bytes()
data.PoseidonCodeHash = types.EmptyPoseidonCodeHash.Bytes()
} }
if data.Root == (common.Hash{}) { if data.Root == (common.Hash{}) {
data.Root = types.EmptyRootHash data.Root = types.EmptyRootHash
@ -1194,7 +1204,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
} }
// Write any contract code associated with the state object // Write any contract code associated with the state object
if obj.code != nil && obj.dirtyCode { if obj.code != nil && obj.dirtyCode {
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code) rawdb.WriteCode(codeWriter, common.BytesToHash(obj.KeccakCodeHash()), obj.code)
obj.dirtyCode = false obj.dirtyCode = false
} }
// Write any storage changes in the state object to its storage trie // Write any storage changes in the state object to its storage trie

View file

@ -504,7 +504,8 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) checkeq("GetKeccakCodeHash", state.GetKeccakCodeHash(addr), checkstate.GetKeccakCodeHash(addr))
checkeq("GetPoseidonCodeHash", state.GetPoseidonCodeHash(addr), checkstate.GetPoseidonCodeHash(addr))
checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
// Check storage. // Check storage.
if obj := state.getStateObject(addr); obj != nil { if obj := state.getStateObject(addr); obj != nil {

View file

@ -47,7 +47,7 @@ func NewStateSync(root common.Hash, database ethdb.KeyValueReader, onLeaf func(k
return err return err
} }
syncer.AddSubTrie(obj.Root, path, parent, parentPath, onSlot) syncer.AddSubTrie(obj.Root, path, parent, parentPath, onSlot)
syncer.AddCodeEntry(common.BytesToHash(obj.CodeHash), path, parent, parentPath) syncer.AddCodeEntry(common.BytesToHash(obj.KeccakCodeHash), path, parent, parentPath)
return nil return nil
} }
syncer = trie.NewSync(root, database, onAccount, scheme) syncer = trie.NewSync(root, database, onAccount, scheme)

View file

@ -67,7 +67,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, com
acc.nonce = uint64(42 * i) acc.nonce = uint64(42 * i)
if i%3 == 0 { if i%3 == 0 {
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i}) obj.SetCode([]byte{i, i, i, i, i})
acc.code = []byte{i, i, i, i, i} acc.code = []byte{i, i, i, i, i}
} }
if i%5 == 0 { if i%5 == 0 {
@ -615,7 +615,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) {
isCode[crypto.Keccak256Hash(acc.code)] = struct{}{} isCode[crypto.Keccak256Hash(acc.code)] = struct{}{}
} }
} }
isCode[types.EmptyCodeHash] = struct{}{} isCode[types.EmptyKeccakCodeHash] = struct{}{}
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler
dstDb := rawdb.NewMemoryDatabase() dstDb := rawdb.NewMemoryDatabase()

View file

@ -281,8 +281,8 @@ func (st *StateTransition) preCheck() error {
msg.From.Hex(), stNonce) msg.From.Hex(), stNonce)
} }
// Make sure the sender is an EOA // Make sure the sender is an EOA
codeHash := st.state.GetCodeHash(msg.From) codeHash := st.state.GetKeccakCodeHash(msg.From)
if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash { if codeHash != (common.Hash{}) && codeHash != types.EmptyKeccakCodeHash {
return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA, return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA,
msg.From.Hex(), codeHash) msg.From.Hex(), codeHash)
} }

View file

@ -1,24 +1,25 @@
// TODO: fix me
// Code generated by rlpgen. DO NOT EDIT. // Code generated by rlpgen. DO NOT EDIT.
package types package types
import "github.com/ethereum/go-ethereum/rlp" // import "github.com/ethereum/go-ethereum/rlp"
import "io" // import "io"
func (obj *StateAccount) EncodeRLP(_w io.Writer) error { // func (obj *StateAccount) EncodeRLP(_w io.Writer) error {
w := rlp.NewEncoderBuffer(_w) // w := rlp.NewEncoderBuffer(_w)
_tmp0 := w.List() // _tmp0 := w.List()
w.WriteUint64(obj.Nonce) // w.WriteUint64(obj.Nonce)
if obj.Balance == nil { // if obj.Balance == nil {
w.Write(rlp.EmptyString) // w.Write(rlp.EmptyString)
} else { // } else {
if obj.Balance.Sign() == -1 { // if obj.Balance.Sign() == -1 {
return rlp.ErrNegativeBigInt // return rlp.ErrNegativeBigInt
} // }
w.WriteBigInt(obj.Balance) // w.WriteBigInt(obj.Balance)
} // }
w.WriteBytes(obj.Root[:]) // w.WriteBytes(obj.Root[:])
w.WriteBytes(obj.CodeHash) // w.WriteBytes(obj.CodeHash)
w.ListEnd(_tmp0) // w.ListEnd(_tmp0)
return w.Flush() // return w.Flush()
} // }

View file

@ -18,7 +18,7 @@ package types
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/codehash"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
@ -29,8 +29,14 @@ var (
// EmptyUncleHash is the known hash of the empty uncle set. // EmptyUncleHash is the known hash of the empty uncle set.
EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
// EmptyCodeHash is the known hash of the empty EVM bytecode. // // EmptyCodeHash is the known hash of the empty EVM bytecode.
EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 // EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
// EmptyKeccakCodeHash is the known Keccak hash of the empty EVM bytecode.
EmptyKeccakCodeHash = codehash.EmptyKeccakCodeHash
// EmptyKeccakCodeHash is the known Poseidon hash of the empty EVM bytecode.
EmptyPoseidonCodeHash = codehash.EmptyPoseidonCodeHash
// EmptyTxsHash is the known hash of the empty transaction set. // EmptyTxsHash is the known hash of the empty transaction set.
EmptyTxsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") EmptyTxsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")

View file

@ -29,18 +29,20 @@ import (
// StateAccount is the Ethereum consensus representation of accounts. // StateAccount is the Ethereum consensus representation of accounts.
// These objects are stored in the main account trie. // These objects are stored in the main account trie.
type StateAccount struct { type StateAccount struct {
Nonce uint64 Nonce uint64
Balance *big.Int Balance *big.Int
Root common.Hash // merkle root of the storage trie Root common.Hash // merkle root of the storage trie
CodeHash []byte KeccakCodeHash []byte
PoseidonCodeHash []byte
} }
// NewEmptyStateAccount constructs an empty state account. // NewEmptyStateAccount constructs an empty state account.
func NewEmptyStateAccount() *StateAccount { func NewEmptyStateAccount() *StateAccount {
return &StateAccount{ return &StateAccount{
Balance: new(big.Int), Balance: new(big.Int),
Root: EmptyRootHash, Root: EmptyRootHash,
CodeHash: EmptyCodeHash.Bytes(), KeccakCodeHash: EmptyKeccakCodeHash.Bytes(),
PoseidonCodeHash: EmptyPoseidonCodeHash.Bytes(),
} }
} }
@ -51,10 +53,11 @@ func (acct *StateAccount) Copy() *StateAccount {
balance = new(big.Int).Set(acct.Balance) balance = new(big.Int).Set(acct.Balance)
} }
return &StateAccount{ return &StateAccount{
Nonce: acct.Nonce, Nonce: acct.Nonce,
Balance: balance, Balance: balance,
Root: acct.Root, Root: acct.Root,
CodeHash: common.CopyBytes(acct.CodeHash), KeccakCodeHash: common.CopyBytes(acct.KeccakCodeHash),
PoseidonCodeHash: common.CopyBytes(acct.PoseidonCodeHash),
} }
} }
@ -62,10 +65,11 @@ func (acct *StateAccount) Copy() *StateAccount {
// with a byte slice. This format can be used to represent full-consensus format // with a byte slice. This format can be used to represent full-consensus format
// or slim format which replaces the empty root and code hash as nil byte slice. // or slim format which replaces the empty root and code hash as nil byte slice.
type SlimAccount struct { type SlimAccount struct {
Nonce uint64 Nonce uint64
Balance *big.Int Balance *big.Int
Root []byte // Nil if root equals to types.EmptyRootHash Root []byte // Nil if root equals to types.EmptyRootHash
CodeHash []byte // Nil if hash equals to types.EmptyCodeHash KeccakCodeHash []byte // Nil if hash equals to types.EmptyKeccakCodeHash
PoseidonCodeHash []byte // Nil if hash equals to types.EmptyPoseidonCodeHash
} }
// SlimAccountRLP encodes the state account in 'slim RLP' format. // SlimAccountRLP encodes the state account in 'slim RLP' format.
@ -77,8 +81,9 @@ func SlimAccountRLP(account StateAccount) []byte {
if account.Root != EmptyRootHash { if account.Root != EmptyRootHash {
slim.Root = account.Root[:] slim.Root = account.Root[:]
} }
if !bytes.Equal(account.CodeHash, EmptyCodeHash[:]) { if !bytes.Equal(account.KeccakCodeHash, EmptyKeccakCodeHash[:]) {
slim.CodeHash = account.CodeHash slim.KeccakCodeHash = account.KeccakCodeHash
slim.PoseidonCodeHash = account.PoseidonCodeHash
} }
data, err := rlp.EncodeToBytes(slim) data, err := rlp.EncodeToBytes(slim)
if err != nil { if err != nil {
@ -103,10 +108,12 @@ func FullAccount(data []byte) (*StateAccount, error) {
} else { } else {
account.Root = common.BytesToHash(slim.Root) account.Root = common.BytesToHash(slim.Root)
} }
if len(slim.CodeHash) == 0 { if len(slim.KeccakCodeHash) == 0 {
account.CodeHash = EmptyCodeHash[:] account.KeccakCodeHash = EmptyKeccakCodeHash[:]
account.PoseidonCodeHash = EmptyPoseidonCodeHash[:]
} else { } else {
account.CodeHash = slim.CodeHash account.KeccakCodeHash = slim.KeccakCodeHash
account.PoseidonCodeHash = slim.PoseidonCodeHash
} }
return &account, nil return &account, nil
} }

View file

@ -54,7 +54,7 @@ type Contract struct {
analysis bitvec // Locally cached result of JUMPDEST analysis analysis bitvec // Locally cached result of JUMPDEST analysis
Code []byte Code []byte
CodeHash common.Hash CodeHash common.Hash // Keccak code hash
CodeAddr *common.Address CodeAddr *common.Address
Input []byte Input []byte

View file

@ -234,7 +234,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// If the account has no code, we can abort here // If the account has no code, we can abort here
// The depth-check is already done, and precompiles handled above // The depth-check is already done, and precompiles handled above
contract := NewContract(caller, AccountRef(addrCopy), value, gas) contract := NewContract(caller, AccountRef(addrCopy), value, gas)
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code) contract.SetCallCode(&addrCopy, evm.StateDB.GetKeccakCodeHash(addrCopy), code)
ret, err = evm.interpreter.Run(contract, input, false) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas gas = contract.Gas
} }
@ -291,7 +291,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only. // The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(caller.Address()), value, gas) contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) contract.SetCallCode(&addrCopy, evm.StateDB.GetKeccakCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
ret, err = evm.interpreter.Run(contract, input, false) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas gas = contract.Gas
} }
@ -335,7 +335,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
addrCopy := addr addrCopy := addr
// Initialise a new contract and make initialise the delegate values // Initialise a new contract and make initialise the delegate values
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) contract.SetCallCode(&addrCopy, evm.StateDB.GetKeccakCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
ret, err = evm.interpreter.Run(contract, input, false) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas gas = contract.Gas
} }
@ -388,7 +388,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only. // The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas) contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas)
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) contract.SetCallCode(&addrCopy, evm.StateDB.GetKeccakCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
// When an error was returned by the EVM or when setting the creation code // When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally // above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in Homestead this also counts for code storage gas errors. // when we're in Homestead this also counts for code storage gas errors.
@ -411,6 +411,7 @@ type codeAndHash struct {
func (c *codeAndHash) Hash() common.Hash { func (c *codeAndHash) Hash() common.Hash {
if c.hash == (common.Hash{}) { if c.hash == (common.Hash{}) {
// when calculating CREATE2 address, we use Keccak256 not Poseidon
c.hash = crypto.Keccak256Hash(c.code) c.hash = crypto.Keccak256Hash(c.code)
} }
return c.hash return c.hash
@ -437,8 +438,8 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
evm.StateDB.AddAddressToAccessList(address) evm.StateDB.AddAddressToAccessList(address)
} }
// Ensure there's no existing contract already at the designated address // Ensure there's no existing contract already at the designated address
contractHash := evm.StateDB.GetCodeHash(address) contractHash := evm.StateDB.GetKeccakCodeHash(address)
if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) { if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyKeccakCodeHash) {
return nil, common.Address{}, 0, ErrContractAddressCollision return nil, common.Address{}, 0, ErrContractAddressCollision
} }
// Create a new account on the state // Create a new account on the state

View file

@ -391,7 +391,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
// opExtCodeHash returns the code hash of a specified account. // opExtCodeHash returns the code hash of a specified account.
// There are several cases when the function is called, while we can relay everything // There are several cases when the function is called, while we can relay everything
// to `state.GetCodeHash` function to ensure the correctness. // to `state.GetKeccakCodeHash` function to ensure the correctness.
// //
// 1. Caller tries to get the code hash of a normal contract account, state // 1. Caller tries to get the code hash of a normal contract account, state
// should return the relative code hash and set it as the result. // should return the relative code hash and set it as the result.
@ -421,7 +421,7 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
if interpreter.evm.StateDB.Empty(address) { if interpreter.evm.StateDB.Empty(address) {
slot.Clear() slot.Clear()
} else { } else {
slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes()) slot.SetBytes(interpreter.evm.StateDB.GetKeccakCodeHash(address).Bytes())
} }
return nil, nil return nil, nil
} }

View file

@ -725,7 +725,7 @@ func TestRandom(t *testing.T) {
for _, tt := range []testcase{ for _, tt := range []testcase{
{name: "empty hash", random: common.Hash{}}, {name: "empty hash", random: common.Hash{}},
{name: "1", random: common.Hash{0}}, {name: "1", random: common.Hash{0}},
{name: "emptyCodeHash", random: types.EmptyCodeHash}, {name: "emptyCodeHash", random: types.EmptyKeccakCodeHash},
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})}, {name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
} { } {
var ( var (

View file

@ -35,7 +35,8 @@ type StateDB interface {
GetNonce(common.Address) uint64 GetNonce(common.Address) uint64
SetNonce(common.Address, uint64) SetNonce(common.Address, uint64)
GetCodeHash(common.Address) common.Hash GetKeccakCodeHash(common.Address) common.Hash
GetPoseidonCodeHash(common.Address) common.Hash
GetCode(common.Address) []byte GetCode(common.Address) []byte
SetCode(common.Address, []byte) SetCode(common.Address, []byte)
GetCodeSize(common.Address) int GetCodeSize(common.Address) int

View file

@ -0,0 +1,23 @@
package codehash
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/poseidon"
)
var EmptyPoseidonCodeHash common.Hash
var EmptyKeccakCodeHash common.Hash
func PoseidonCodeHash(code []byte) (h common.Hash) {
return poseidon.CodeHash(code)
}
func KeccakCodeHash(code []byte) (h common.Hash) {
return crypto.Keccak256Hash(code)
}
func init() {
EmptyPoseidonCodeHash = poseidon.CodeHash(nil)
EmptyKeccakCodeHash = crypto.Keccak256Hash(nil)
}

View file

@ -465,7 +465,7 @@ func ServiceGetByteCodesQuery(chain *core.BlockChain, req *GetByteCodesPacket) [
bytes uint64 bytes uint64
) )
for _, hash := range req.Hashes { for _, hash := range req.Hashes {
if hash == types.EmptyCodeHash { if hash == types.EmptyKeccakCodeHash {
// Peers should not request the empty code, but if they do, at // Peers should not request the empty code, but if they do, at
// least sent them back a correct response without db lookups // least sent them back a correct response without db lookups
codes = append(codes, []byte{}) codes = append(codes, []byte{})

View file

@ -1881,9 +1881,9 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
res.task.pend = 0 res.task.pend = 0
for i, account := range res.accounts { for i, account := range res.accounts {
// Check if the account is a contract with an unknown code // Check if the account is a contract with an unknown code
if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(account.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)) { if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.KeccakCodeHash)) {
res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{} res.task.codeTasks[common.BytesToHash(account.KeccakCodeHash)] = struct{}{}
res.task.needCode[i] = true res.task.needCode[i] = true
res.task.pend++ res.task.pend++
} }
@ -1947,7 +1947,7 @@ func (s *Syncer) processBytecodeResponse(res *bytecodeResponse) {
} }
// Code was delivered, mark it not needed any more // Code was delivered, mark it not needed any more
for j, account := range res.task.res.accounts { for j, account := range res.task.res.accounts {
if res.task.needCode[j] && hash == common.BytesToHash(account.CodeHash) { if res.task.needCode[j] && hash == common.BytesToHash(account.KeccakCodeHash) {
res.task.needCode[j] = false res.task.needCode[j] = false
res.task.pend-- res.task.pend--
} }

View file

@ -1489,7 +1489,7 @@ func getCodeHash(i uint64) []byte {
// getCodeByHash convenience function to lookup the code from the code hash // getCodeByHash convenience function to lookup the code from the code hash
func getCodeByHash(hash common.Hash) []byte { func getCodeByHash(hash common.Hash) []byte {
if hash == types.EmptyCodeHash { if hash == types.EmptyKeccakCodeHash {
return nil return nil
} }
for i, h := range codehashes { for i, h := range codehashes {
@ -1509,10 +1509,11 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv)
) )
for i := uint64(1); i <= uint64(n); i++ { for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i, Nonce: i,
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash, Root: types.EmptyRootHash,
CodeHash: getCodeHash(i), KeccakCodeHash: getCodeHash(i),
// TODO: PoseidonCodeHash
}) })
key := key32(i) key := key32(i)
elem := &kv{key, value} elem := &kv{key, value}
@ -1560,10 +1561,11 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
// Fill boundary accounts // Fill boundary accounts
for i := 0; i < len(boundaries); i++ { for i := 0; i < len(boundaries); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: uint64(0), Nonce: uint64(0),
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash, Root: types.EmptyRootHash,
CodeHash: getCodeHash(uint64(i)), KeccakCodeHash: getCodeHash(uint64(i)),
// TODO: PoseidonCodeHash
}) })
elem := &kv{boundaries[i].Bytes(), value} elem := &kv{boundaries[i].Bytes(), value}
accTrie.MustUpdate(elem.k, elem.v) accTrie.MustUpdate(elem.k, elem.v)
@ -1572,10 +1574,11 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
// Fill other accounts if required // Fill other accounts if required
for i := uint64(1); i <= uint64(n); i++ { for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i, Nonce: i,
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash, Root: types.EmptyRootHash,
CodeHash: getCodeHash(i), KeccakCodeHash: getCodeHash(i),
// TODO: PoseidonCodeHash
}) })
elem := &kv{key32(i), value} elem := &kv{key32(i), value}
accTrie.MustUpdate(elem.k, elem.v) accTrie.MustUpdate(elem.k, elem.v)
@ -1607,7 +1610,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
// Create n accounts in the trie // Create n accounts in the trie
for i := uint64(1); i <= uint64(accounts); i++ { for i := uint64(1); i <= uint64(accounts); i++ {
key := key32(i) key := key32(i)
codehash := types.EmptyCodeHash.Bytes() codehash := types.EmptyKeccakCodeHash.Bytes()
if code { if code {
codehash = getCodeHash(i) codehash = getCodeHash(i)
} }
@ -1616,10 +1619,11 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
nodes.Merge(stNodes) nodes.Merge(stNodes)
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i, Nonce: i,
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: stRoot, Root: stRoot,
CodeHash: codehash, KeccakCodeHash: codehash,
// TODO: PoseidonCodeHash
}) })
elem := &kv{key, value} elem := &kv{key, value}
accTrie.MustUpdate(elem.k, elem.v) accTrie.MustUpdate(elem.k, elem.v)
@ -1662,7 +1666,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
// Create n accounts in the trie // Create n accounts in the trie
for i := uint64(1); i <= uint64(accounts); i++ { for i := uint64(1); i <= uint64(accounts); i++ {
key := key32(i) key := key32(i)
codehash := types.EmptyCodeHash.Bytes() codehash := types.EmptyKeccakCodeHash.Bytes()
if code { if code {
codehash = getCodeHash(i) codehash = getCodeHash(i)
} }
@ -1682,10 +1686,11 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
nodes.Merge(stNodes) nodes.Merge(stNodes)
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i, Nonce: i,
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: stRoot, Root: stRoot,
CodeHash: codehash, KeccakCodeHash: codehash,
// TODO: PoseidonCodeHash
}) })
elem := &kv{key, value} elem := &kv{key, value}
accTrie.MustUpdate(elem.k, elem.v) accTrie.MustUpdate(elem.k, elem.v)
@ -1838,10 +1843,11 @@ func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *test
accIt := trie.NewIterator(accTrie.MustNodeIterator(nil)) accIt := trie.NewIterator(accTrie.MustNodeIterator(nil))
for accIt.Next() { for accIt.Next() {
var acc struct { var acc struct {
Nonce uint64 Nonce uint64
Balance *big.Int Balance *big.Int
Root common.Hash Root common.Hash
CodeHash []byte KeccakCodeHash []byte
PoseidonCodeHash []byte
} }
if err := rlp.DecodeBytes(accIt.Value, &acc); err != nil { if err := rlp.DecodeBytes(accIt.Value, &acc); err != nil {
log.Crit("Invalid account encountered during snapshot creation", "err", err) log.Crit("Invalid account encountered during snapshot creation", "err", err)

View file

@ -41,7 +41,7 @@ func (account) SetBalance(*big.Int) {}
func (account) SetNonce(uint64) {} func (account) SetNonce(uint64) {}
func (account) Balance() *big.Int { return nil } func (account) Balance() *big.Int { return nil }
func (account) Address() common.Address { return common.Address{} } func (account) Address() common.Address { return common.Address{} }
func (account) SetCode(common.Hash, []byte) {} func (account) SetCode([]byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
type dummyStatedb struct { type dummyStatedb struct {

View file

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

View file

@ -62,13 +62,14 @@ func (ec *Client) CreateAccessList(ctx context.Context, msg ethereum.CallMsg) (*
// AccountResult is the result of a GetProof operation. // AccountResult is the result of a GetProof operation.
type AccountResult struct { type AccountResult struct {
Address common.Address `json:"address"` Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"` AccountProof []string `json:"accountProof"`
Balance *big.Int `json:"balance"` Balance *big.Int `json:"balance"`
CodeHash common.Hash `json:"codeHash"` KeccakCodeHash common.Hash `json:"keccakCodeHash"`
Nonce uint64 `json:"nonce"` PoseidonCodeHash common.Hash `json:"poseidonCodeHash"`
StorageHash common.Hash `json:"storageHash"` Nonce uint64 `json:"nonce"`
StorageProof []StorageResult `json:"storageProof"` StorageHash common.Hash `json:"storageHash"`
StorageProof []StorageResult `json:"storageProof"`
} }
// StorageResult provides a proof for a key-value pair. // StorageResult provides a proof for a key-value pair.
@ -88,13 +89,14 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s
} }
type accountResult struct { type accountResult struct {
Address common.Address `json:"address"` Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"` AccountProof []string `json:"accountProof"`
Balance *hexutil.Big `json:"balance"` Balance *hexutil.Big `json:"balance"`
CodeHash common.Hash `json:"codeHash"` KeccakCodeHash common.Hash `json:"keccakCodeHash"`
Nonce hexutil.Uint64 `json:"nonce"` PoseidonCodeHash common.Hash `json:"poseidonCodeHash"`
StorageHash common.Hash `json:"storageHash"` Nonce hexutil.Uint64 `json:"nonce"`
StorageProof []storageResult `json:"storageProof"` StorageHash common.Hash `json:"storageHash"`
StorageProof []storageResult `json:"storageProof"`
} }
// Avoid keys being 'null'. // Avoid keys being 'null'.
@ -114,13 +116,14 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s
}) })
} }
result := AccountResult{ result := AccountResult{
Address: res.Address, Address: res.Address,
AccountProof: res.AccountProof, AccountProof: res.AccountProof,
Balance: res.Balance.ToInt(), Balance: res.Balance.ToInt(),
Nonce: uint64(res.Nonce), Nonce: uint64(res.Nonce),
CodeHash: res.CodeHash, KeccakCodeHash: res.KeccakCodeHash,
StorageHash: res.StorageHash, PoseidonCodeHash: res.PoseidonCodeHash,
StorageProof: storageResults, StorageHash: res.StorageHash,
StorageProof: storageResults,
} }
return &result, err return &result, err
} }

View file

@ -239,7 +239,7 @@ func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) {
} }
// test code // test code
code, _ := ethcl.CodeAt(context.Background(), addr, nil) code, _ := ethcl.CodeAt(context.Background(), addr, nil)
if have, want := result.CodeHash, crypto.Keccak256Hash(code); have != want { if have, want := result.KeccakCodeHash, crypto.Keccak256Hash(code); have != want {
t.Fatalf("codehash wrong, have %v want %v ", have, want) t.Fatalf("codehash wrong, have %v want %v ", have, want)
} }
} }

View file

@ -641,13 +641,14 @@ func (s *BlockChainAPI) GetBalance(ctx context.Context, address common.Address,
// Result structs for GetProof // Result structs for GetProof
type AccountResult struct { type AccountResult struct {
Address common.Address `json:"address"` Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"` AccountProof []string `json:"accountProof"`
Balance *hexutil.Big `json:"balance"` Balance *hexutil.Big `json:"balance"`
CodeHash common.Hash `json:"codeHash"` KeccakCodeHash common.Hash `json:"keccakCodeHash"`
Nonce hexutil.Uint64 `json:"nonce"` PoseidonCodeHash common.Hash `json:"poseidonCodeHash"`
StorageHash common.Hash `json:"storageHash"` Nonce hexutil.Uint64 `json:"nonce"`
StorageProof []StorageResult `json:"storageProof"` StorageHash common.Hash `json:"storageHash"`
StorageProof []StorageResult `json:"storageProof"`
} }
type StorageResult struct { type StorageResult struct {
@ -688,7 +689,8 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
if statedb == nil || err != nil { if statedb == nil || err != nil {
return nil, err return nil, err
} }
codeHash := statedb.GetCodeHash(address) keccakCodeHash := statedb.GetKeccakCodeHash(address)
poseidonCodeHash := statedb.GetPoseidonCodeHash(address)
storageRoot := statedb.GetStorageRoot(address) storageRoot := statedb.GetStorageRoot(address)
if len(keys) > 0 { if len(keys) > 0 {
@ -735,13 +737,14 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
return nil, err return nil, err
} }
return &AccountResult{ return &AccountResult{
Address: address, Address: address,
AccountProof: accountProof, AccountProof: accountProof,
Balance: (*hexutil.Big)(statedb.GetBalance(address)), Balance: (*hexutil.Big)(statedb.GetBalance(address)),
CodeHash: codeHash, KeccakCodeHash: keccakCodeHash,
Nonce: hexutil.Uint64(statedb.GetNonce(address)), PoseidonCodeHash: poseidonCodeHash,
StorageHash: storageRoot, Nonce: hexutil.Uint64(statedb.GetNonce(address)),
StorageProof: storageProof, StorageHash: storageRoot,
StorageProof: storageProof,
}, statedb.Error() }, statedb.Error()
} }

View file

@ -311,9 +311,9 @@ func handleGetCode(msg Decoder) (serveRequestFn, uint64, uint64, error) {
p.bumpInvalid() p.bumpInvalid()
continue continue
} }
code, err := bc.StateCache().ContractCode(address, common.BytesToHash(account.CodeHash)) code, err := bc.StateCache().ContractCode(address, common.BytesToHash(account.KeccakCodeHash))
if err != nil { if err != nil {
p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", address, "codehash", common.BytesToHash(account.CodeHash), "err", err) p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", address, "codehash", common.BytesToHash(account.KeccakCodeHash), "err", err)
continue continue
} }
// Accumulate the code and abort if enough data was retrieved // Accumulate the code and abort if enough data was retrieved

View file

@ -32,10 +32,6 @@ import (
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
) )
var (
sha3Nil = crypto.Keccak256Hash(nil)
)
func NewState(ctx context.Context, head *types.Header, odr OdrBackend) *state.StateDB { func NewState(ctx context.Context, head *types.Header, odr OdrBackend) *state.StateDB {
state, _ := state.New(head.Root, NewStateDatabase(ctx, head, odr), nil) state, _ := state.New(head.Root, NewStateDatabase(ctx, head, odr), nil)
return state return state
@ -73,7 +69,7 @@ func (db *odrDatabase) CopyTrie(t state.Trie) state.Trie {
} }
func (db *odrDatabase) ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) { func (db *odrDatabase) ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) {
if codeHash == sha3Nil { if codeHash == types.EmptyKeccakCodeHash {
return nil, nil return nil, nil
} }
code := rawdb.ReadCode(db.backend.Database(), codeHash) code := rawdb.ReadCode(db.backend.Database(), codeHash)

View file

@ -244,7 +244,7 @@ func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, par
// as is. // as is.
func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash, parentPath []byte) { func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash, parentPath []byte) {
// Short circuit if the entry is empty or already known // Short circuit if the entry is empty or already known
if hash == types.EmptyCodeHash { if hash == types.EmptyKeccakCodeHash {
return return
} }
if s.membatch.hasCode(hash) { if s.membatch.hasCode(hash) {

View file

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/codehash"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
@ -762,9 +763,10 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
accounts = make([][]byte, len(addresses)) accounts = make([][]byte, len(addresses))
for i := 0; i < len(accounts); i++ { for i := 0; i < len(accounts); i++ {
var ( var (
nonce = uint64(random.Int63()) nonce = uint64(random.Int63())
root = types.EmptyRootHash root = types.EmptyRootHash
code = crypto.Keccak256(nil) codekeccak = codehash.EmptyKeccakCodeHash
codeposeidon = codehash.EmptyPoseidonCodeHash
) )
// The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems,
// and will consume different amount of data from the rand source. // and will consume different amount of data from the rand source.
@ -774,7 +776,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
balanceBytes := make([]byte, numBytes) balanceBytes := make([]byte, numBytes)
random.Read(balanceBytes) random.Read(balanceBytes)
balance := new(big.Int).SetBytes(balanceBytes) balance := new(big.Int).SetBytes(balanceBytes)
data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code}) data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, KeccakCodeHash: codekeccak.Bytes(), PoseidonCodeHash: codeposeidon.Bytes()})
accounts[i] = data accounts[i] = data
} }
return addresses, accounts return addresses, accounts

View file

@ -52,10 +52,11 @@ func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[comm
func generateAccount(storageRoot common.Hash) types.StateAccount { func generateAccount(storageRoot common.Hash) types.StateAccount {
return types.StateAccount{ return types.StateAccount{
Nonce: uint64(rand.Intn(100)), Nonce: uint64(rand.Intn(100)),
Balance: big.NewInt(rand.Int63()), Balance: big.NewInt(rand.Int63()),
CodeHash: testutil.RandBytes(32), KeccakCodeHash: testutil.RandBytes(32),
Root: storageRoot, PoseidonCodeHash: testutil.RandBytes(32),
Root: storageRoot,
} }
} }