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

View file

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

View file

@ -49,14 +49,15 @@ type DumpCollector interface {
// DumpAccount represents an account in the state.
type DumpAccount struct {
Balance string `json:"balance"`
Nonce uint64 `json:"nonce"`
Root hexutil.Bytes `json:"root"`
CodeHash hexutil.Bytes `json:"codeHash"`
Code hexutil.Bytes `json:"code,omitempty"`
Storage map[common.Hash]string `json:"storage,omitempty"`
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
Balance string `json:"balance"`
Nonce uint64 `json:"nonce"`
Root hexutil.Bytes `json:"root"`
KeccakCodeHash hexutil.Bytes `json:"keccakCodeHash"`
PoseidonCodeHash hexutil.Bytes `json:"poseidonCodeHash"`
Code hexutil.Bytes `json:"code,omitempty"`
Storage map[common.Hash]string `json:"storage,omitempty"`
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
func (d iterativeDump) OnAccount(addr *common.Address, account DumpAccount) {
dumpAccount := &DumpAccount{
Balance: account.Balance,
Nonce: account.Nonce,
Root: account.Root,
CodeHash: account.CodeHash,
Code: account.Code,
Storage: account.Storage,
SecureKey: account.SecureKey,
Address: addr,
Balance: account.Balance,
Nonce: account.Nonce,
Root: account.Root,
KeccakCodeHash: account.KeccakCodeHash,
PoseidonCodeHash: account.PoseidonCodeHash,
Code: account.Code,
Storage: account.Storage,
SecureKey: account.SecureKey,
Address: addr,
}
d.Encode(dumpAccount)
}
@ -151,11 +153,12 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
panic(err)
}
account := DumpAccount{
Balance: data.Balance.String(),
Nonce: data.Nonce,
Root: data.Root[:],
CodeHash: data.CodeHash,
SecureKey: it.Key,
Balance: data.Balance.String(),
Nonce: data.Nonce,
Root: data.Root[:],
KeccakCodeHash: data.KeccakCodeHash,
PoseidonCodeHash: data.PoseidonCodeHash,
SecureKey: it.Key,
}
var (
addrBytes = s.trie.GetKey(it.Key)

View file

@ -134,11 +134,11 @@ func (it *nodeIterator) step() error {
if !it.dataIt.Next(true) {
it.dataIt = nil
}
if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
it.codeHash = common.BytesToHash(account.CodeHash)
it.code, err = it.state.db.ContractCode(address, common.BytesToHash(account.CodeHash))
if !bytes.Equal(account.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
it.codeHash = common.BytesToHash(account.KeccakCodeHash)
it.code, err = it.state.db.ContractCode(address, common.BytesToHash(account.KeccakCodeHash))
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()

View file

@ -222,7 +222,7 @@ func (ch nonceChange) dirtied() *common.Address {
}
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 {

View file

@ -451,8 +451,8 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
return storageIter.Error()
}
}
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
stateBloom.Put(acc.CodeHash, nil)
if !bytes.Equal(acc.KeccakCodeHash, types.EmptyKeccakCodeHash.Bytes()) {
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()
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.
if codeHash != types.EmptyCodeHash {
if codeHash != types.EmptyKeccakCodeHash {
code := rawdb.ReadCode(src, codeHash)
if len(code) == 0 {
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)
}
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 {
results <- err
return

View file

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

View file

@ -58,9 +58,9 @@ func testGeneration(t *testing.T, scheme string) {
var helper = newHelper(scheme)
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-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), 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, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.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-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)
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.addSnapAccount("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, 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.addTrieAccount("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, 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, 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)
helper.addTrieAccount("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, 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, 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"})
root, snap := helper.CommitAndGenerate()
@ -259,28 +259,28 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
helper := newHelper(scheme)
// 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"})
// 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)
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
{
// 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.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"})
// 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.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"})
// 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.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"})
}
@ -288,22 +288,22 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{
// 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.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"})
// 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.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"})
// 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.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"})
// 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.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"})
}
@ -311,17 +311,17 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{
// 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.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"})
// 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.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"})
// 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.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"})
}
@ -366,25 +366,25 @@ func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) {
// 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-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
helper.addTrieAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
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, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // Middle
helper.addTrieAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // End
}
// Wrong accounts
{
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
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, 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.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, 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, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()})
}
// 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-5", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: 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-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, KeccakCodeHash: common.Hex2Bytes("0x1234"), PoseidonCodeHash: common.Hex2Bytes("0x1234")}) // Middle
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()
@ -418,9 +418,9 @@ func testGenerateCorruptAccountTrie(t *testing.T, scheme string) {
// without any storage slots to keep the test smaller.
helper := newHelper(scheme)
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
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, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
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
@ -462,11 +462,11 @@ func testGenerateMissingStorageTrie(t *testing.T, scheme string) {
acc3 = hashData([]byte("acc-3"))
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
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
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, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
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)
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()
@ -502,11 +502,11 @@ func testGenerateCorruptStorageTrie(t *testing.T, scheme string) {
// two of which also has the same 3-slot storage trie attached.
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
helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
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, KeccakCodeHash: types.EmptyKeccakCodeHash.Bytes(), PoseidonCodeHash: types.EmptyPoseidonCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
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)
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()
@ -546,7 +546,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
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)
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"},
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)
key := hashData([]byte("acc-2"))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@ -622,7 +622,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3"},
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)
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
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)
key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@ -678,7 +678,7 @@ func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) {
}
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)
helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val)
@ -720,7 +720,7 @@ func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) {
}
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)
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++ {
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),
&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()
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++ {
accKey := fmt.Sprintf("acc-%d", i)
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 moddedVals []string
for ii := 0; ii < 8; ii++ {
@ -903,11 +903,11 @@ func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string
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)
helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, 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, 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.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-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)
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-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, 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, 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.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)

