feat: change bytecode hash function from Keccak to Poseidon (#149)

* feat: change bytecode hash function from Keccak to Poseidon

* fix TestStateProcessorErrors

* rename files

* copy iden3's poseidon package to local

* update poseidon hash

* apply new hash in codehash

* extend hash method, use actual code size as cap

* prune keccak(nil) for empty code

* update empty code hash references to Poseidon

* add TestPoseidonCodeHash

* use keccak for empty code hash

* go mod tidy

* goimports

* use Poseidon code hash in state and sync tests

* run goimports

* run goimports

* remove unnecessary reallocation from CodeHash

* goimports

* move codehash API to separate module

* add missing package

* fix review comments

* improve comments

Co-authored-by: Ho Vei <noelwei@gmail.com>
This commit is contained in:
Péter Garamvölgyi 2022-09-08 00:16:17 +02:00 committed by GitHub
parent 346bfc82e8
commit 304af60f50
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 25516 additions and 41 deletions

View file

@ -32,7 +32,7 @@ import (
"github.com/scroll-tech/go-ethereum/core/state/pruner" "github.com/scroll-tech/go-ethereum/core/state/pruner"
"github.com/scroll-tech/go-ethereum/core/state/snapshot" "github.com/scroll-tech/go-ethereum/core/state/snapshot"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rlp" "github.com/scroll-tech/go-ethereum/rlp"
"github.com/scroll-tech/go-ethereum/trie" "github.com/scroll-tech/go-ethereum/trie"
@ -43,7 +43,7 @@ var (
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode. // emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256(nil) emptyCode = codehash.EmptyCodeHash.Bytes()
) )
var ( var (

View file

@ -27,6 +27,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert"
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/consensus" "github.com/scroll-tech/go-ethereum/consensus"
"github.com/scroll-tech/go-ethereum/consensus/ethash" "github.com/scroll-tech/go-ethereum/consensus/ethash"
@ -2986,3 +2988,108 @@ func TestEIP1559Transition(t *testing.T) {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
} }
} }
// TestPoseidonCodeHash makes sure that, after switching
// to Poseidon, code hashes change but addresses do not.
func TestPoseidonCodeHash(t *testing.T) {
// pragma solidity =0.8.7;
//
// contract Factory {
// event Deployed(address addr);
//
// function create(bytes memory code) public {
// address addr;
//
// assembly {
// addr := create(0, add(code, 0x20), mload(code))
// if iszero(extcodesize(addr)) {
// revert(0, 0)
// }
// }
//
// emit Deployed(addr);
// }
//
// function create2(bytes memory code) public {
// address addr;
//
// assembly {
// addr := create2(0, add(code, 0x20), mload(code), 0)
// if iszero(extcodesize(addr)) {
// revert(0, 0)
// }
// }
//
// emit Deployed(addr);
// }
// }
var deployCode = common.Hex2Bytes("608060405234801561001057600080fd5b506101d1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063cf5ba53f1461003b578063f4754f6614610050575b600080fd5b61004e6100493660046100d4565b610063565b005b61004e61005e3660046100d4565b6100bb565b60008151602083016000f09050803b61007b57600080fd5b6040516001600160a01b03821681527ff40fcec21964ffb566044d083b4073f29f7f7929110ea19e1b3ebe375d89055e9060200160405180910390a15050565b6000808251602084016000f59050803b61007b57600080fd5b6000602082840312156100e657600080fd5b813567ffffffffffffffff808211156100fe57600080fd5b818401915084601f83011261011257600080fd5b81358181111561012457610124610185565b604051601f8201601f19908116603f0116810190838211818310171561014c5761014c610185565b8160405282815287602084870101111561016557600080fd5b826020860160208301376000928101602001929092525095945050505050565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220c9bd2005b8669d44bf0254309308e422e7bdf086ac7a507990a0690a22b1eccd64736f6c63430008070033")
var callCreateCode = common.Hex2Bytes("cf5ba53f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005c6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220707985753fcb6578098bb16f3709cf6d012993cba6dd3712661cf8f57bbc0d4d64736f6c6343000807003300000000")
var callCreate2Code = common.Hex2Bytes("f4754f660000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005c6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220707985753fcb6578098bb16f3709cf6d012993cba6dd3712661cf8f57bbc0d4d64736f6c6343000807003300000000")
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker()
blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil)
)
defer blockchain.Stop()
// check empty code hash
state, _ := blockchain.State()
codeHash := state.GetCodeHash(addr1)
assert.Equal(t, codeHash, common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), "code hash mismatch")
// deploy contract through transaction
chain, receipts := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, gen *BlockGen) {
tx, _ := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, deployCode), signer, key1)
gen.AddTx(tx)
})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert chain: %v", err)
}
// make sure that the address did not change
contractAddress := receipts[0][0].ContractAddress
assert.Equal(t, common.HexToAddress("0x3A220f351252089D385b29beca14e27F204c296A"), contractAddress, "address mismatch")
state, _ = blockchain.State()
codeHash = state.GetCodeHash(contractAddress)
// keccak: 0x089bfd332dfa6117cbc20756f31801ce4f5a175eb258e46bf8123317da54cd96
assert.Equal(t, codeHash, common.HexToHash("0x28ec09723b285e17caabc4a8d52dbd097feddf408aee115cbb57c3c9c814d2b2"), "code hash mismatch")
// deploy contract through another contract (CREATE and CREATE2)
chain, receipts = GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), engine, db, 1, func(i int, gen *BlockGen) {
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), contractAddress, new(big.Int), 1000000, gen.header.BaseFee, callCreateCode), signer, key1)
gen.AddTx(tx)
tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), contractAddress, new(big.Int), 1000000, gen.header.BaseFee, callCreate2Code), signer, key1)
gen.AddTx(tx2)
})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert chain: %v", err)
}
address1 := common.BytesToAddress(receipts[0][0].Logs[0].Data)
address2 := common.BytesToAddress(receipts[0][1].Logs[0].Data)
assert.Equal(t, common.HexToAddress("0x733f1083Fe476698001FA20D651376b7b3F1CA79"), address1, "address mismatch")
assert.Equal(t, common.HexToAddress("0x4099734c88B7D091E744da0E849df0e818e7E208"), address2, "address mismatch")
state, _ = blockchain.State()
codeHash1 := state.GetCodeHash(address1)
codeHash2 := state.GetCodeHash(address2)
// keccak: 0xfb5cd93a70ce47f91d33fac3afdb7b54680a6b0683506646a108ef4dfc047583
assert.Equal(t, common.HexToHash("0x2fa5836118b70a257defd2e54064ab63cc9bb2e91823eaacbdef32370050b5b2"), codeHash1, "code hash mismatch")
assert.Equal(t, common.HexToHash("0x2fa5836118b70a257defd2e54064ab63cc9bb2e91823eaacbdef32370050b5b2"), codeHash2, "code hash mismatch")
}

