mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core, params, cmd: implement eip1702
This commit is contained in:
parent
beff5fa578
commit
a8711c035d
21 changed files with 292 additions and 139 deletions
|
|
@ -203,10 +203,10 @@ func runCmd(ctx *cli.Context) error {
|
|||
var leftOverGas uint64
|
||||
if ctx.GlobalBool(CreateFlag.Name) {
|
||||
input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...)
|
||||
ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig)
|
||||
ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig) // The default code version is 0.
|
||||
} else {
|
||||
if len(code) > 0 {
|
||||
statedb.SetCode(receiver, code)
|
||||
statedb.SetCode(receiver, code, 0)
|
||||
}
|
||||
ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
|
|||
CanTransfer: CanTransfer,
|
||||
Transfer: Transfer,
|
||||
GetHash: GetHashFn(header, chain),
|
||||
ValidateCode: ValidateCode,
|
||||
Origin: msg.From(),
|
||||
Coinbase: beneficiary,
|
||||
BlockNumber: new(big.Int).Set(header.Number),
|
||||
|
|
@ -95,3 +96,10 @@ func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int)
|
|||
db.SubBalance(sender, amount)
|
||||
db.AddBalance(recipient, amount)
|
||||
}
|
||||
|
||||
// ValidateCode returns an indicator whether the given code is valid.
|
||||
func ValidateCode(version uint64, code []byte) bool {
|
||||
// When code version is 0, the validation does nothing and always succeeds.
|
||||
// Future VM versions can define additional validation that has to be passed.
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
|
|||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||
for addr, account := range g.Alloc {
|
||||
statedb.AddBalance(addr, account.Balance)
|
||||
statedb.SetCode(addr, account.Code)
|
||||
statedb.SetCode(addr, account.Code, 0) // Should all genesis accounts' code version being 0?
|
||||
statedb.SetNonce(addr, account.Nonce)
|
||||
for key, value := range account.Storage {
|
||||
statedb.SetState(addr, key, value)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ type DumpAccount struct {
|
|||
Root string `json:"root"`
|
||||
CodeHash string `json:"codeHash"`
|
||||
Code string `json:"code,omitempty"`
|
||||
CodeVersion uint64 `json:"codeVersion"`
|
||||
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
|
||||
|
|
@ -70,6 +71,7 @@ func (self iterativeDump) onAccount(addr common.Address, account DumpAccount) {
|
|||
Root: account.Root,
|
||||
CodeHash: account.CodeHash,
|
||||
Code: account.Code,
|
||||
CodeVersion: account.CodeVersion,
|
||||
Storage: account.Storage,
|
||||
SecureKey: account.SecureKey,
|
||||
Address: nil,
|
||||
|
|
@ -86,7 +88,7 @@ func (self iterativeDump) onRoot(root common.Hash) {
|
|||
}
|
||||
|
||||
func (self *StateDB) dump(c collector, excludeCode, excludeStorage, excludeMissingPreimages bool) {
|
||||
emptyAddress := (common.Address{})
|
||||
emptyAddress := common.Address{}
|
||||
missingPreimages := 0
|
||||
c.onRoot(self.trie.Hash())
|
||||
it := trie.NewIterator(self.trie.NodeIterator(nil))
|
||||
|
|
@ -102,6 +104,7 @@ func (self *StateDB) dump(c collector, excludeCode, excludeStorage, excludeMissi
|
|||
Nonce: data.Nonce,
|
||||
Root: common.Bytes2Hex(data.Root[:]),
|
||||
CodeHash: common.Bytes2Hex(data.CodeHash),
|
||||
CodeVersion: data.CodeVersion,
|
||||
}
|
||||
if emptyAddress == addr {
|
||||
// Preimage missing
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ type (
|
|||
codeChange struct {
|
||||
account *common.Address
|
||||
prevcode, prevhash []byte
|
||||
version uint64
|
||||
}
|
||||
|
||||
// Changes to other state values.
|
||||
|
|
@ -188,7 +189,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(common.BytesToHash(ch.prevhash), ch.prevcode, ch.version)
|
||||
}
|
||||
|
||||
func (ch codeChange) dirtied() *common.Address {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ func (s Storage) String() (str string) {
|
|||
for key, value := range s {
|
||||
str += fmt.Sprintf("%X : %X\n", key, value)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +51,6 @@ func (s Storage) Copy() Storage {
|
|||
for key, value := range s {
|
||||
cpy[key] = value
|
||||
}
|
||||
|
||||
return cpy
|
||||
}
|
||||
|
||||
|
|
@ -95,13 +93,75 @@ func (s *stateObject) empty() bool {
|
|||
return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash)
|
||||
}
|
||||
|
||||
// Account is the Ethereum consensus representation of accounts.
|
||||
// These objects are stored in the main account trie.
|
||||
// legacyStoredAccount is the legacy storage encoding of a state object used in
|
||||
// database.
|
||||
type legacyStoredAccount struct {
|
||||
Nonce uint64 // The nonce of account.
|
||||
Balance *big.Int // The balance of account.
|
||||
Root common.Hash // Merkle root of the storage trie
|
||||
CodeHash []byte // The code hash of account.
|
||||
}
|
||||
|
||||
// storedAccount is the storage encoding of a state object used in database which
|
||||
// includes code version field introduced by EIP1702.
|
||||
type storedAccount Account
|
||||
|
||||
// Account is ethereum consensus representation of accounts. These objects are
|
||||
// stored in the main account trie.
|
||||
type Account struct {
|
||||
Nonce uint64
|
||||
Balance *big.Int
|
||||
Root common.Hash // merkle root of the storage trie
|
||||
CodeHash []byte
|
||||
Nonce uint64 // The nonce of account.
|
||||
Balance *big.Int // The balance of account.
|
||||
Root common.Hash // Merkle root of the storage trie.
|
||||
CodeHash []byte // The code hash of account.
|
||||
CodeVersion uint64 // The version of account code.
|
||||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (a *Account) EncodeRLP(w io.Writer) error {
|
||||
if a.CodeVersion == 0 {
|
||||
return rlp.Encode(w, legacyStoredAccount{a.Nonce, a.Balance, a.Root, a.CodeHash})
|
||||
}
|
||||
return rlp.Encode(w, storedAccount(*a))
|
||||
}
|
||||
|
||||
// EncodeRLP implements rlp.Decoder.
|
||||
func (a *Account) DecodeRLP(r *rlp.Stream) error {
|
||||
blob, err := r.Raw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elems, _, err := rlp.SplitList(blob)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch c, _ := rlp.CountValues(elems); c {
|
||||
case 4:
|
||||
return decodeLegacyAccount(a, blob)
|
||||
case 5:
|
||||
return decodeAccount(a, blob)
|
||||
default:
|
||||
return fmt.Errorf("invalid number of list elements: %v", c)
|
||||
}
|
||||
}
|
||||
|
||||
// decodeLegacyAccount decodes the account information from legacy format blob.
|
||||
func decodeLegacyAccount(a *Account, blob []byte) error {
|
||||
var dec legacyStoredAccount
|
||||
if err := rlp.DecodeBytes(blob, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Nonce, a.Balance, a.Root, a.CodeHash = dec.Nonce, dec.Balance, dec.Root, dec.CodeHash
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodeAccount decodes the account information from current format blob.
|
||||
func decodeAccount(a *Account, blob []byte) error {
|
||||
var dec storedAccount
|
||||
if err := rlp.DecodeBytes(blob, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
*a = Account(dec)
|
||||
return nil
|
||||
}
|
||||
|
||||
// newObject creates a state object.
|
||||
|
|
@ -124,7 +184,7 @@ func newObject(db *StateDB, address common.Address, data Account) *stateObject {
|
|||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (s *stateObject) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, s.data)
|
||||
return rlp.Encode(w, &s.data)
|
||||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
|
|
@ -355,19 +415,21 @@ func (s *stateObject) Code(db Database) []byte {
|
|||
return code
|
||||
}
|
||||
|
||||
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
|
||||
func (s *stateObject) SetCode(codeHash common.Hash, code []byte, version uint64) {
|
||||
prevcode := s.Code(s.db.db)
|
||||
s.db.journal.append(codeChange{
|
||||
account: &s.address,
|
||||
prevhash: s.CodeHash(),
|
||||
prevcode: prevcode,
|
||||
version: s.data.CodeVersion,
|
||||
})
|
||||
s.setCode(codeHash, code)
|
||||
s.setCode(codeHash, code, version)
|
||||
}
|
||||
|
||||
func (s *stateObject) setCode(codeHash common.Hash, code []byte) {
|
||||
func (s *stateObject) setCode(codeHash common.Hash, code []byte, version uint64) {
|
||||
s.code = code
|
||||
s.data.CodeHash = codeHash[:]
|
||||
s.data.CodeVersion = version
|
||||
s.dirtyCode = true
|
||||
}
|
||||
|
||||
|
|
@ -395,6 +457,10 @@ func (s *stateObject) Nonce() uint64 {
|
|||
return s.data.Nonce
|
||||
}
|
||||
|
||||
func (s *stateObject) CodeVersion() uint64 {
|
||||
return s.data.CodeVersion
|
||||
}
|
||||
|
||||
// Never called, but must be present to allow stateObject to be used
|
||||
// as a vm.Account interface that also satisfies the vm.ContractRef
|
||||
// interface. Interfaces are awesome.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
|
|||
obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01}))
|
||||
obj1.AddBalance(big.NewInt(22))
|
||||
obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02}))
|
||||
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
|
||||
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}, 0)
|
||||
obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02}))
|
||||
obj3.SetBalance(big.NewInt(44))
|
||||
|
||||
|
|
@ -60,20 +60,23 @@ func (s *StateSuite) TestDump(c *checker.C) {
|
|||
"balance": "22",
|
||||
"nonce": 0,
|
||||
"root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||
"codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
|
||||
"codeVersion": 0
|
||||
},
|
||||
"0x0000000000000000000000000000000000000002": {
|
||||
"balance": "44",
|
||||
"nonce": 0,
|
||||
"root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||
"codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
|
||||
"codeVersion": 0
|
||||
},
|
||||
"0x0000000000000000000000000000000000000102": {
|
||||
"balance": "0",
|
||||
"nonce": 0,
|
||||
"root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"codeHash": "87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3",
|
||||
"code": "03030303030303"
|
||||
"code": "03030303030303",
|
||||
"codeVersion": 0
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
|
@ -153,7 +156,7 @@ func TestSnapshot2(t *testing.T) {
|
|||
so0 := state.getStateObject(stateobjaddr0)
|
||||
so0.SetBalance(big.NewInt(42))
|
||||
so0.SetNonce(43)
|
||||
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
|
||||
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}, 0)
|
||||
so0.suicided = false
|
||||
so0.deleted = false
|
||||
state.setStateObject(so0)
|
||||
|
|
@ -165,7 +168,7 @@ func TestSnapshot2(t *testing.T) {
|
|||
so1 := state.getStateObject(stateobjaddr1)
|
||||
so1.SetBalance(big.NewInt(52))
|
||||
so1.SetNonce(53)
|
||||
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
|
||||
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}, 0)
|
||||
so1.suicided = true
|
||||
so1.deleted = true
|
||||
state.setStateObject(so1)
|
||||
|
|
|
|||
|
|
@ -278,6 +278,14 @@ func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
|
|||
return common.BytesToHash(stateObject.CodeHash())
|
||||
}
|
||||
|
||||
func (self *StateDB) GetCodeVersion(addr common.Address) uint64 {
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject == nil {
|
||||
return 0
|
||||
}
|
||||
return stateObject.CodeVersion()
|
||||
}
|
||||
|
||||
// GetState retrieves a value from the given account's storage trie.
|
||||
func (self *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
|
||||
stateObject := self.getStateObject(addr)
|
||||
|
|
@ -372,10 +380,10 @@ func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *StateDB) SetCode(addr common.Address, code []byte) {
|
||||
func (self *StateDB) SetCode(addr common.Address, code []byte, version uint64) {
|
||||
stateObject := self.GetOrNewStateObject(addr)
|
||||
if stateObject != nil {
|
||||
stateObject.SetCode(crypto.Keccak256Hash(code), code)
|
||||
stateObject.SetCode(crypto.Keccak256Hash(code), code, version)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -488,7 +496,6 @@ func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
|
|||
func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
|
||||
prev = self.getStateObject(addr)
|
||||
newobj = newObject(self, addr, Account{})
|
||||
newobj.setNonce(0) // sets the object to dirty
|
||||
if prev == nil {
|
||||
self.journal.append(createObjectChange{account: &addr})
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ 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/rlp"
|
||||
)
|
||||
|
||||
// Tests that updating a state trie does not leak any database writes prior to
|
||||
|
|
@ -51,7 +52,7 @@ func TestUpdateLeaks(t *testing.T) {
|
|||
state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
|
||||
}
|
||||
if i%3 == 0 {
|
||||
state.SetCode(addr, []byte{i, i, i, i, i})
|
||||
state.SetCode(addr, []byte{i, i, i, i, i}, 0)
|
||||
}
|
||||
state.IntermediateRoot(false)
|
||||
}
|
||||
|
|
@ -80,7 +81,7 @@ func TestIntermediateLeaks(t *testing.T) {
|
|||
state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak})
|
||||
}
|
||||
if i%3 == 0 {
|
||||
state.SetCode(addr, []byte{i, i, i, i, i, tweak})
|
||||
state.SetCode(addr, []byte{i, i, i, i, i, tweak}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,10 +248,10 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
|
|||
fn: func(a testAction, s *StateDB) {
|
||||
code := make([]byte, 16)
|
||||
binary.BigEndian.PutUint64(code, uint64(a.args[0]))
|
||||
binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
|
||||
s.SetCode(addr, code)
|
||||
binary.BigEndian.PutUint64(code[8:16], uint64(a.args[1]))
|
||||
s.SetCode(addr, code, uint64(a.args[2]))
|
||||
},
|
||||
args: make([]int64, 2),
|
||||
args: make([]int64, 3),
|
||||
},
|
||||
{
|
||||
name: "CreateAccount",
|
||||
|
|
@ -449,3 +450,49 @@ func TestCopyOfCopy(t *testing.T) {
|
|||
t.Fatalf("2nd copy fail, expected 42, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateObjectDecoding(t *testing.T) {
|
||||
var accounts = []Account{
|
||||
{
|
||||
Nonce: 100,
|
||||
Balance: big.NewInt(100),
|
||||
Root: common.HexToHash("deadbeef"),
|
||||
CodeHash: []byte{0x01, 0x02, 0x03},
|
||||
},
|
||||
{
|
||||
Nonce: 100,
|
||||
Balance: big.NewInt(100),
|
||||
Root: common.HexToHash("deadbeef"),
|
||||
CodeHash: []byte{0x01, 0x02, 0x03},
|
||||
CodeVersion: 0,
|
||||
},
|
||||
{
|
||||
Nonce: 100,
|
||||
Balance: big.NewInt(100),
|
||||
Root: common.HexToHash("deadbeef"),
|
||||
CodeHash: []byte{0x01, 0x02, 0x03},
|
||||
CodeVersion: 1,
|
||||
},
|
||||
{
|
||||
Nonce: 100,
|
||||
Balance: big.NewInt(100),
|
||||
Root: common.HexToHash("deadbeef"),
|
||||
CodeHash: []byte{0x01, 0x02, 0x03},
|
||||
CodeVersion: math.MaxUint64,
|
||||
},
|
||||
}
|
||||
for _, acct := range accounts {
|
||||
blob, err := rlp.EncodeToBytes(&acct)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to encode account %v", err)
|
||||
}
|
||||
var dec Account
|
||||
err = rlp.DecodeBytes(blob, &dec)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to decode account %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(acct, dec) {
|
||||
t.Fatalf("Mismatch after encoding/decoding, want %v, has %v", acct, dec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func makeTestState() (Database, common.Hash, []*testAccount) {
|
|||
acc.nonce = uint64(42 * i)
|
||||
|
||||
if i%3 == 0 {
|
||||
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
|
||||
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i}, 0)
|
||||
acc.code = []byte{i, i, i, i, i}
|
||||
}
|
||||
state.updateStateObject(obj)
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
var (
|
||||
errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas")
|
||||
)
|
||||
var errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas")
|
||||
|
||||
/*
|
||||
The State Transitioning Model
|
||||
|
|
@ -206,7 +204,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
|
|||
vmerr error
|
||||
)
|
||||
if contractCreation {
|
||||
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
|
||||
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value, st.evm.ChainConfig().LatestCodeVersion)
|
||||
} else {
|
||||
// Increment the nonce for the next transaction
|
||||
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ type Contract struct {
|
|||
CodeAddr *common.Address
|
||||
Input []byte
|
||||
|
||||
CodeVersion uint64
|
||||
Gas uint64
|
||||
value *big.Int
|
||||
}
|
||||
|
|
@ -169,16 +170,18 @@ func (c *Contract) Value() *big.Int {
|
|||
|
||||
// SetCallCode sets the code of the contract and address of the backing data
|
||||
// object
|
||||
func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
|
||||
func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte, version uint64) {
|
||||
c.Code = code
|
||||
c.CodeHash = hash
|
||||
c.CodeAddr = addr
|
||||
c.CodeVersion = version
|
||||
}
|
||||
|
||||
// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash.
|
||||
// In case hash is not provided, the jumpdest analysis will not be saved to the parent context
|
||||
func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash) {
|
||||
func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash, version uint64) {
|
||||
c.Code = codeAndHash.code
|
||||
c.CodeHash = codeAndHash.hash
|
||||
c.CodeAddr = addr
|
||||
c.CodeVersion = version
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,18 @@ var emptyCodeHash = crypto.Keccak256Hash(nil)
|
|||
type (
|
||||
// CanTransferFunc is the signature of a transfer guard function
|
||||
CanTransferFunc func(StateDB, common.Address, *big.Int) bool
|
||||
|
||||
// TransferFunc is the signature of a transfer function
|
||||
TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
|
||||
|
||||
// GetHashFunc returns the nth block hash in the blockchain
|
||||
// and is used by the BLOCKHASH EVM op code.
|
||||
GetHashFunc func(uint64) common.Hash
|
||||
|
||||
// ValidateCodeFunc returns an indicator whether the given contract
|
||||
// code is valid or not. If false is returned, the transaction is failed
|
||||
// and returns out-of-gas.
|
||||
ValidateCodeFunc func(uint64, []byte) bool
|
||||
)
|
||||
|
||||
// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
|
||||
|
|
@ -54,7 +61,8 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
|
|||
return RunPrecompiledContract(p, input, contract)
|
||||
}
|
||||
}
|
||||
for _, interpreter := range evm.interpreters {
|
||||
interpreters := evm.interpreters[contract.CodeVersion]
|
||||
for _, interpreter := range interpreters {
|
||||
if interpreter.CanRun(contract.Code) {
|
||||
if evm.interpreter != interpreter {
|
||||
// Ensure that the interpreter pointer is set back
|
||||
|
|
@ -76,11 +84,16 @@ type Context struct {
|
|||
// CanTransfer returns whether the account contains
|
||||
// sufficient ether to transfer the value
|
||||
CanTransfer CanTransferFunc
|
||||
|
||||
// Transfer transfers ether from one account to the other
|
||||
Transfer TransferFunc
|
||||
|
||||
// GetHash returns the hash corresponding to n
|
||||
GetHash GetHashFunc
|
||||
|
||||
// ValidateCode returns whether the contract code is valid.
|
||||
ValidateCode ValidateCodeFunc
|
||||
|
||||
// Message information
|
||||
Origin common.Address // Provides information for ORIGIN
|
||||
GasPrice *big.Int // Provides information for GASPRICE
|
||||
|
|
@ -119,7 +132,7 @@ type EVM struct {
|
|||
vmConfig Config
|
||||
// global (to this context) ethereum virtual machine
|
||||
// used throughout the execution of the tx.
|
||||
interpreters []Interpreter
|
||||
interpreters map[uint64][]Interpreter
|
||||
interpreter Interpreter
|
||||
// abort is used to abort the EVM calling operations
|
||||
// NOTE: must be set atomically
|
||||
|
|
@ -139,7 +152,7 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
|
|||
vmConfig: vmConfig,
|
||||
chainConfig: chainConfig,
|
||||
chainRules: chainConfig.Rules(ctx.BlockNumber),
|
||||
interpreters: make([]Interpreter, 0, 1),
|
||||
interpreters: make(map[uint64][]Interpreter),
|
||||
}
|
||||
|
||||
if chainConfig.IsEWASM(ctx.BlockNumber) {
|
||||
|
|
@ -160,8 +173,8 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
|
|||
|
||||
// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here
|
||||
// as we always want to have the built-in EVM as the failover option.
|
||||
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig))
|
||||
evm.interpreter = evm.interpreters[0]
|
||||
evm.interpreters[0] = []Interpreter{NewEVMInterpreter(evm, vmConfig)}
|
||||
evm.interpreter = evm.interpreters[0][0]
|
||||
|
||||
return evm
|
||||
}
|
||||
|
|
@ -226,7 +239,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
// 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, to, value, gas)
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr), evm.StateDB.GetCodeVersion(addr))
|
||||
|
||||
// Even if the account has no code, we need to continue because it might be a precompile
|
||||
start := time.Now()
|
||||
|
|
@ -281,7 +294,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, to, value, gas)
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr), evm.StateDB.GetCodeVersion(addr))
|
||||
|
||||
ret, err = run(evm, contract, input, false)
|
||||
if err != nil {
|
||||
|
|
@ -314,7 +327,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
|||
|
||||
// Initialise a new contract and make initialise the delegate values
|
||||
contract := NewContract(caller, to, nil, gas).AsDelegate()
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr), evm.StateDB.GetCodeVersion(addr))
|
||||
|
||||
ret, err = run(evm, contract, input, false)
|
||||
if err != nil {
|
||||
|
|
@ -346,7 +359,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, to, new(big.Int), gas)
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr), evm.StateDB.GetCodeVersion(addr))
|
||||
|
||||
// We do an AddBalance of zero here, just in order to trigger a touch.
|
||||
// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
|
||||
|
|
@ -380,7 +393,7 @@ func (c *codeAndHash) Hash() common.Hash {
|
|||
}
|
||||
|
||||
// create creates a new contract using code as deployment code.
|
||||
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
|
||||
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, version uint64) ([]byte, common.Address, uint64, error) {
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
|
|
@ -389,6 +402,12 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||
return nil, common.Address{}, gas, ErrInsufficientBalance
|
||||
}
|
||||
if !evm.ValidateCode(version, codeAndHash.code) {
|
||||
// According to EIP1702, if the validation phrase fails,
|
||||
// contract creation does not proceed, return out-of-gas
|
||||
// and consume all remaining gas.
|
||||
return nil, common.Address{}, 0, ErrOutOfGas
|
||||
}
|
||||
nonce := evm.StateDB.GetNonce(caller.Address())
|
||||
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
||||
|
||||
|
|
@ -408,7 +427,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
// 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(address), value, gas)
|
||||
contract.SetCodeOptionalHash(&address, codeAndHash)
|
||||
contract.SetCodeOptionalHash(&address, codeAndHash, version)
|
||||
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
return nil, address, gas, nil
|
||||
|
|
@ -430,7 +449,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
if err == nil && !maxCodeSizeExceeded {
|
||||
createDataGas := uint64(len(ret)) * params.CreateDataGas
|
||||
if contract.UseGas(createDataGas) {
|
||||
evm.StateDB.SetCode(address, ret)
|
||||
evm.StateDB.SetCode(address, ret, version)
|
||||
} else {
|
||||
err = ErrCodeStoreOutOfGas
|
||||
}
|
||||
|
|
@ -457,19 +476,19 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
}
|
||||
|
||||
// Create creates a new contract using code as deployment code.
|
||||
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int, version uint64) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
|
||||
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr)
|
||||
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, version)
|
||||
}
|
||||
|
||||
// Create2 creates a new contract using code as deployment code.
|
||||
//
|
||||
// The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:]
|
||||
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
|
||||
func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||
func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int, version uint64) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||
codeAndHash := &codeAndHash{code: code}
|
||||
contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes())
|
||||
return evm.create(caller, codeAndHash, gas, endowment, contractAddr)
|
||||
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, version)
|
||||
}
|
||||
|
||||
// ChainConfig returns the environment's chain configuration
|
||||
|
|
|
|||
|
|
@ -699,7 +699,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
|
|||
}
|
||||
|
||||
contract.UseGas(gas)
|
||||
res, addr, returnGas, suberr := interpreter.evm.Create(contract, input, gas, value)
|
||||
res, addr, returnGas, suberr := interpreter.evm.Create(contract, input, gas, value, contract.CodeVersion)
|
||||
// Push item on the stack based on the returned error. If the ruleset is
|
||||
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
||||
// rule) and treat as an error, if the ruleset is frontier we must
|
||||
|
|
@ -732,7 +732,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
|
|||
// Apply EIP150
|
||||
gas -= gas / 64
|
||||
contract.UseGas(gas)
|
||||
res, addr, returnGas, suberr := interpreter.evm.Create2(contract, input, gas, endowment, salt)
|
||||
res, addr, returnGas, suberr := interpreter.evm.Create2(contract, input, gas, endowment, salt, contract.CodeVersion)
|
||||
// Push item on the stack based on the returned error.
|
||||
if suberr != nil {
|
||||
stack.push(interpreter.intPool.getZero())
|
||||
|
|
|
|||
|
|
@ -36,8 +36,9 @@ type StateDB interface {
|
|||
|
||||
GetCodeHash(common.Address) common.Hash
|
||||
GetCode(common.Address) []byte
|
||||
SetCode(common.Address, []byte)
|
||||
SetCode(common.Address, []byte, uint64)
|
||||
GetCodeSize(common.Address) int
|
||||
GetCodeVersion(address common.Address) uint64
|
||||
|
||||
AddRefund(uint64)
|
||||
SubRefund(uint64)
|
||||
|
|
@ -65,16 +66,3 @@ type StateDB interface {
|
|||
|
||||
ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error
|
||||
}
|
||||
|
||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
||||
// depends on this context being implemented for doing subcalls and initialising new EVM contracts.
|
||||
type CallContext interface {
|
||||
// Call another contract
|
||||
Call(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
|
||||
// Take another's contract code and execute within our own context
|
||||
CallCode(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
|
||||
// Same as CallCode except sender and value is propagated from parent to child scope
|
||||
DelegateCall(env *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
|
||||
// Create a new contract
|
||||
Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func NewEnv(cfg *Config) *vm.EVM {
|
|||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetHash: func(uint64) common.Hash { return common.Hash{} },
|
||||
|
||||
ValidateCode: core.ValidateCode,
|
||||
Origin: cfg.Origin,
|
||||
Coinbase: cfg.Coinbase,
|
||||
BlockNumber: cfg.BlockNumber,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ type Config struct {
|
|||
GasLimit uint64
|
||||
GasPrice *big.Int
|
||||
Value *big.Int
|
||||
Version uint64
|
||||
Debug bool
|
||||
EVMConfig vm.Config
|
||||
|
||||
|
|
@ -108,7 +109,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
|||
)
|
||||
cfg.State.CreateAccount(address)
|
||||
// set the receiver's (the executing contract) code for execution.
|
||||
cfg.State.SetCode(address, code)
|
||||
cfg.State.SetCode(address, code, cfg.Version)
|
||||
// Call the code with the given configuration.
|
||||
ret, _, err := vmenv.Call(
|
||||
sender,
|
||||
|
|
@ -142,6 +143,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
|
|||
input,
|
||||
cfg.GasLimit,
|
||||
cfg.Value,
|
||||
cfg.Version,
|
||||
)
|
||||
return code, address, leftOverGas, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ func TestCall(t *testing.T) {
|
|||
byte(vm.PUSH1), 32,
|
||||
byte(vm.PUSH1), 0,
|
||||
byte(vm.RETURN),
|
||||
})
|
||||
}, 0)
|
||||
|
||||
ret, _, err := Call(address, nil, &Config{State: state})
|
||||
if err != nil {
|
||||
|
|
@ -157,7 +157,7 @@ func benchmarkEVM_Create(bench *testing.B, code string) {
|
|||
)
|
||||
|
||||
statedb.CreateAccount(sender)
|
||||
statedb.SetCode(receiver, common.FromHex(code))
|
||||
statedb.SetCode(receiver, common.FromHex(code), 0)
|
||||
runtimeConfig := Config{
|
||||
Origin: sender,
|
||||
State: statedb,
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ func TestPrestateTracerCreate2(t *testing.T) {
|
|||
context := vm.Context{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
ValidateCode: core.ValidateCode,
|
||||
Origin: origin,
|
||||
Coinbase: common.Address{},
|
||||
BlockNumber: new(big.Int).SetUint64(8000000),
|
||||
|
|
@ -234,6 +235,7 @@ func TestCallTracer(t *testing.T) {
|
|||
context := vm.Context{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
ValidateCode: core.ValidateCode,
|
||||
Origin: origin,
|
||||
Coinbase: test.Context.Miner,
|
||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ var (
|
|||
HomesteadBlock: big.NewInt(1150000),
|
||||
DAOForkBlock: big.NewInt(1920000),
|
||||
DAOForkSupport: true,
|
||||
LatestCodeVersion: 0,
|
||||
EIP150Block: big.NewInt(2463000),
|
||||
EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
|
||||
EIP155Block: big.NewInt(2675000),
|
||||
|
|
@ -96,6 +97,7 @@ var (
|
|||
HomesteadBlock: big.NewInt(0),
|
||||
DAOForkBlock: nil,
|
||||
DAOForkSupport: true,
|
||||
LatestCodeVersion: 0,
|
||||
EIP150Block: big.NewInt(0),
|
||||
EIP150Hash: common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"),
|
||||
EIP155Block: big.NewInt(10),
|
||||
|
|
@ -134,6 +136,7 @@ var (
|
|||
HomesteadBlock: big.NewInt(1),
|
||||
DAOForkBlock: nil,
|
||||
DAOForkSupport: true,
|
||||
LatestCodeVersion: 0,
|
||||
EIP150Block: big.NewInt(2),
|
||||
EIP150Hash: common.HexToHash("0x9b095b36c15eaf13044373aef8ee0bd3a382a5abb92e402afa44b8249c3a90e9"),
|
||||
EIP155Block: big.NewInt(3),
|
||||
|
|
@ -174,6 +177,7 @@ var (
|
|||
HomesteadBlock: big.NewInt(0),
|
||||
DAOForkBlock: nil,
|
||||
DAOForkSupport: true,
|
||||
LatestCodeVersion: 0,
|
||||
EIP150Block: big.NewInt(0),
|
||||
EIP155Block: big.NewInt(0),
|
||||
EIP158Block: big.NewInt(0),
|
||||
|
|
@ -213,16 +217,16 @@ var (
|
|||
//
|
||||
// This configuration is intentionally not using keyed fields to force anyone
|
||||
// adding flags to the config to also have to set these fields.
|
||||
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
|
||||
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, 0, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
|
||||
|
||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||
// and accepted by the Ethereum core developers into the Clique consensus.
|
||||
//
|
||||
// This configuration is intentionally not using keyed fields to force anyone
|
||||
// adding flags to the config to also have to set these fields.
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, 0, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
|
||||
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, 0, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||
)
|
||||
|
||||
|
|
@ -281,6 +285,9 @@ type ChainConfig struct {
|
|||
DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork)
|
||||
DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
|
||||
|
||||
// EIP1702 introduces the code version change (https://eips.ethereum.org/EIPS/eip-1702)
|
||||
LatestCodeVersion uint64 `json:"latestCodeVersion,omitempty"` // The latest account code version indicator, 0 as default.
|
||||
|
||||
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
||||
EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
|
||||
EIP150Hash common.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
||||
|
|
@ -293,7 +300,6 @@ type ChainConfig struct {
|
|||
PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople)
|
||||
IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul)
|
||||
EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated)
|
||||
|
||||
// Various consensus engines
|
||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
|
|||
sdb := state.NewDatabase(db)
|
||||
statedb, _ := state.New(common.Hash{}, sdb)
|
||||
for addr, a := range accounts {
|
||||
statedb.SetCode(addr, a.Code)
|
||||
statedb.SetCode(addr, a.Code, 0) // Default code version is 0.
|
||||
statedb.SetNonce(addr, a.Nonce)
|
||||
statedb.SetBalance(addr, a.Balance)
|
||||
for k, v := range a.Storage {
|
||||
|
|
|
|||
Loading…
Reference in a new issue