View file

@ -44,10 +44,11 @@ func randomHash() common.Hash {
// randomAccount generates a random account and returns it RLP encoded.
func randomAccount() []byte {
a := &types.StateAccount{
Balance: big.NewInt(rand.Int63()),
Nonce: rand.Uint64(),
Root: randomHash(),
CodeHash: types.EmptyCodeHash[:],
Balance: big.NewInt(rand.Int63()),
Nonce: rand.Uint64(),
Root: randomHash(),
KeccakCodeHash: types.EmptyKeccakCodeHash[:],
PoseidonCodeHash: types.EmptyPoseidonCodeHash[:],
}
data, _ := rlp.EncodeToBytes(a)
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.balance: %x\n", account.Balance)
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
{
@ -136,7 +137,8 @@ func CheckJournalAccount(db ethdb.KeyValueStore, hash common.Hash) error {
fmt.Printf("\taccount.nonce: %d\n", account.Nonce)
fmt.Printf("\taccount.balance: %x\n", account.Balance)
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 {
fmt.Printf("\t Destructed!")

View file

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/codehash"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
@ -93,7 +94,8 @@ type stateObject struct {
// empty returns whether the account is considered empty.
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.
@ -469,12 +471,12 @@ func (s *stateObject) Code() []byte {
if s.code != nil {
return s.code
}
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
if bytes.Equal(s.KeccakCodeHash(), types.EmptyKeccakCodeHash.Bytes()) {
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 {
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
return code
@ -487,29 +489,29 @@ func (s *stateObject) CodeSize() int {
if s.code != nil {
return len(s.code)
}
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
if bytes.Equal(s.KeccakCodeHash(), types.EmptyKeccakCodeHash.Bytes()) {
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 {
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
}
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
func (s *stateObject) SetCode(code []byte) {
prevcode := s.Code()
s.db.journal.append(codeChange{
account: &s.address,
prevhash: s.CodeHash(),
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.data.CodeHash = codeHash[:]
s.data.KeccakCodeHash = codehash.KeccakCodeHash(code).Bytes()
s.data.PoseidonCodeHash = codehash.PoseidonCodeHash(code).Bytes()
s.dirtyCode = true
}
@ -525,8 +527,12 @@ func (s *stateObject) setNonce(nonce uint64) {
s.data.Nonce = nonce
}
func (s *stateObject) CodeHash() []byte {
return s.data.CodeHash
func (s *stateObject) PoseidonCodeHash() []byte {
return s.data.PoseidonCodeHash
}
func (s *stateObject) KeccakCodeHash() []byte {
return s.data.KeccakCodeHash
}
func (s *stateObject) Balance() *big.Int {

View file

@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
)
@ -51,7 +50,7 @@ func TestDump(t *testing.T) {
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
obj1.AddBalance(big.NewInt(22))
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
obj3.SetBalance(big.NewInt(44))
@ -105,7 +104,7 @@ func TestIterativeDump(t *testing.T) {
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
obj1.AddBalance(big.NewInt(22))
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
obj3.SetBalance(big.NewInt(44))
obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00}))
@ -207,7 +206,7 @@ func TestSnapshot2(t *testing.T) {
so0 := state.getStateObject(stateobjaddr0)
so0.SetBalance(big.NewInt(42))
so0.SetNonce(43)
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
so0.SetCode([]byte{'c', 'a', 'f', 'e'})
so0.selfDestructed = false
so0.deleted = false
state.setStateObject(so0)
@ -219,7 +218,7 @@ func TestSnapshot2(t *testing.T) {
so1 := state.getStateObject(stateobjaddr1)
so1.SetBalance(big.NewInt(52))
so1.SetNonce(53)
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'})
so1.selfDestructed = true
so1.deleted = true
state.setStateObject(so1)
@ -259,8 +258,8 @@ func compareStateObjects(so0, so1 *stateObject, t *testing.T) {
if 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()) {
t.Fatalf("CodeHash mismatch: have %v, want %v", so0.CodeHash(), so1.CodeHash())
if !bytes.Equal(so0.KeccakCodeHash(), so1.KeccakCodeHash()) {
t.Fatalf("CodeHash mismatch: have %v, want %v", so0.KeccakCodeHash(), so1.KeccakCodeHash())
}
if !bytes.Equal(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
}
func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
func (s *StateDB) GetPoseidonCodeHash(addr common.Address) common.Hash {
stateObject := s.getStateObject(addr)
if stateObject == nil {
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.
@ -405,7 +413,7 @@ func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
func (s *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := s.GetOrNewStateObject(addr)
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))
}
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
// 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
}
data = &types.StateAccount{
Nonce: acc.Nonce,
Balance: acc.Balance,
CodeHash: acc.CodeHash,
Root: common.BytesToHash(acc.Root),
Nonce: acc.Nonce,
Balance: acc.Balance,
KeccakCodeHash: acc.KeccakCodeHash,
PoseidonCodeHash: acc.PoseidonCodeHash,
Root: common.BytesToHash(acc.Root),
}
if len(data.CodeHash) == 0 {
data.CodeHash = types.EmptyCodeHash.Bytes()
if len(data.KeccakCodeHash) == 0 {
data.KeccakCodeHash = types.EmptyKeccakCodeHash.Bytes()
data.PoseidonCodeHash = types.EmptyPoseidonCodeHash.Bytes()
}
if data.Root == (common.Hash{}) {
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
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
}
// 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("GetNonce", state.GetNonce(addr), checkstate.GetNonce(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))
// Check storage.
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
}
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
}
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)
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}
}
if i%5 == 0 {
@ -615,7 +615,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) {
isCode[crypto.Keccak256Hash(acc.code)] = struct{}{}
}
}
isCode[types.EmptyCodeHash] = struct{}{}
isCode[types.EmptyKeccakCodeHash] = struct{}{}
// Create a destination state and sync with the scheduler
dstDb := rawdb.NewMemoryDatabase()

View file

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

View file

@ -418,7 +418,7 @@ func (b *Block) Size() uint64 {
// PayloadSize returns the encoded storage size sum of all transactions in a block.
func (b *Block) PayloadSize() uint64 {
// add up all txs sizes
var totalSize uint64
var totalSize uint64
for _, tx := range b.transactions {
if !tx.IsL1MessageTx() {
totalSize += tx.Size()

View file

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

View file

@ -18,7 +18,7 @@ package types
import (
"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"
)
@ -29,8 +29,14 @@ var (
// EmptyUncleHash is the known hash of the empty uncle set.
EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
// EmptyCodeHash is the known hash of the empty EVM bytecode.
EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
// // EmptyCodeHash is the known hash of the empty EVM bytecode.
// 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 = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")

View file

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

View file

@ -54,7 +54,7 @@ type Contract struct {
analysis bitvec // Locally cached result of JUMPDEST analysis
Code []byte
CodeHash common.Hash
CodeHash common.Hash // Keccak code hash
CodeAddr *common.Address
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
// The depth-check is already done, and precompiles handled above
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)
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.
// The contract is a scoped environment for this execution context only.
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)
gas = contract.Gas
}
@ -335,7 +335,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
addrCopy := addr
// Initialise a new contract and make initialise the delegate values
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)
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.
// The contract is a scoped environment for this execution context only.
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
// 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.
@ -411,6 +411,7 @@ type codeAndHash struct {
func (c *codeAndHash) Hash() common.Hash {
if c.hash == (common.Hash{}) {
// when calculating CREATE2 address, we use Keccak256 not Poseidon
c.hash = crypto.Keccak256Hash(c.code)
}
return c.hash
@ -437,8 +438,8 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
evm.StateDB.AddAddressToAccessList(address)
}
// Ensure there's no existing contract already at the designated address
contractHash := evm.StateDB.GetCodeHash(address)
if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) {
contractHash := evm.StateDB.GetKeccakCodeHash(address)
if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyKeccakCodeHash) {
return nil, common.Address{}, 0, ErrContractAddressCollision
}
// 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.
// 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
// 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) {
slot.Clear()
} else {
slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes())
slot.SetBytes(interpreter.evm.StateDB.GetKeccakCodeHash(address).Bytes())
}
return nil, nil
}

View file

@ -725,7 +725,7 @@ func TestRandom(t *testing.T) {
for _, tt := range []testcase{
{name: "empty hash", random: common.Hash{}},
{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})},
} {
var (

View file

@ -35,7 +35,8 @@ type StateDB interface {
GetNonce(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
SetCode(common.Address, []byte)
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
)
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
// least sent them back a correct response without db lookups
codes = append(codes, []byte{})

View file

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

View file

@ -1489,7 +1489,7 @@ func getCodeHash(i uint64) []byte {
// getCodeByHash convenience function to lookup the code from the code hash
func getCodeByHash(hash common.Hash) []byte {
if hash == types.EmptyCodeHash {
if hash == types.EmptyKeccakCodeHash {
return nil
}
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++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash,
KeccakCodeHash: getCodeHash(i),
// TODO: PoseidonCodeHash
})
key := key32(i)
elem := &kv{key, value}
@ -1560,10 +1561,11 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
// Fill boundary accounts
for i := 0; i < len(boundaries); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: uint64(0),
Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(uint64(i)),
Nonce: uint64(0),
Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash,
KeccakCodeHash: getCodeHash(uint64(i)),
// TODO: PoseidonCodeHash
})
elem := &kv{boundaries[i].Bytes(), value}
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
for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: types.EmptyRootHash,
KeccakCodeHash: getCodeHash(i),
// TODO: PoseidonCodeHash
})
elem := &kv{key32(i), value}
accTrie.MustUpdate(elem.k, elem.v)
@ -1607,7 +1610,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
// Create n accounts in the trie
for i := uint64(1); i <= uint64(accounts); i++ {
key := key32(i)
codehash := types.EmptyCodeHash.Bytes()
codehash := types.EmptyKeccakCodeHash.Bytes()
if code {
codehash = getCodeHash(i)
}
@ -1616,10 +1619,11 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
nodes.Merge(stNodes)
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: stRoot,
CodeHash: codehash,
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: stRoot,
KeccakCodeHash: codehash,
// TODO: PoseidonCodeHash
})
elem := &kv{key, value}
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
for i := uint64(1); i <= uint64(accounts); i++ {
key := key32(i)
codehash := types.EmptyCodeHash.Bytes()
codehash := types.EmptyKeccakCodeHash.Bytes()
if code {
codehash = getCodeHash(i)
}
@ -1682,10 +1686,11 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
nodes.Merge(stNodes)
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: stRoot,
CodeHash: codehash,
Nonce: i,
Balance: big.NewInt(int64(i)),
Root: stRoot,
KeccakCodeHash: codehash,
// TODO: PoseidonCodeHash
})
elem := &kv{key, value}
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))
for accIt.Next() {
var acc struct {
Nonce uint64
Balance *big.Int
Root common.Hash
CodeHash []byte
Nonce uint64
Balance *big.Int
Root common.Hash
KeccakCodeHash []byte
PoseidonCodeHash []byte
}
if err := rlp.DecodeBytes(accIt.Value, &acc); err != nil {
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) Balance() *big.Int { return nil }
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) {}
type dummyStatedb struct {

View file

@ -32,9 +32,9 @@ type dummyContractRef struct {
calledForEach bool
}
func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode(common.Hash, []byte) {}
func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode([]byte) {}
func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) {
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.
type AccountResult struct {
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *big.Int `json:"balance"`
CodeHash common.Hash `json:"codeHash"`
Nonce uint64 `json:"nonce"`
StorageHash common.Hash `json:"storageHash"`
StorageProof []StorageResult `json:"storageProof"`
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *big.Int `json:"balance"`
KeccakCodeHash common.Hash `json:"keccakCodeHash"`
PoseidonCodeHash common.Hash `json:"poseidonCodeHash"`
Nonce uint64 `json:"nonce"`
StorageHash common.Hash `json:"storageHash"`
StorageProof []StorageResult `json:"storageProof"`
}
// 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 {
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *hexutil.Big `json:"balance"`
CodeHash common.Hash `json:"codeHash"`
Nonce hexutil.Uint64 `json:"nonce"`
StorageHash common.Hash `json:"storageHash"`
StorageProof []storageResult `json:"storageProof"`
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *hexutil.Big `json:"balance"`
KeccakCodeHash common.Hash `json:"keccakCodeHash"`
PoseidonCodeHash common.Hash `json:"poseidonCodeHash"`
Nonce hexutil.Uint64 `json:"nonce"`
StorageHash common.Hash `json:"storageHash"`
StorageProof []storageResult `json:"storageProof"`
}
// Avoid keys being 'null'.
@ -114,13 +116,14 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s
})
}
result := AccountResult{
Address: res.Address,
AccountProof: res.AccountProof,
Balance: res.Balance.ToInt(),
Nonce: uint64(res.Nonce),
CodeHash: res.CodeHash,
StorageHash: res.StorageHash,
StorageProof: storageResults,
Address: res.Address,
AccountProof: res.AccountProof,
Balance: res.Balance.ToInt(),
Nonce: uint64(res.Nonce),
KeccakCodeHash: res.KeccakCodeHash,
PoseidonCodeHash: res.PoseidonCodeHash,
StorageHash: res.StorageHash,
StorageProof: storageResults,
}
return &result, err
}