View file

@ -31,7 +31,7 @@ import (
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state/snapshot" "github.com/scroll-tech/go-ethereum/core/state/snapshot"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rlp" "github.com/scroll-tech/go-ethereum/rlp"
@ -60,7 +60,7 @@ var (
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode. // emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256(nil) emptyCode = codehash.EmptyCodeHash.Bytes()
) )
// Pruner is an offline tool to prune the stale state with the // Pruner is an offline tool to prune the stale state with the

View file

@ -30,7 +30,7 @@ import (
"github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/common/math" "github.com/scroll-tech/go-ethereum/common/math"
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/ethdb/memorydb" "github.com/scroll-tech/go-ethereum/ethdb/memorydb"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
@ -44,7 +44,7 @@ var (
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode. // emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256Hash(nil) emptyCode = codehash.EmptyCodeHash
// accountCheckRange is the upper limit of the number of accounts involved in // accountCheckRange is the upper limit of the number of accounts involved in
// each range check. This is a value estimated based on experience. If this // each range check. This is a value estimated based on experience. If this

View file

@ -26,11 +26,12 @@ import (
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/metrics" "github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/rlp" "github.com/scroll-tech/go-ethereum/rlp"
) )
var emptyCodeHash = crypto.Keccak256(nil) var emptyCodeHash = codehash.EmptyCodeHash.Bytes()
type Code []byte type Code []byte

View file

@ -23,7 +23,7 @@ import (
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
) )
@ -47,7 +47,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(codehash.CodeHash([]byte{3, 3, 3, 3, 3, 3, 3}), []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))
@ -59,7 +59,7 @@ func TestDump(t *testing.T) {
// check that DumpToCollector contains the state objects that are in trie // check that DumpToCollector contains the state objects that are in trie
got := string(s.state.Dump(nil)) got := string(s.state.Dump(nil))
want := `{ want := `{
"root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2", "root": "bfd17853c56ac63be7327da432ef90a9b04376d71efede2a60765d2c94704cfe",
"accounts": { "accounts": {
"0x0000000000000000000000000000000000000001": { "0x0000000000000000000000000000000000000001": {
"balance": "22", "balance": "22",
@ -79,7 +79,7 @@ func TestDump(t *testing.T) {
"balance": "0", "balance": "0",
"nonce": 0, "nonce": 0,
"root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"codeHash": "0x87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3", "codeHash": "0x2263940ad476ca23bf01a9b033d65cd6b8bf9b7224a7ef2a4f10b61a2c039083",
"code": "0x03030303030303", "code": "0x03030303030303",
"key": "0xa17eacbc25cda025e81db9c5c62868822c73ce097cee2a63e33a2e41268358a1" "key": "0xa17eacbc25cda025e81db9c5c62868822c73ce097cee2a63e33a2e41268358a1"
} }
@ -165,7 +165,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(codehash.CodeHash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
so0.suicided = false so0.suicided = false
so0.deleted = false so0.deleted = false
state.setStateObject(so0) state.setStateObject(so0)
@ -177,7 +177,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(codehash.CodeHash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
so1.suicided = true so1.suicided = true
so1.deleted = true so1.deleted = true
state.setStateObject(so1) state.setStateObject(so1)

View file

@ -29,6 +29,7 @@ import (
"github.com/scroll-tech/go-ethereum/core/state/snapshot" "github.com/scroll-tech/go-ethereum/core/state/snapshot"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics" "github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/rlp" "github.com/scroll-tech/go-ethereum/rlp"
@ -459,7 +460,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(codehash.CodeHash(code), code)
} }
} }

View file

@ -25,6 +25,7 @@ import (
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/ethdb/memorydb" "github.com/scroll-tech/go-ethereum/ethdb/memorydb"
"github.com/scroll-tech/go-ethereum/rlp" "github.com/scroll-tech/go-ethereum/rlp"
@ -58,12 +59,12 @@ func makeTestState() (Database, common.Hash, []*testAccount) {
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(codehash.CodeHash([]byte{i, i, i, i, i}), []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 {
for j := byte(0); j < 5; j++ { for j := byte(0); j < 5; j++ {
hash := crypto.Keccak256Hash([]byte{i, i, i, i, i, j, j}) hash := codehash.CodeHash([]byte{i, i, i, i, i, j, j})
obj.SetState(db, hash, hash) obj.SetState(db, hash, hash)
} }
} }
@ -407,7 +408,7 @@ func TestIncompleteStateSync(t *testing.T) {
var isCode = make(map[common.Hash]struct{}) var isCode = make(map[common.Hash]struct{})
for _, acc := range srcAccounts { for _, acc := range srcAccounts {
if len(acc.code) > 0 { if len(acc.code) > 0 {
isCode[crypto.Keccak256Hash(acc.code)] = struct{}{} isCode[codehash.CodeHash(acc.code)] = struct{}{}
} }
} }
isCode[common.BytesToHash(emptyCodeHash)] = struct{}{} isCode[common.BytesToHash(emptyCodeHash)] = struct{}{}

View file

@ -285,7 +285,7 @@ func TestStateProcessorErrors(t *testing.T) {
txs: []*types.Transaction{ txs: []*types.Transaction{
mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)), mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)),
}, },
want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1", want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x14644f8304e8c7052dee61ac235af61e12e25a730d13beccac8b3b72f5705874",
}, },
} { } {
block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config) block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config)

