mirror of
https://github.com/luxfi/coreth.git
synced 2026-10-30 17:00:51 +00:00
286 lines
9.7 KiB
Go
286 lines
9.7 KiB
Go
//go:build skip
|
|
// +build skip
|
|
|
|
// TODO: Update tests for new geth API changes
|
|
|
|
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
//
|
|
// This file is a derived work, based on the go-ethereum library whose original
|
|
// notices appear below.
|
|
//
|
|
// It is distributed under a license compatible with the licensing terms of the
|
|
// original code from which it is derived.
|
|
//
|
|
// Much love to the original authors for their work.
|
|
// **********
|
|
// Copyright 2020 The go-ethereum Authors
|
|
// This file is part of the go-ethereum library.
|
|
//
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package core
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"math/big"
|
|
"testing"
|
|
|
|
"github.com/luxfi/coreth/consensus/dummy"
|
|
"github.com/luxfi/coreth/nativeasset"
|
|
"github.com/luxfi/coreth/params"
|
|
"github.com/luxfi/coreth/plugin/evm/upgrade/genesisparams"
|
|
"github.com/luxfi/coreth/plugin/evm/upgrade/gaslimit_initial"
|
|
"github.com/luxfi/crypto"
|
|
"github.com/luxfi/geth/common"
|
|
"github.com/luxfi/geth/core/rawdb"
|
|
"github.com/luxfi/geth/core/state"
|
|
"github.com/luxfi/geth/core/types"
|
|
"github.com/luxfi/geth/core/vm"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var (
|
|
signer = types.LatestSigner(params.TestChainConfig)
|
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
|
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
|
|
)
|
|
|
|
func makeContractTx(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction {
|
|
tx, _ := types.SignTx(types.NewContractCreation(nonce, amount, gasLimit, gasPrice, data), signer, testKey)
|
|
return tx
|
|
}
|
|
|
|
func makeTx(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction {
|
|
tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, testKey)
|
|
return tx
|
|
}
|
|
|
|
/*
|
|
//SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.0;
|
|
|
|
// FromWithinContract creates a contract with a single fallback function that invokes Native Asset Call
|
|
// so that a transaction does not need to specify any input data to hit the call.
|
|
contract FromWithinContract {
|
|
fallback() external {
|
|
address precompile = 0x0100000000000000000000000000000000000002;
|
|
precompile.call(abi.encodePacked());
|
|
}
|
|
}
|
|
|
|
|
|
// FromWithinContractConstructor creates a contract that hits Native Asset Call within the contract constructor.
|
|
contract FromWithinContractConstructor {
|
|
constructor () {
|
|
address precompile = 0x0100000000000000000000000000000000000002;
|
|
precompile.call(abi.encodePacked());
|
|
}
|
|
}
|
|
*/
|
|
|
|
type stateTransitionTest struct {
|
|
config *params.ChainConfig
|
|
txs []*types.Transaction
|
|
gasUsed []uint64
|
|
want string
|
|
}
|
|
|
|
func executeStateTransitionTest(t *testing.T, st stateTransitionTest) {
|
|
require := require.New(t)
|
|
|
|
require.Equal(len(st.txs), len(st.gasUsed), "length of gas used must match length of txs")
|
|
|
|
var (
|
|
db = rawdb.NewMemoryDatabase()
|
|
gspec = &Genesis{
|
|
Config: st.config,
|
|
Alloc: types.GenesisAlloc{
|
|
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{
|
|
Balance: big.NewInt(2000000000000000000), // 2 ether
|
|
Nonce: 0,
|
|
},
|
|
},
|
|
GasLimit: gaslimit_initial.GasLimit,
|
|
}
|
|
genesis = gspec.ToBlock()
|
|
engine = dummy.NewFaker()
|
|
blockchain, _ = NewBlockChain(db, DefaultCacheConfig, gspec, engine, vm.Config{}, common.Hash{}, false)
|
|
)
|
|
defer blockchain.Stop()
|
|
|
|
statedb, err := state.New(genesis.Root(), blockchain.stateCache, blockchain.snaps)
|
|
require.NoError(err)
|
|
|
|
block := GenerateBadBlock(genesis, engine, st.txs, blockchain.chainConfig)
|
|
receipts, _, _, err := blockchain.processor.Process(block, genesis.Header(), statedb, blockchain.vmConfig)
|
|
|
|
if st.want == "" {
|
|
// If no error is expected, require no error and verify the correct gas used amounts from the receipts
|
|
require.NoError(err)
|
|
|
|
for i, gasUsed := range st.gasUsed {
|
|
require.Equal(gasUsed, receipts[i].GasUsed, "expected gas used to match for index %d", i)
|
|
}
|
|
} else {
|
|
require.ErrorContains(err, st.want)
|
|
}
|
|
}
|
|
|
|
func TestNativeAssetContractCall(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
data, err := hex.DecodeString("608060405234801561001057600080fd5b5061016e806100206000396000f3fe608060405234801561001057600080fd5b50600073010000000000000000000000000000000000000290508073ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040516100639190610121565b6000604051808303816000865af19150503d80600081146100a0576040519150601f19603f3d011682016040523d82523d6000602084013e6100a5565b606091505b005b600081519050919050565b600081905092915050565b60005b838110156100db5780820151818401526020810190506100c0565b838111156100ea576000848401525b50505050565b60006100fb826100a7565b61010581856100b2565b93506101158185602086016100bd565b80840191505092915050565b600061012d82846100f0565b91508190509291505056fea2646970667358221220a297c3e133143287abef22b1c1d4e45f588efc3db99a84b364560a2079876fc364736f6c634300080d0033")
|
|
require.NoError(err)
|
|
|
|
contractAddr := crypto.CreateAddress(testAddr, 0)
|
|
txs := []*types.Transaction{
|
|
makeContractTx(0, common.Big0, 500_000, big.NewInt(genesisparams.MinGasPrice), data),
|
|
makeTx(1, contractAddr, common.Big0, 100_000, big.NewInt(genesisparams.MinGasPrice), nil), // No input data is necessary, since this will hit the contract's fallback function.
|
|
}
|
|
|
|
tests := map[string]stateTransitionTest{
|
|
"phase5": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{132091, 41618},
|
|
want: "",
|
|
},
|
|
"prePhase6": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{132091, 21618},
|
|
want: "",
|
|
},
|
|
"phase6": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{132091, 41618},
|
|
want: "",
|
|
},
|
|
"banff": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{132091, 21618},
|
|
want: "",
|
|
},
|
|
"durango": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{132117, 21618},
|
|
want: "",
|
|
},
|
|
"etna": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{132117, 21618},
|
|
want: "",
|
|
},
|
|
}
|
|
|
|
for name, stTest := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
executeStateTransitionTest(t, stTest)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNativeAssetContractConstructor(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
data, err := hex.DecodeString("608060405234801561001057600080fd5b50600073010000000000000000000000000000000000000290508073ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040516100639190610128565b6000604051808303816000865af19150503d80600081146100a0576040519150601f19603f3d011682016040523d82523d6000602084013e6100a5565b606091505b5050505061013f565b600081519050919050565b600081905092915050565b60005b838110156100e25780820151818401526020810190506100c7565b838111156100f1576000848401525b50505050565b6000610102826100ae565b61010c81856100b9565b935061011c8185602086016100c4565b80840191505092915050565b600061013482846100f7565b915081905092915050565b603f8061014d6000396000f3fe6080604052600080fdfea26469706673582212208a8a2e0bb031a4d5bdfa861a6e43ae57e6f4e0cc40d069ad6f52585406790ac864736f6c634300080d0033")
|
|
require.NoError(err)
|
|
|
|
txs := []*types.Transaction{
|
|
makeContractTx(0, common.Big0, 100_000, big.NewInt(genesisparams.MinGasPrice), data),
|
|
}
|
|
|
|
phase6Tests := map[string]stateTransitionTest{
|
|
"phase5": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{92046},
|
|
want: "",
|
|
},
|
|
"prePhase6": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{72046},
|
|
want: "",
|
|
},
|
|
"phase6": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{92046},
|
|
want: "",
|
|
},
|
|
"banff": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{72046},
|
|
want: "",
|
|
},
|
|
}
|
|
|
|
for name, stTest := range phase6Tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
executeStateTransitionTest(t, stTest)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNativeAssetDirectEOACall(t *testing.T) {
|
|
txs := []*types.Transaction{
|
|
makeTx(0, nativeasset.NativeAssetCallAddr, common.Big0, 100_000, big.NewInt(genesisparams.MinGasPrice), nil),
|
|
}
|
|
|
|
phase6Tests := map[string]stateTransitionTest{
|
|
"phase5": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{41000},
|
|
want: "",
|
|
},
|
|
// Note: PrePhase6 used a soft error to ensure the Native Asset Call precompile was not used from an EOA, however,
|
|
// after PrePhase6 was over, this soft error was no longer needed since it would never be included in the chain, so
|
|
// it has been removed.
|
|
// Therefore, there is no need for an error to be returned in this test case even though a soft error would have been
|
|
// returned during PrePhase6.
|
|
"prePhase6": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{21000},
|
|
want: "",
|
|
},
|
|
"phase6": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{41000},
|
|
want: "",
|
|
},
|
|
"banff": {
|
|
config: params.TestChainConfig,
|
|
txs: txs,
|
|
gasUsed: []uint64{21000},
|
|
want: "",
|
|
},
|
|
}
|
|
|
|
for name, stTest := range phase6Tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
executeStateTransitionTest(t, stTest)
|
|
})
|
|
}
|
|
}
|