View file

@ -239,7 +239,7 @@ func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) {
}
// test code
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)
}
}

View file

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

View file

@ -311,9 +311,9 @@ func handleGetCode(msg Decoder) (serveRequestFn, uint64, uint64, error) {
p.bumpInvalid()
continue
}
code, err := bc.StateCache().ContractCode(address, common.BytesToHash(account.CodeHash))
code, err := bc.StateCache().ContractCode(address, common.BytesToHash(account.KeccakCodeHash))
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
}
// Accumulate the code and abort if enough data was retrieved

View file

@ -32,10 +32,6 @@ import (
"github.com/ethereum/go-ethereum/trie/trienode"
)
var (
sha3Nil = crypto.Keccak256Hash(nil)
)
func NewState(ctx context.Context, head *types.Header, odr OdrBackend) *state.StateDB {
state, _ := state.New(head.Root, NewStateDatabase(ctx, head, odr), nil)
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) {
if codeHash == sha3Nil {
if codeHash == types.EmptyKeccakCodeHash {
return nil, nil
}
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.
func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash, parentPath []byte) {
// Short circuit if the entry is empty or already known
if hash == types.EmptyCodeHash {
if hash == types.EmptyKeccakCodeHash {
return
}
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/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/codehash"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"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))
for i := 0; i < len(accounts); i++ {
var (
nonce = uint64(random.Int63())
root = types.EmptyRootHash
code = crypto.Keccak256(nil)
nonce = uint64(random.Int63())
root = types.EmptyRootHash
codekeccak = codehash.EmptyKeccakCodeHash
codeposeidon = codehash.EmptyPoseidonCodeHash
)
// 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.
@ -774,7 +776,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
balanceBytes := make([]byte, numBytes)
random.Read(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
}
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 {
return types.StateAccount{
Nonce: uint64(rand.Intn(100)),
Balance: big.NewInt(rand.Int63()),
CodeHash: testutil.RandBytes(32),
Root: storageRoot,
Nonce: uint64(rand.Intn(100)),
Balance: big.NewInt(rand.Int63()),
KeccakCodeHash: testutil.RandBytes(32),
PoseidonCodeHash: testutil.RandBytes(32),
Root: storageRoot,
}
}