Skip to content

Commit

Permalink
Remove global variables and aggregate them in the test engine
Browse files Browse the repository at this point in the history
  • Loading branch information
Mdaiki0730 committed Jan 27, 2025
1 parent b4fc2d9 commit bd1bee7
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 72 deletions.
20 changes: 7 additions & 13 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2733,11 +2733,6 @@ func (bc *BlockChain) SaveTrieNodeCacheToDisk() error {
return nil
}

var (
GasLimitInExecutionSpecTest uint64
UseKaiaCancunExtCodeHashFee bool
)

// ApplyTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
Expand Down Expand Up @@ -2766,19 +2761,18 @@ func (bc *BlockChain) ApplyTransaction(chainConfig *params.ChainConfig, author *
// Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author)

// when execution spec test, we can insert test GasLimit to blockContext.
if GasLimitInExecutionSpecTest != 0 {
blockContext.GasLimit = GasLimitInExecutionSpecTest
}
txContext := NewEVMTxContext(msg, header, chainConfig)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(blockContext, txContext, statedb, chainConfig, vmConfig)

// when execution spec test, we can insert test GasLimit to blockContext.
if UseKaiaCancunExtCodeHashFee && chainConfig.Rules(header.Number).IsCancun {
// EIP-1052 must be activated for backward compatibility on Kaia. But EIP-2929 is activated instead of it on Ethereum
vm.ChangeGasCostForTest(&vmenv.Config.JumpTable, vm.EXTCODEHASH, params.WarmStorageReadCostEIP2929)
// change evm and msg for eest
if bc != nil {
if e, hasMethod := bc.Engine().(interface {
BeforeApplyMessage(*vm.EVM, *types.Transaction)
}); hasMethod {
e.BeforeApplyMessage(vmenv, msg)
}
}

// Apply the transaction to the current state (included in the env)
Expand Down
4 changes: 1 addition & 3 deletions blockchain/types/tx_internal_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,6 @@ func toWordSize(size uint64) uint64 {
return (size + 31) / 32
}

var IsPragueInExecutionSpecTest bool

// Klaytn-TxTypes since genesis, and EthTxTypes since istanbul use this.
func IntrinsicGasPayload(gas uint64, data []byte, isContractCreation bool, rules params.Rules) (uint64, uint64, error) {
var tokens uint64
Expand All @@ -593,7 +591,7 @@ func IntrinsicGasPayload(gas uint64, data []byte, isContractCreation bool, rules
// Since the genesis block, a flat 100 gas is paid
// regardless of whether the value is zero or non-zero.
nonZeroGas, zeroGas := params.TxDataGas, params.TxDataGas
if rules.IsPrague || IsPragueInExecutionSpecTest {
if rules.IsPrague {
nonZeroGas = params.TxDataNonZeroGasEIP2028
zeroGas = params.TxDataZeroGas
}
Expand Down
5 changes: 0 additions & 5 deletions tests/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"testing"

"github.com/kaiachain/kaia/blockchain"
"github.com/kaiachain/kaia/blockchain/types"
"github.com/kaiachain/kaia/common"
"github.com/stretchr/testify/suite"
)
Expand Down Expand Up @@ -64,17 +63,13 @@ type ExecutionSpecBlockTestSuite struct {
func (suite *ExecutionSpecBlockTestSuite) SetupSuite() {
suite.originalIsPrecompiledContractAddress = common.IsPrecompiledContractAddress
common.IsPrecompiledContractAddress = isPrecompiledContractAddressForEthTest
blockchain.UseKaiaCancunExtCodeHashFee = true
blockchain.CreateContractWithCodeFormatInExecutionSpecTest = true
}

func (suite *ExecutionSpecBlockTestSuite) TearDownSuite() {
// Reset global variables for test
common.IsPrecompiledContractAddress = suite.originalIsPrecompiledContractAddress
blockchain.UseKaiaCancunExtCodeHashFee = false
blockchain.GasLimitInExecutionSpecTest = 0
blockchain.CreateContractWithCodeFormatInExecutionSpecTest = false
types.IsPragueInExecutionSpecTest = false
}

func (suite *ExecutionSpecBlockTestSuite) TestExecutionSpecBlock() {
Expand Down
88 changes: 37 additions & 51 deletions tests/block_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,36 @@ type btHeaderMarshaling struct {

type eestEngine struct {
*gxhash.Gxhash
baseFee *big.Int
baseFee *big.Int
gasLimit uint64
}

var _ consensus.Engine = &eestEngine{}

func (e *eestEngine) BeforeApplyMessage(evm *vm.EVM, msg *types.Transaction) {
// Change GasLimit to the one in the eth header
evm.Context.GasLimit = e.gasLimit

if evm.ChainConfig().Rules(evm.Context.BlockNumber).IsCancun {
// EIP-1052 must be activated for backward compatibility on Kaia. But EIP-2929 is activated instead of it on Ethereum
vm.ChangeGasCostForTest(&evm.Config.JumpTable, vm.EXTCODEHASH, params.WarmStorageReadCostEIP2929)
}

// When istanbul is enabled, instrinsic gas is different from eth, so enable IsPrague to make them equal
r := evm.ChainConfig().Rules(evm.Context.BlockNumber)
if evm.ChainConfig().Rules(evm.Context.BlockNumber).IsIstanbul {
r.IsPrague = true
}
updatedIntrinsicGas, dataTokens, _ := types.IntrinsicGas(msg.Data(), msg.AccessList(), msg.AuthorizationList(), msg.To() == nil, r)
from, _ := msg.From()
msg = types.NewMessage(from, msg.To(), msg.Nonce(), msg.GetTxInternalData().GetAmount(), msg.Gas(), msg.GasPrice(), msg.GasFeeCap(), msg.GasTipCap(), msg.Data(), true, updatedIntrinsicGas, dataTokens, msg.AccessList(), msg.AuthorizationList())

// Gas prices are calculated in eth
if e.baseFee != nil {
evm.GasPrice = math.BigMin(new(big.Int).Add(msg.GasTipCap(), e.baseFee), msg.GasFeeCap())
}
}

func (e *eestEngine) Initialize(chain consensus.ChainReader, header *types.Header, state *state.StateDB) {
if chain.Config().IsPragueForkEnabled(header.Number) {
context := blockchain.NewEVMBlockContext(header, chain, nil)
Expand Down Expand Up @@ -151,6 +176,7 @@ func (e *eestEngine) Finalize(chain consensus.ChainReader, header *types.Header,

func (e *eestEngine) applyHeader(h TestHeader) {
e.baseFee = h.BaseFee
e.gasLimit = h.GasLimit
}

func (t *BlockTest) Run() error {
Expand Down Expand Up @@ -195,7 +221,7 @@ func (t *BlockTest) Run() error {
}
defer chain.Stop()

_, senderMap, err := t.insertBlocksFromTx(chain, *gblock, db, tracer)
_, err = t.insertBlocksFromTx(chain, *gblock, db, tracer)
if err != nil {
return err
}
Expand All @@ -204,7 +230,7 @@ func (t *BlockTest) Run() error {
if err != nil {
return err
}
if err = t.validatePostState(newDB, senderMap); err != nil {
if err = t.validatePostState(newDB); err != nil {
return fmt.Errorf("post state validation failed: %v", err)
}

Expand Down Expand Up @@ -280,9 +306,8 @@ type rewardList struct {
ethReward *big.Int
}

func (t *BlockTest) insertBlocksFromTx(bc *blockchain.BlockChain, gBlock types.Block, db database.DBManager, tracer *vm.StructLogger) ([]btBlock, map[common.Address]*big.Int, error) {
func (t *BlockTest) insertBlocksFromTx(bc *blockchain.BlockChain, gBlock types.Block, db database.DBManager, tracer *vm.StructLogger) ([]btBlock, error) {
validBlocks := make([]btBlock, 0)
senderMap := map[common.Address]*big.Int{}
preBlock := &gBlock

// insert the test blocks, which will execute all transactions
Expand All @@ -292,77 +317,42 @@ func (t *BlockTest) insertBlocksFromTx(bc *blockchain.BlockChain, gBlock types.B
if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, nil, fmt.Errorf("Block RLP decoding failed when expected to succeed: %v", err)
return nil, fmt.Errorf("Block RLP decoding failed when expected to succeed: %v", err)
}
}

if e := bc.Engine().(interface{ applyHeader(TestHeader) }); e != nil {
e.applyHeader(header)
}

// The intrinsic gas calculation affects gas used, so we need to make some changes to the main code.
if bc.Config().IsIstanbulForkEnabled(bc.CurrentHeader().Number) {
types.IsPragueInExecutionSpecTest = true
}
blockchain.GasLimitInExecutionSpecTest = header.GasLimit

// var maxFeePerGas *big.Int
blocks, receiptsList := blockchain.GenerateChain(bc.Config(), preBlock, bc.Engine(), db, 1, func(i int, b *blockchain.BlockGen) {
blocks, _ := blockchain.GenerateChain(bc.Config(), preBlock, bc.Engine(), db, 1, func(i int, b *blockchain.BlockGen) {
b.SetRewardbase(common.Address(header.Coinbase))
for _, tx := range txs {
b.AddTxWithChainEvenHasError(bc, tx)
}
})
preBlock = blocks[0]

// The reward calculation is different for kaia and eth, and this will be deducted from the state later.
for _, receipt := range receiptsList[0] {
for _, tx := range blocks[0].Body().Transactions {
if tx.Hash() != receipt.TxHash {
continue
}

// kaia gas price
var kaiaGasPrice *big.Int
if tx.Type() == types.TxTypeEthereumDynamicFee || tx.Type() == types.TxTypeEthereumSetCode {
kaiaGasPrice = tx.EffectiveGasPrice(blocks[0].Header(), bc.Config())
} else {
kaiaGasPrice = tx.GasPrice()
}

// eth gas price
ethGasPrice := tx.GasPrice()
if header.BaseFee != nil {
ethGasPrice = math.BigMin(new(big.Int).Add(tx.GasTipCap(), header.BaseFee), tx.GasFeeCap())
}

// Because it is a eth test, we don't have to think about fee payer
// Because the baseFee is set to 0, Kaia's gas fee may be 0 if the transaction has a dynamic fee.
senderMap[tx.ValidatedSender()] = new(big.Int).Sub(
new(big.Int).Mul(new(big.Int).SetUint64(receipt.GasUsed), kaiaGasPrice),
new(big.Int).Mul(new(big.Int).SetUint64(receipt.GasUsed), ethGasPrice))
}
}

if header.GasUsed != blocks[0].GasUsed() {
return nil, nil, fmt.Errorf("Unexpected GasUsed error (Expected: %v, Actual: %v)", header.GasUsed, blocks[0].GasUsed())
return nil, fmt.Errorf("Unexpected GasUsed error (Expected: %v, Actual: %v)", header.GasUsed, blocks[0].GasUsed())
}

i, err := bc.InsertChain(blocks)
if err != nil {
if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, nil, fmt.Errorf("Block #%v insertion into chain failed: %v", blocks[i].Number(), err)
return nil, fmt.Errorf("Block #%v insertion into chain failed: %v", blocks[i].Number(), err)
}
}
if b.BlockHeader == nil {
return nil, nil, errors.New("Block insertion should have failed")
return nil, errors.New("Block insertion should have failed")
}

validBlocks = append(validBlocks, b)
}
return validBlocks, senderMap, nil
return validBlocks, nil
}

func validateHeader(h *btHeader, h2 *types.Header) error {
Expand Down Expand Up @@ -396,13 +386,9 @@ func validateHeader(h *btHeader, h2 *types.Header) error {
return nil
}

func (t *BlockTest) validatePostState(statedb *state.StateDB, senderMap map[common.Address]*big.Int) error {
func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
// validate post state accounts in test file against what we have in state db
for addr, acct := range t.json.Post {
if senderGasAdjust, exist := senderMap[addr]; exist {
statedb.AddBalance(addr, senderGasAdjust)
}

// address is indirectly verified by the other fields, as it's the db key
code2 := statedb.GetCode(addr)
balance2 := statedb.GetBalance(addr)
Expand Down

0 comments on commit bd1bee7

Please sign in to comment.