Support genesis constructors for Chiado (#6103)

This is a continuation of PR #6058 and fixes Chiado genesis state root
by supporting genesis constructors (deployment code).
This commit is contained in:
Andrew Ashikhmin 2022-11-21 17:21:59 +01:00 committed by GitHub
parent c582f750be
commit 0b28c7ad13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 370 additions and 246 deletions

View File

@ -248,7 +248,7 @@ func runCmd(ctx *cli.Context) error {
if chainConfig != nil {
runtimeConfig.ChainConfig = chainConfig
} else {
runtimeConfig.ChainConfig = params.AllEthashProtocolChanges
runtimeConfig.ChainConfig = params.AllProtocolChanges
}
var hexInput []byte

View File

@ -272,7 +272,7 @@ func initialState1() error {
address2 = crypto.PubkeyToAddress(key2.PublicKey)
theAddr = common.Address{1}
gspec = &core.Genesis{
Config: params.AllEthashProtocolChanges,
Config: params.AllProtocolChanges,
Alloc: core.GenesisAlloc{
address: {Balance: big.NewInt(9000000000000000000)},
address1: {Balance: big.NewInt(200000000000000000)},
@ -281,7 +281,7 @@ func initialState1() error {
GasLimit: 10000000,
}
// this code generates a log
signer = types.MakeSigner(params.AllEthashProtocolChanges, 1)
signer = types.MakeSigner(params.AllProtocolChanges, 1)
)
m := stages.MockWithGenesis(nil, gspec, key, false)
defer m.DB.Close()

File diff suppressed because one or more lines are too long

View File

@ -507,11 +507,36 @@ func SysCallContract(contract common.Address, data []byte, chainConfig params.Ch
return ret, err
}
// from the null sender, with 50M gas.
func SysCallContractTx(contract common.Address, data []byte) (tx types.Transaction, err error) {
//nonce := ibs.GetNonce(SystemAddress)
tx = types.NewTransaction(0, contract, u256.Num0, 50_000_000, u256.Num0, data)
return tx.FakeSign(state.SystemAddress)
// SysCreate is a special (system) contract creation methods for genesis constructors.
func SysCreate(contract common.Address, data []byte, chainConfig params.ChainConfig, ibs *state.IntraBlockState, header *types.Header) (result []byte, err error) {
if chainConfig.DAOForkSupport && chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(header.Number) == 0 {
misc.ApplyDAOHardFork(ibs)
}
msg := types.NewMessage(
contract,
nil, // to
0, u256.Num0,
math.MaxUint64, u256.Num0,
nil, nil,
data, nil, false,
true, // isFree
)
vmConfig := vm.Config{NoReceipts: true}
// Create a new context to be used in the EVM environment
author := &contract
txContext := NewEVMTxContext(msg)
blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), nil, author)
evm := vm.NewEVM(blockContext, txContext, ibs, &chainConfig, vmConfig)
ret, _, err := evm.SysCreate(
vm.AccountRef(msg.From()),
msg.Data(),
msg.Gas(),
msg.Value(),
contract,
)
return ret, err
}
func CallContract(contract common.Address, data []byte, chainConfig params.ChainConfig, ibs *state.IntraBlockState, header *types.Header, engine consensus.Engine) (result []byte, err error) {

View File

@ -17,13 +17,15 @@ var _ = (*genesisAccountMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (g GenesisAccount) MarshalJSON() ([]byte, error) {
type GenesisAccount struct {
Code hexutil.Bytes `json:"code,omitempty"`
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
Nonce math.HexOrDecimal64 `json:"nonce,omitempty"`
PrivateKey hexutil.Bytes `json:"secretKey,omitempty"`
Constructor hexutil.Bytes `json:"constructor,omitempty"`
Code hexutil.Bytes `json:"code,omitempty"`
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
Nonce math.HexOrDecimal64 `json:"nonce,omitempty"`
PrivateKey hexutil.Bytes `json:"secretKey,omitempty"`
}
var enc GenesisAccount
enc.Constructor = g.Constructor
enc.Code = g.Code
if g.Storage != nil {
enc.Storage = make(map[storageJSON]storageJSON, len(g.Storage))
@ -40,16 +42,20 @@ func (g GenesisAccount) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (g *GenesisAccount) UnmarshalJSON(input []byte) error {
type GenesisAccount struct {
Code *hexutil.Bytes `json:"code,omitempty"`
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"`
PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"`
Constructor *hexutil.Bytes `json:"constructor,omitempty"`
Code *hexutil.Bytes `json:"code,omitempty"`
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"`
PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"`
}
var dec GenesisAccount
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Constructor != nil {
g.Constructor = *dec.Constructor
}
if dec.Code != nil {
g.Code = *dec.Code
}

View File

@ -32,6 +32,9 @@ import (
"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/mdbx"
"github.com/ledgerwatch/log/v3"
"golang.org/x/exp/slices"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/common/hexutil"
"github.com/ledgerwatch/erigon/common/math"
@ -44,7 +47,6 @@ import (
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/params/networkname"
"github.com/ledgerwatch/erigon/turbo/trie"
"github.com/ledgerwatch/log/v3"
)
//go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
@ -101,12 +103,14 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
}
// GenesisAccount is an account in the state of the genesis block.
// Either use "constructor" for deployment code or "code" directly for the final code.
type GenesisAccount struct {
Code []byte `json:"code,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
Balance *big.Int `json:"balance" gencodec:"required"`
Nonce uint64 `json:"nonce,omitempty"`
PrivateKey []byte `json:"secretKey,omitempty"` // for tests
Constructor []byte `json:"constructor,omitempty"` // deployment code
Code []byte `json:"code,omitempty"` // final contract code
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
Balance *big.Int `json:"balance" gencodec:"required"`
Nonce uint64 `json:"nonce,omitempty"`
PrivateKey []byte `json:"secretKey,omitempty"` // for tests
}
// field type overrides for gencodec
@ -123,11 +127,12 @@ type genesisSpecMarshaling struct {
}
type genesisAccountMarshaling struct {
Code hexutil.Bytes
Balance *math.HexOrDecimal256
Nonce math.HexOrDecimal64
Storage map[storageJSON]storageJSON
PrivateKey hexutil.Bytes
Constructor hexutil.Bytes
Code hexutil.Bytes
Balance *math.HexOrDecimal256
Nonce math.HexOrDecimal64
Storage map[storageJSON]storageJSON
PrivateKey hexutil.Bytes
}
// storageJSON represents a 256 bit byte array, but allows less than 256 bits when
@ -208,7 +213,7 @@ func MustCommitGenesisBlock(db kv.RwDB, genesis *Genesis) (*params.ChainConfig,
func WriteGenesisBlock(db kv.RwTx, genesis *Genesis, overrideMergeNetsplitBlock, overrideTerminalTotalDifficulty *big.Int) (*params.ChainConfig, *types.Block, error) {
if genesis != nil && genesis.Config == nil {
return params.AllEthashProtocolChanges, nil, ErrGenesisNoConfig
return params.AllProtocolChanges, nil, ErrGenesisNoConfig
}
// Just commit the new block if there is no stored genesis block.
storedHash, storedErr := rawdb.ReadCanonicalHash(db, 0)
@ -307,56 +312,25 @@ func (g *Genesis) configOrDefault(genesisHash common.Hash) *params.ChainConfig {
if config != nil {
return config
} else {
return params.AllEthashProtocolChanges
return params.AllProtocolChanges
}
}
func sortedAllocKeys(m GenesisAlloc) []string {
keys := make([]string, len(m))
i := 0
for k := range m {
keys[i] = string(k.Bytes())
i++
}
slices.Sort(keys)
return keys
}
// ToBlock creates the genesis block and writes state of a genesis specification
// to the given database (or discards it if nil).
func (g *Genesis) ToBlock() (*types.Block, *state.IntraBlockState, error) {
_ = g.Alloc //nil-check
var root common.Hash
var statedb *state.IntraBlockState
wg := sync.WaitGroup{}
wg.Add(1)
go func() { // we may run inside write tx, can't open 2nd write tx in same goroutine
defer wg.Done()
tmpDB := mdbx.NewMDBX(log.New()).InMem("").MapSize(2 * datasize.GB).MustOpen()
defer tmpDB.Close()
tx, err := tmpDB.BeginRw(context.Background())
if err != nil {
panic(err)
}
defer tx.Rollback()
r, w := state.NewDbStateReader(tx), state.NewDbStateWriter(tx, 0)
statedb = state.New(r)
for addr, account := range g.Alloc {
balance, overflow := uint256.FromBig(account.Balance)
if overflow {
panic("overflow at genesis allocs")
}
statedb.AddBalance(addr, balance)
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage {
key := key
val := uint256.NewInt(0).SetBytes(value.Bytes())
statedb.SetState(addr, &key, *val)
}
if len(account.Code) > 0 || len(account.Storage) > 0 {
statedb.SetIncarnation(addr, state.FirstContractIncarnation)
}
}
if err := statedb.FinalizeTx(&params.Rules{}, w); err != nil {
panic(err)
}
root, err = trie.CalcRoot("genesis", tx)
if err != nil {
panic(err)
}
}()
wg.Wait()
head := &types.Header{
Number: new(big.Int).SetUint64(g.Number),
@ -369,7 +343,6 @@ func (g *Genesis) ToBlock() (*types.Block, *state.IntraBlockState, error) {
Difficulty: g.Difficulty,
MixDigest: g.Mixhash,
Coinbase: g.Coinbase,
Root: root,
BaseFee: g.BaseFee,
AuRaStep: g.AuRaStep,
AuRaSeal: g.AuRaSeal,
@ -388,6 +361,76 @@ func (g *Genesis) ToBlock() (*types.Block, *state.IntraBlockState, error) {
}
}
var root common.Hash
var statedb *state.IntraBlockState
wg := sync.WaitGroup{}
wg.Add(1)
go func() { // we may run inside write tx, can't open 2nd write tx in same goroutine
// TODO(yperbasis): use memdb.MemoryMutation instead
defer wg.Done()
tmpDB := mdbx.NewMDBX(log.New()).InMem("").MapSize(2 * datasize.GB).MustOpen()
defer tmpDB.Close()
tx, err := tmpDB.BeginRw(context.Background())
if err != nil {
panic(err)
}
defer tx.Rollback()
r, w := state.NewDbStateReader(tx), state.NewDbStateWriter(tx, 0)
statedb = state.New(r)
hasConstructorAllocation := false
for _, account := range g.Alloc {
if len(account.Constructor) > 0 {
hasConstructorAllocation = true
break
}
}
// See https://github.com/NethermindEth/nethermind/blob/master/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/LoadGenesisBlockAuRa.cs
if hasConstructorAllocation && g.Config.Aura != nil {
statedb.CreateAccount(common.Address{}, false)
}
keys := sortedAllocKeys(g.Alloc)
for _, key := range keys {
addr := common.BytesToAddress([]byte(key))
account := g.Alloc[addr]
balance, overflow := uint256.FromBig(account.Balance)
if overflow {
panic("overflow at genesis allocs")
}
statedb.AddBalance(addr, balance)
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage {
key := key
val := uint256.NewInt(0).SetBytes(value.Bytes())
statedb.SetState(addr, &key, *val)
}
if len(account.Constructor) > 0 {
_, err := SysCreate(addr, account.Constructor, *g.Config, statedb, head)
if err != nil {
panic(err)
}
}
if len(account.Code) > 0 || len(account.Storage) > 0 || len(account.Constructor) > 0 {
statedb.SetIncarnation(addr, state.FirstContractIncarnation)
}
}
if err := statedb.FinalizeTx(&params.Rules{}, w); err != nil {
panic(err)
}
root, err = trie.CalcRoot("genesis", tx)
if err != nil {
panic(err)
}
}()
wg.Wait()
head.Root = root
return types.NewBlock(head, nil, nil, nil), statedb, nil
}
@ -442,7 +485,7 @@ func (g *Genesis) Write(tx kv.RwTx) (*types.Block, *state.IntraBlockState, error
}
config := g.Config
if config == nil {
config = params.AllEthashProtocolChanges
config = params.AllProtocolChanges
}
if err := config.CheckConfigForkOrder(); err != nil {
return nil, nil, err

View File

@ -2,16 +2,24 @@ package core
import (
"context"
"math/big"
"testing"
"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/params/networkname"
"github.com/stretchr/testify/require"
"github.com/ledgerwatch/erigon/rlp"
)
func TestDefaultBSCGenesisBlock(t *testing.T) {
func TestDefaultGenesisBlockHashes(t *testing.T) {
db := memdb.NewTestDB(t)
check := func(network string) {
genesis := DefaultGenesisBlockByChainName(network)
@ -27,14 +35,61 @@ func TestDefaultBSCGenesisBlock(t *testing.T) {
require.Equal(t, block.Hash().Bytes(), expect.Bytes(), network)
}
for _, network := range networkname.All {
if network == networkname.ChiadoChainName {
continue
}
check(network)
}
}
func TestDefaultGenesisBlockRoots(t *testing.T) {
require := require.New(t)
var err error
block, _, _ := DefaultGenesisBlock().ToBlock()
if block.Hash() != params.MainnetGenesisHash {
t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash(), params.MainnetGenesisHash)
}
block, _, err = DefaultRopstenGenesisBlock().ToBlock()
require.NoError(err)
if block.Hash() != params.RopstenGenesisHash {
t.Errorf("wrong Ropsten genesis hash, got %v, want %v", block.Hash(), params.RopstenGenesisHash)
}
block, _, err = DefaultSokolGenesisBlock().ToBlock()
require.NoError(err)
if block.Root() != params.SokolGenesisStateRoot {
t.Errorf("wrong Sokol genesis state root, got %v, want %v", block.Root(), params.SokolGenesisStateRoot)
}
if block.Hash() != params.SokolGenesisHash {
t.Errorf("wrong Sokol genesis hash, got %v, want %v", block.Hash(), params.SokolGenesisHash)
}
block, _, err = DefaultFermionGenesisBlock().ToBlock()
require.NoError(err)
if block.Root() != params.FermionGenesisStateRoot {
t.Errorf("wrong Fermion genesis state root, got %v, want %v", block.Root(), params.FermionGenesisStateRoot)
}
if block.Hash() != params.FermionGenesisHash {
t.Errorf("wrong Fermion genesis hash, got %v, want %v", block.Hash(), params.FermionGenesisHash)
}
block, _, err = DefaultGnosisGenesisBlock().ToBlock()
require.NoError(err)
if block.Root() != params.GnosisGenesisStateRoot {
t.Errorf("wrong Gnosis Chain genesis state root, got %v, want %v", block.Root(), params.GnosisGenesisStateRoot)
}
if block.Hash() != params.GnosisGenesisHash {
t.Errorf("wrong Gnosis Chain genesis hash, got %v, want %v", block.Hash(), params.GnosisGenesisHash)
}
block, _, err = DefaultChiadoGenesisBlock().ToBlock()
require.NoError(err)
if block.Root() != params.ChiadoGenesisStateRoot {
t.Errorf("wrong Chiado genesis state root, got %v, want %v", block.Root(), params.ChiadoGenesisStateRoot)
}
if block.Hash() != params.ChiadoGenesisHash {
t.Errorf("wrong Chiado genesis hash, got %v, want %v", block.Hash(), params.ChiadoGenesisHash)
}
}
func TestCommitGenesisIdempotency(t *testing.T) {
_, tx := memdb.NewTestTx(t)
genesis := DefaultGenesisBlockByChainName(networkname.MainnetChainName)
@ -50,3 +105,93 @@ func TestCommitGenesisIdempotency(t *testing.T) {
require.NoError(t, err)
require.Equal(t, uint64(2), seq)
}
func TestSokolHeaderRLP(t *testing.T) {
require := require.New(t)
{ //sokol
expect := common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
block, _, err := DefaultSokolGenesisBlock().ToBlock()
require.NoError(err)
b, err := rlp.EncodeToBytes(block.Header())
require.NoError(err)
require.Equal(expect, b)
h := &types.Header{}
err = rlp.DecodeBytes(expect, h)
require.NoError(err)
expectSeal := common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
require.Equal(uint64(0), h.AuRaStep)
require.Equal(expectSeal, h.AuRaSeal)
enc, err := rlp.EncodeToBytes(h)
require.NoError(err)
require.Equal(expect, enc)
}
{ // sokol, more seals
h := &types.Header{}
enc := common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808002b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001")
err := rlp.DecodeBytes(enc, h)
require.NoError(err)
require.Equal(uint64(2), h.AuRaStep)
expectSeal := common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001")
require.Equal(expectSeal, h.AuRaSeal)
res, err := rlp.EncodeToBytes(h) // after encode getting source bytes
require.NoError(err)
require.Equal(enc, res)
}
{ // ethash
expect := common.FromHex("f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23")
h := &types.Header{}
err := rlp.DecodeBytes(expect, h)
require.NoError(err)
res, err := rlp.EncodeToBytes(h) // after encode getting source bytes
require.NoError(err)
require.Equal(expect, res)
}
}
func TestAllocConstructor(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
// This deployment code initially sets contract's 0th storage to 0x2a
// and its 1st storage to 0x01c9.
deploymentCode := common.FromHex("602a5f556101c960015560048060135f395ff35f355f55")
funds := big.NewInt(1000000000)
address := common.HexToAddress("0x1000000000000000000000000000000000000001")
genSpec := &Genesis{
Config: params.AllProtocolChanges,
Alloc: GenesisAlloc{
address: {Constructor: deploymentCode, Balance: funds},
},
}
db := memdb.NewTestDB(t)
defer db.Close()
_, _, err := CommitGenesisBlock(db, genSpec)
require.NoError(err)
tx, err := db.BeginRo(context.Background())
require.NoError(err)
defer tx.Rollback()
state := state.New(state.NewPlainState(tx, 1))
balance := state.GetBalance(address)
assert.Equal(funds, balance.ToBig())
code := state.GetCode(address)
assert.Equal(common.FromHex("5f355f55"), code)
key0 := common.HexToHash("0000000000000000000000000000000000000000000000000000000000000000")
storage0 := &uint256.Int{}
state.GetState(address, &key0, storage0)
assert.Equal(uint256.NewInt(0x2a), storage0)
key1 := common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001")
storage1 := &uint256.Int{}
state.GetState(address, &key1, storage1)
assert.Equal(uint256.NewInt(0x01c9), storage1)
}

View File

@ -16,7 +16,7 @@ import (
)
var (
chainConfig = params.AllEthashProtocolChanges
chainConfig = params.AllProtocolChanges
address = common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b")
)

View File

@ -325,7 +325,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 *uint256.Int, address common.Address, calltype CallType) ([]byte, common.Address, uint64, error) {
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, calltype CallType, incrementNonce bool) ([]byte, common.Address, uint64, error) {
var ret []byte
var err error
// Depth check execution. Fail if we're trying to execute above the
@ -342,11 +342,13 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
evm.config.Tracer.CaptureEnd(evm.depth, ret, startGas, gas, time.Since(startTime), err)
}(gas, time.Now())
}
nonce := evm.intraBlockState.GetNonce(caller.Address())
if nonce+1 < nonce {
return nil, common.Address{}, gas, ErrNonceUintOverflow
if incrementNonce {
nonce := evm.intraBlockState.GetNonce(caller.Address())
if nonce+1 < nonce {
return nil, common.Address{}, gas, ErrNonceUintOverflow
}
evm.intraBlockState.SetNonce(caller.Address(), nonce+1)
}
evm.intraBlockState.SetNonce(caller.Address(), nonce+1)
// We add this to the access list _before_ taking a snapshot. Even if the creation fails,
// the access-list change should not be rolled back
if evm.chainRules.IsBerlin {
@ -424,9 +426,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// Create creates a new contract using code as deployment code.
// DESCRIBED: docs/programmers_guide/guide.md#nonce
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
contractAddr = crypto.CreateAddress(caller.Address(), evm.intraBlockState.GetNonce(caller.Address()))
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATET)
return evm.create(caller, &codeAndHash{code: code}, gas, endowment, contractAddr, CREATET, true /* incrementNonce */)
}
// Create2 creates a new contract using code as deployment code.
@ -437,7 +439,14 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint2
func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
codeAndHash := &codeAndHash{code: code}
contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2T)
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2T, true /* incrementNonce */)
}
// SysCreate is a special (system) contract creation methods for genesis constructors.
// Unlike the normal Create & Create2, it doesn't increment caller's nonce.
func (evm *EVM) SysCreate(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, contractAddr common.Address) (ret []byte, leftOverGas uint64, err error) {
ret, _, leftOverGas, err = evm.create(caller, &codeAndHash{code: code}, gas, endowment, contractAddr, CREATET, false /* incrementNonce */)
return
}
// ChainConfig returns the environment's chain configuration

View File

@ -94,12 +94,12 @@ func TestEIP2200(t *testing.T) {
s.SetCode(address, hexutil.MustDecode(tt.input))
s.SetState(address, &common.Hash{}, *uint256.NewInt(uint64(tt.original)))
_ = s.CommitBlock(params.AllEthashProtocolChanges.Rules(0), state.NewPlainStateWriter(tx, tx, 0))
_ = s.CommitBlock(params.AllProtocolChanges.Rules(0), state.NewPlainStateWriter(tx, tx, 0))
vmctx := BlockContext{
CanTransfer: func(IntraBlockState, common.Address, *uint256.Int) bool { return true },
Transfer: func(IntraBlockState, common.Address, common.Address, *uint256.Int, bool) {},
}
vmenv := NewEVM(vmctx, TxContext{}, s, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
vmenv := NewEVM(vmctx, TxContext{}, s, params.AllProtocolChanges, Config{ExtraEips: []int{2200}})
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int), false /* bailout */)
if !errors.Is(err, tt.failure) {
@ -138,7 +138,7 @@ func TestCreateGas(t *testing.T) {
s := state.New(state.NewPlainStateReader(tx))
s.CreateAccount(address, true)
s.SetCode(address, hexutil.MustDecode(tt.code))
_ = s.CommitBlock(params.AllEthashProtocolChanges.Rules(0), state.NewPlainStateWriter(tx, tx, 0))
_ = s.CommitBlock(params.TestChainConfig.Rules(0), state.NewPlainStateWriter(tx, tx, 0))
vmctx := BlockContext{
CanTransfer: func(IntraBlockState, common.Address, *uint256.Int) bool { return true },
@ -149,7 +149,7 @@ func TestCreateGas(t *testing.T) {
config.ExtraEips = []int{3860}
}
vmenv := NewEVM(vmctx, TxContext{}, s, params.AllEthashProtocolChanges, config)
vmenv := NewEVM(vmctx, TxContext{}, s, params.TestChainConfig, config)
var startGas uint64 = math.MaxUint64
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int), false /* bailout */)

View File

@ -85,6 +85,7 @@ var (
SokolGenesisStateRoot = common.HexToHash("0xfad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3")
FermionGenesisStateRoot = common.HexToHash("0x08982dc16236c51b6d9aff8b76cd0faa7067eb55eba62395d5a82649d8fb73c4")
GnosisGenesisStateRoot = common.HexToHash("0x40cf4430ecaa733787d1a65154a3b9efb560c95d9e324a23b97f0609b539133b")
ChiadoGenesisStateRoot = common.HexToHash("0x9ec3eaf4e6188dfbdd6ade76eaa88289b57c63c9a2cde8d35291d5a29e143d31")
)
var (
@ -113,25 +114,28 @@ var (
FermionChainConfig = readChainSpec("chainspecs/fermion.json")
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Ethash consensus.
AllEthashProtocolChanges = &ChainConfig{
ChainID: big.NewInt(1337),
Consensus: EtHashConsensus,
HomesteadBlock: big.NewInt(0),
TangerineWhistleBlock: big.NewInt(0),
TangerineWhistleHash: common.Hash{},
SpuriousDragonBlock: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
Ethash: new(EthashConfig),
// AllProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the main net protocol.
AllProtocolChanges = &ChainConfig{
ChainID: big.NewInt(1337),
Consensus: EtHashConsensus,
HomesteadBlock: big.NewInt(0),
TangerineWhistleBlock: big.NewInt(0),
TangerineWhistleHash: common.Hash{},
SpuriousDragonBlock: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true,
ShanghaiBlock: big.NewInt(0),
Ethash: new(EthashConfig),
}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced

View File

@ -29,8 +29,8 @@ func TestCheckCompatible(t *testing.T) {
wantErr *ConfigCompatError
}
tests := []test{
{stored: AllEthashProtocolChanges, new: AllEthashProtocolChanges, head: 0, wantErr: nil},
{stored: AllEthashProtocolChanges, new: AllEthashProtocolChanges, head: 100, wantErr: nil},
{stored: AllProtocolChanges, new: AllProtocolChanges, head: 0, wantErr: nil},
{stored: AllProtocolChanges, new: AllProtocolChanges, head: 100, wantErr: nil},
{
stored: &ChainConfig{TangerineWhistleBlock: big.NewInt(10)},
new: &ChainConfig{TangerineWhistleBlock: big.NewInt(20)},
@ -38,7 +38,7 @@ func TestCheckCompatible(t *testing.T) {
wantErr: nil,
},
{
stored: AllEthashProtocolChanges,
stored: AllProtocolChanges,
new: &ChainConfig{HomesteadBlock: nil},
head: 3,
wantErr: &ConfigCompatError{
@ -49,7 +49,7 @@ func TestCheckCompatible(t *testing.T) {
},
},
{
stored: AllEthashProtocolChanges,
stored: AllProtocolChanges,
new: &ChainConfig{HomesteadBlock: big.NewInt(1)},
head: 3,
wantErr: &ConfigCompatError{

View File

@ -25,124 +25,16 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/core"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/crypto"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/rlp"
"github.com/ledgerwatch/erigon/turbo/stages"
"github.com/stretchr/testify/require"
)
func TestDefaultGenesisBlock(t *testing.T) {
block, _, _ := core.DefaultGenesisBlock().ToBlock()
if block.Hash() != params.MainnetGenesisHash {
t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash(), params.MainnetGenesisHash)
}
var err error
block, _, err = core.DefaultRopstenGenesisBlock().ToBlock()
if err != nil {
t.Errorf("error: %v", err)
}
if block.Hash() != params.RopstenGenesisHash {
t.Errorf("wrong ropsten genesis hash, got %v, want %v", block.Hash(), params.RopstenGenesisHash)
}
block, _, err = core.DefaultSokolGenesisBlock().ToBlock()
if err != nil {
t.Errorf("error: %v", err)
}
if block.Root() != params.SokolGenesisStateRoot {
t.Errorf("wrong sokol genesis state root, got %v, want %v", block.Root(), params.SokolGenesisStateRoot)
}
if block.Hash() != params.SokolGenesisHash {
t.Errorf("wrong sokol genesis hash, got %v, want %v", block.Hash(), params.SokolGenesisHash)
}
block, _, err = core.DefaultFermionGenesisBlock().ToBlock()
if err != nil {
t.Errorf("error: %v", err)
}
if block.Root() != params.FermionGenesisStateRoot {
t.Errorf("wrong fermion genesis state root, got %v, want %v", block.Root(), params.FermionGenesisStateRoot)
}
if block.Hash() != params.FermionGenesisHash {
t.Errorf("wrong fermion genesis hash, got %v, want %v", block.Hash(), params.FermionGenesisHash)
}
block, _, err = core.DefaultGnosisGenesisBlock().ToBlock()
if err != nil {
t.Errorf("error: %v", err)
}
if block.Root() != params.GnosisGenesisStateRoot {
t.Errorf("wrong Gnosis Chain genesis state root, got %v, want %v", block.Root(), params.GnosisGenesisStateRoot)
}
if block.Hash() != params.GnosisGenesisHash {
t.Errorf("wrong Gnosis Chain genesis hash, got %v, want %v", block.Hash(), params.GnosisGenesisHash)
}
/*
block, _, err = core.DefaultChiadoGenesisBlock().ToBlock()
if err != nil {
t.Errorf("error: %v", err)
}
if block.Hash() != params.ChiadoGenesisHash {
t.Errorf("wrong Chiado genesis hash, got %v, want %v", block.Hash(), params.ChiadoGenesisHash)
}
*/
}
func TestSokolHeaderRLP(t *testing.T) {
require := require.New(t)
{ //sokol
expect := common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
block, _, err := core.DefaultSokolGenesisBlock().ToBlock()
require.NoError(err)
b, err := rlp.EncodeToBytes(block.Header())
require.NoError(err)
require.Equal(expect, b)
h := &types.Header{}
err = rlp.DecodeBytes(expect, h)
require.NoError(err)
expectSeal := common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
require.Equal(uint64(0), h.AuRaStep)
require.Equal(expectSeal, h.AuRaSeal)
enc, err := rlp.EncodeToBytes(h)
require.NoError(err)
require.Equal(expect, enc)
}
{ // sokol, more seals
h := &types.Header{}
enc := common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808002b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001")
err := rlp.DecodeBytes(enc, h)
require.NoError(err)
require.Equal(uint64(2), h.AuRaStep)
expectSeal := common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001")
require.Equal(expectSeal, h.AuRaSeal)
res, err := rlp.EncodeToBytes(h) // after encode getting source bytes
require.NoError(err)
require.Equal(enc, res)
}
{ // ethash
expect := common.FromHex("f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23")
h := &types.Header{}
err := rlp.DecodeBytes(expect, h)
require.NoError(err)
res, err := rlp.EncodeToBytes(h) // after encode getting source bytes
require.NoError(err)
require.Equal(expect, res)
}
}
func TestSetupGenesis(t *testing.T) {
var (
customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50")
@ -168,7 +60,7 @@ func TestSetupGenesis(t *testing.T) {
return core.CommitGenesisBlock(db, new(core.Genesis))
},
wantErr: core.ErrGenesisNoConfig,
wantConfig: params.AllEthashProtocolChanges,
wantConfig: params.AllProtocolChanges,
},
{
name: "no block in DB, genesis == nil",

View File

@ -19,7 +19,7 @@ func TestInserter1(t *testing.T) {
funds := big.NewInt(1000000000)
key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address := crypto.PubkeyToAddress(key.PublicKey)
chainConfig := params.AllEthashProtocolChanges
chainConfig := params.AllProtocolChanges
gspec := &core.Genesis{
Config: chainConfig,
Alloc: core.GenesisAlloc{

View File

@ -472,7 +472,7 @@ func MockWithZeroTTD(t *testing.T, withPosDownloader bool) *MockSentry {
funds := big.NewInt(1 * params.Ether)
key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address := crypto.PubkeyToAddress(key.PublicKey)
chainConfig := params.AllEthashProtocolChanges
chainConfig := params.AllProtocolChanges
chainConfig.TerminalTotalDifficulty = common.Big0
gspec := &core.Genesis{
Config: chainConfig,