View file

@ -25,11 +25,11 @@ import (
cmath "github.com/scroll-tech/go-ethereum/common/math" cmath "github.com/scroll-tech/go-ethereum/common/math"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/core/vm" "github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
) )
var emptyCodeHash = crypto.Keccak256Hash(nil) var emptyCodeHash = codehash.EmptyCodeHash
/* /*
The State Transitioning Model The State Transitioning Model

View file

@ -3,7 +3,7 @@ package zktrie
import ( import (
"math/big" "math/big"
"github.com/iden3/go-iden3-crypto/poseidon" "github.com/scroll-tech/go-ethereum/crypto/poseidon"
) )
// HashElems performs a recursive poseidon hash over the array of ElemBytes, each hash // HashElems performs a recursive poseidon hash over the array of ElemBytes, each hash
@ -11,7 +11,7 @@ import (
func HashElems(fst, snd *big.Int, elems ...*big.Int) (*Hash, error) { func HashElems(fst, snd *big.Int, elems ...*big.Int) (*Hash, error) {
l := len(elems) l := len(elems)
baseH, err := poseidon.Hash([]*big.Int{fst, snd}) baseH, err := poseidon.HashFixed([]*big.Int{fst, snd})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -26,7 +26,7 @@ func HashElems(fst, snd *big.Int, elems ...*big.Int) (*Hash, error) {
if (i+1)*2 > l { if (i+1)*2 > l {
tmp[i] = elems[i*2+1] tmp[i] = elems[i*2+1]
} else { } else {
h, err := poseidon.Hash(elems[i*2 : (i+1)*2]) h, err := poseidon.HashFixed(elems[i*2 : (i+1)*2])
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -25,12 +25,13 @@ import (
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
) )
// emptyCodeHash is used by create to ensure deployment is disallowed to already // emptyCodeHash is used by create to ensure deployment is disallowed to already
// deployed contract addresses (relevant after the account abstraction). // deployed contract addresses (relevant after the account abstraction).
var emptyCodeHash = crypto.Keccak256Hash(nil) var emptyCodeHash = codehash.EmptyCodeHash
type ( type (
// CanTransferFunc is the signature of a transfer guard function // CanTransferFunc is the signature of a transfer guard function
@ -410,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

View file

@ -0,0 +1,16 @@
package codehash
import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto/poseidon"
)
var EmptyCodeHash common.Hash
func CodeHash(code []byte) (h common.Hash) {
return poseidon.CodeHash(code)
}
func init() {
EmptyCodeHash = poseidon.CodeHash(nil)
}

View file

@ -0,0 +1,47 @@
package poseidon
import (
"math/big"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto"
)
const defaultPoseidonChunk = 3
func CodeHash(code []byte) (h common.Hash) {
// special case for nil hash
if len(code) == 0 {
return crypto.Keccak256Hash(nil)
}
cap := int64(len(code))
// step 1: pad code with 0x0 (STOP) so that len(code) % 16 == 0
// step 2: for every 16 bytes, convert to Fr, so that we get a Fr array
var length = (len(code) + 15) / 16
Frs := make([]*big.Int, length)
ii := 0
for ii < length-1 {
Frs[ii] = big.NewInt(0)
Frs[ii].SetBytes(code[ii*16 : (ii+1)*16])
ii++
}
Frs[ii] = big.NewInt(0)
bytes := make([]byte, 16)
copy(bytes, code[ii*16:])
Frs[ii].SetBytes(bytes)
// step 3: apply the array onto a sponge process with the current poseidon scheme
// (3 Frs permutation and 1 Fr for output, so the throughout is 2 Frs)
// step 4: convert final root Fr to u256 (big-endian representation)
hash, _ := HashWithCap(Frs, defaultPoseidonChunk, cap)
codeHash := common.Hash{}
hash.FillBytes(codeHash[:])
return codeHash
}

View file

@ -0,0 +1,24 @@
package poseidon
import (
"fmt"
"testing"
)
func TestPoseidonCodeHash(t *testing.T) {
// nil
got := fmt.Sprintf("%s", CodeHash(nil))
want := "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
if got != want {
t.Errorf("got %q, wanted %q", got, want)
}
// single byte
got = fmt.Sprintf("%s", CodeHash([]byte{0}))
want = "0x0ee069e6aa796ef0e46cbd51d10468393d443a00f5affe72898d9ab62e335e16"
if got != want {
t.Errorf("got %q, wanted %q", got, want)
}
}

24906
crypto/poseidon/constants.go Normal file

File diff suppressed because it is too large Load diff

192
crypto/poseidon/poseidon.go Normal file
View file

@ -0,0 +1,192 @@
// from github.com/iden3/go-iden3-crypto/ff/poseidon
package poseidon
import (
"errors"
"fmt"
"math/big"
"github.com/iden3/go-iden3-crypto/ff"
"github.com/iden3/go-iden3-crypto/utils"
)
const NROUNDSF = 8 //nolint:golint
var NROUNDSP = []int{56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68} //nolint:golint
func zero() *ff.Element {
return ff.NewElement()
}
// exp5 performs x^5 mod p
// https://eprint.iacr.org/2019/458.pdf page 8
func exp5(a *ff.Element) {
a.Exp(*a, big.NewInt(5)) //nolint:gomnd
}
// exp5state perform exp5 for whole state
func exp5state(state []*ff.Element) {
for i := 0; i < len(state); i++ {
exp5(state[i])
}
}
// ark computes Add-Round Key, from the paper https://eprint.iacr.org/2019/458.pdf
func ark(state []*ff.Element, c []*ff.Element, it int) {
for i := 0; i < len(state); i++ {
state[i].Add(state[i], c[it+i])
}
}
// mix returns [[matrix]] * [vector]
func mix(state []*ff.Element, t int, m [][]*ff.Element) []*ff.Element {
mul := zero()
newState := make([]*ff.Element, t)
for i := 0; i < t; i++ {
newState[i] = zero()
}
for i := 0; i < len(state); i++ {
newState[i].SetUint64(0)
for j := 0; j < len(state); j++ {
mul.Mul(m[j][i], state[j])
newState[i].Add(newState[i], mul)
}
}
return newState
}
func permute(state []*ff.Element, t int) []*ff.Element {
nRoundsF := NROUNDSF
nRoundsP := NROUNDSP[t-2]
C := c.c[t-2]
S := c.s[t-2]
M := c.m[t-2]
P := c.p[t-2]
ark(state, C, 0)
for i := 0; i < nRoundsF/2-1; i++ {
exp5state(state)
ark(state, C, (i+1)*t)
state = mix(state, t, M)
}
exp5state(state)
ark(state, C, (nRoundsF/2)*t)
state = mix(state, t, P)
for i := 0; i < nRoundsP; i++ {
exp5(state[0])
state[0].Add(state[0], C[(nRoundsF/2+1)*t+i])
mul := zero()
newState0 := zero()
for j := 0; j < len(state); j++ {
mul.Mul(S[(t*2-1)*i+j], state[j])
newState0.Add(newState0, mul)
}
for k := 1; k < t; k++ {
mul = zero()
state[k] = state[k].Add(state[k], mul.Mul(state[0], S[(t*2-1)*i+t+k-1]))
}
state[0] = newState0
}
for i := 0; i < nRoundsF/2-1; i++ {
exp5state(state)
ark(state, C, (nRoundsF/2+1)*t+nRoundsP+i*t)
state = mix(state, t, M)
}
exp5state(state)
return mix(state, t, M)
}
// for short, use size of inpBI as cap
func Hash(inpBI []*big.Int, width int) (*big.Int, error) {
return HashWithCap(inpBI, width, int64(len(inpBI)))
}
// Hash using possible sponge specs specified by width (rate from 1 to 15), the size of input is applied as capacity
// (notice we do not include width in the capacity )
func HashWithCap(inpBI []*big.Int, width int, cap int64) (*big.Int, error) {
if width < 2 {
return nil, fmt.Errorf("width must be ranged from 2 to 16")
}
if width-2 > len(NROUNDSP) {
return nil, fmt.Errorf("invalid inputs width %d, max %d", width, len(NROUNDSP)+1) //nolint:gomnd,lll
}
capflag := ff.NewElement().SetBigInt(big.NewInt(cap))
state := make([]*ff.Element, width)
state[0] = capflag
for i := 1; i < width; i++ {
state[i] = zero()
}
rate := width - 1
var absorb []*ff.Element
for len(inpBI) > 0 {
// sponge for fully absorb
if l := len(absorb); l != 0 {
//sanity check
if l != rate {
panic("unexpected absorption size")
}
for i, elm := range absorb {
state[i+1].Add(state[i+1], elm)
}
state = permute(state, width)
}
// absorb
if len(inpBI) < rate {
// padding zero() equal to no action on state
absorb = utils.BigIntArrayToElementArray(inpBI)
inpBI = nil
} else {
absorb = utils.BigIntArrayToElementArray(inpBI[:rate])
inpBI = inpBI[rate:]
}
}
//last time sponge (padding with unabsorb items)
for i, elm := range absorb {
state[i+1].Add(state[i+1], elm)
}
state = permute(state, width)
//squeeze
rE := state[0]
r := big.NewInt(0)
rE.ToBigIntRegular(r)
return r, nil
}
// Hash computes the Poseidon hash for the given fixed-size inputs, select specs automatically from the size, no capacity flag is applied
func HashFixed(inpBI []*big.Int) (*big.Int, error) {
t := len(inpBI) + 1
if len(inpBI) == 0 || len(inpBI) > len(NROUNDSP) {
return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP)) //nolint:gomnd,lll
}
if !utils.CheckBigIntArrayInField(inpBI[:]) {
return nil, errors.New("inputs values not inside Finite Field")
}
inp := utils.BigIntArrayToElementArray(inpBI[:])
state := make([]*ff.Element, t)
state[0] = zero()
copy(state[1:], inp[:])
state = permute(state, t)
rE := state[0]
r := big.NewInt(0)
rE.ToBigIntRegular(r)
return r, nil
}

View file

@ -0,0 +1,170 @@
// from github.com/iden3/go-iden3-crypto/ff/poseidon
package poseidon
import (
"math/big"
"testing"
"github.com/iden3/go-iden3-crypto/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPoseidonHashFixed(t *testing.T) {
b0 := big.NewInt(0)
b1 := big.NewInt(1)
b2 := big.NewInt(2)
b3 := big.NewInt(3)
b4 := big.NewInt(4)
b5 := big.NewInt(5)
b6 := big.NewInt(6)
b7 := big.NewInt(7)
b8 := big.NewInt(8)
b9 := big.NewInt(9)
b10 := big.NewInt(10)
b11 := big.NewInt(11)
b12 := big.NewInt(12)
b13 := big.NewInt(13)
b14 := big.NewInt(14)
b15 := big.NewInt(15)
b16 := big.NewInt(16)
h, err := HashFixed([]*big.Int{b1})
assert.Nil(t, err)
assert.Equal(t,
"18586133768512220936620570745912940619677854269274689475585506675881198879027",
h.String())
h, err = HashFixed([]*big.Int{b1, b2})
assert.Nil(t, err)
assert.Equal(t,
"7853200120776062878684798364095072458815029376092732009249414926327459813530",
h.String())
h, err = HashFixed([]*big.Int{b1, b2, b0, b0, b0})
assert.Nil(t, err)
assert.Equal(t,
"1018317224307729531995786483840663576608797660851238720571059489595066344487",
h.String())
h, err = HashFixed([]*big.Int{b1, b2, b0, b0, b0, b0})
assert.Nil(t, err)
assert.Equal(t,
"15336558801450556532856248569924170992202208561737609669134139141992924267169",
h.String())
h, err = HashFixed([]*big.Int{b3, b4, b0, b0, b0})
assert.Nil(t, err)
assert.Equal(t,
"5811595552068139067952687508729883632420015185677766880877743348592482390548",
h.String())
h, err = HashFixed([]*big.Int{b3, b4, b0, b0, b0, b0})
assert.Nil(t, err)
assert.Equal(t,
"12263118664590987767234828103155242843640892839966517009184493198782366909018",
h.String())
h, err = HashFixed([]*big.Int{b1, b2, b3, b4, b5, b6})
assert.Nil(t, err)
assert.Equal(t,
"20400040500897583745843009878988256314335038853985262692600694741116813247201",
h.String())
h, err = HashFixed([]*big.Int{b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14})
assert.Nil(t, err)
assert.Equal(t,
"8354478399926161176778659061636406690034081872658507739535256090879947077494",
h.String())
h, err = HashFixed([]*big.Int{b1, b2, b3, b4, b5, b6, b7, b8, b9, b0, b0, b0, b0, b0})
assert.Nil(t, err)
assert.Equal(t,
"5540388656744764564518487011617040650780060800286365721923524861648744699539",
h.String())
h, err = HashFixed([]*big.Int{b1, b2, b3, b4, b5, b6, b7, b8, b9, b0, b0, b0, b0, b0, b0, b0})
assert.Nil(t, err)
assert.Equal(t,
"11882816200654282475720830292386643970958445617880627439994635298904836126497",
h.String())
h, err = HashFixed([]*big.Int{b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16})
assert.Nil(t, err)
assert.Equal(t,
"9989051620750914585850546081941653841776809718687451684622678807385399211877",
h.String())
}
func TestErrorInputs(t *testing.T) {
b0 := big.NewInt(0)
b1 := big.NewInt(1)
b2 := big.NewInt(2)
var err error
_, err = HashFixed([]*big.Int{b1, b2, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0})
require.Nil(t, err)
_, err = HashFixed([]*big.Int{b1, b2, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0})
require.NotNil(t, err)
assert.Equal(t, "invalid inputs length 17, max 16", err.Error())
_, err = HashFixed([]*big.Int{b1, b2, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0})
require.NotNil(t, err)
assert.Equal(t, "invalid inputs length 18, max 16", err.Error())
}
func TestInputsNotInField(t *testing.T) {
var err error
// Very big number, should just return error and not go into endless loop
b1 := utils.NewIntFromString("12242166908188651009877250812424843524687801523336557272219921456462821518061999999999999999999999999999999999999999999999999999999999") //nolint:lll
_, err = HashFixed([]*big.Int{b1})
require.Error(t, err, "inputs values not inside Finite Field")
// Finite Field const Q, should return error
b2 := utils.NewIntFromString("21888242871839275222246405745257275088548364400416034343698204186575808495617") //nolint:lll
_, err = HashFixed([]*big.Int{b2})
require.Error(t, err, "inputs values not inside Finite Field")
}
func TestPoseidonHash(t *testing.T) {
ret, err := Hash(nil, 3)
if err != nil {
t.Fatal(err)
}
// Hash nil for width 3 equal to Hash([0, 0])
retRef, err := HashFixed([]*big.Int{big.NewInt(0), big.NewInt(0)})
if err != nil {
t.Fatal(err)
}
assert.Equal(t, ret, retRef)
// hash is different for the cap flag
ret1, err := Hash([]*big.Int{big.NewInt(0)}, 3)
if err != nil {
t.Fatal(err)
}
assert.NotEqual(t, ret1, retRef)
ret2, err := HashWithCap([]*big.Int{big.NewInt(0)}, 3, 0)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, ret2, retRef)
}
func BenchmarkPoseidonHash(b *testing.B) {
b0 := big.NewInt(0)
b1 := utils.NewIntFromString("12242166908188651009877250812424843524687801523336557272219921456462821518061") //nolint:lll
b2 := utils.NewIntFromString("12242166908188651009877250812424843524687801523336557272219921456462821518061") //nolint:lll
bigArray4 := []*big.Int{b1, b2, b0, b0, b0, b0}
for i := 0; i < b.N; i++ {
HashFixed(bigArray4) //nolint:errcheck,gosec
}
}

View file

@ -36,6 +36,7 @@ import (
"github.com/scroll-tech/go-ethereum/core/state/snapshot" "github.com/scroll-tech/go-ethereum/core/state/snapshot"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/event" "github.com/scroll-tech/go-ethereum/event"
"github.com/scroll-tech/go-ethereum/light" "github.com/scroll-tech/go-ethereum/light"
@ -50,7 +51,7 @@ var (
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode. // emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256Hash(nil) emptyCode = codehash.EmptyCodeHash
) )
const ( const (

7
go.mod
View file

@ -56,9 +56,10 @@ require (
github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
golang.org/x/text v0.3.6 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f
golang.org/x/text v0.3.7
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6

16
go.sum
View file

@ -492,8 +492,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -507,8 +508,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -548,19 +550,23 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View file

@ -42,6 +42,7 @@ import (
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/core/vm" "github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/p2p" "github.com/scroll-tech/go-ethereum/p2p"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
@ -672,7 +673,7 @@ func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Addre
storageHash = storageTrie.Hash() storageHash = storageTrie.Hash()
} else { } else {
// no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray. // no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray.
codeHash = crypto.Keccak256Hash(nil) codeHash = codehash.EmptyCodeHash
} }
// create the proof for the storageKeys // create the proof for the storageKeys

View file

@ -26,15 +26,12 @@ import (
"github.com/scroll-tech/go-ethereum/core/state" "github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/rlp" "github.com/scroll-tech/go-ethereum/rlp"
"github.com/scroll-tech/go-ethereum/trie" "github.com/scroll-tech/go-ethereum/trie"
) )
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 +70,7 @@ func (db *odrDatabase) CopyTrie(t state.Trie) state.Trie {
} }
func (db *odrDatabase) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { func (db *odrDatabase) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) {
if codeHash == sha3Nil { if codeHash == codehash.EmptyCodeHash {
return nil, nil return nil, nil
} }
code := rawdb.ReadCode(db.backend.Database(), codeHash) code := rawdb.ReadCode(db.backend.Database(), codeHash)

View file

@ -23,6 +23,7 @@ import (
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/prque" "github.com/scroll-tech/go-ethereum/common/prque"
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
) )
@ -189,7 +190,7 @@ func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, cal
// as is. // as is.
func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash) { func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash) {
// Short circuit if the entry is empty or already known // Short circuit if the entry is empty or already known
if hash == emptyState { if hash == codehash.EmptyCodeHash {
return return
} }
if s.membatch.hasCode(hash) { if s.membatch.hasCode(hash) {

View file

@ -36,6 +36,7 @@ import (
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/codehash"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/ethdb/leveldb" "github.com/scroll-tech/go-ethereum/ethdb/leveldb"
"github.com/scroll-tech/go-ethereum/ethdb/memorydb" "github.com/scroll-tech/go-ethereum/ethdb/memorydb"
@ -649,7 +650,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
var ( var (
nonce = uint64(random.Int63()) nonce = uint64(random.Int63())
root = emptyRoot root = emptyRoot
code = crypto.Keccak256(nil) code = codehash.EmptyCodeHash.Bytes()
) )
// 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.