Skip to content

Commit

Permalink
Merge pull request #231 from Mdaiki0730/feat/eets-refactor
Browse files Browse the repository at this point in the history
test: Remove some main code modifications in EETS
  • Loading branch information
Mdaiki0730 authored Jan 27, 2025
2 parents 77ad493 + bd1bee7 commit 64c368f
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 108 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
39 changes: 5 additions & 34 deletions blockchain/types/tx_internal_data_serializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,42 +69,13 @@ func (serializer *TxInternalDataSerializer) EncodeRLP(w io.Writer) error {
func (serializer *TxInternalDataSerializer) DecodeRLP(s *rlp.Stream) error {
if err := s.Decode(&serializer.txType); err != nil {
// fallback to the original transaction decoding.
kind, _, err := s.Kind()
switch {
case err != nil:
txd := newEmptyTxInternalDataLegacy()
if err := s.Decode(txd); err != nil {
return err
case kind == rlp.List:
// It's a legacy transaction.
txd := newEmptyTxInternalDataLegacy()
if err := s.Decode(txd); err != nil {
return err
}
serializer.txType = TxTypeLegacyTransaction
serializer.tx = txd
return nil
default:
// It's an EIP-2718 typed TX envelope.
// First read the tx payload bytes into a temporary buffer.
ethType, err := s.ReadByte()
if err != nil {
return err
}

switch ethType {
case 1:
serializer.tx = new(TxInternalDataEthereumAccessList)
case 2:
serializer.tx = new(TxInternalDataEthereumDynamicFee)
case 3:
return errUndefinedTxType
case 4:
serializer.tx = new(TxInternalDataEthereumSetCode)
default:
return errUndefinedTxType
}

return s.Decode(serializer.tx)
}
serializer.txType = TxTypeLegacyTransaction
serializer.tx = txd
return nil
}

if serializer.txType == EthereumTxTypeEnvelope {
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
133 changes: 80 additions & 53 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 Expand Up @@ -611,8 +597,49 @@ func (bb *btBlock) decodeTx() (types.Transactions, TestHeader, error) {

// Decode transactions
var txs types.Transactions
if err := s.Decode(&txs); err != nil {
return nil, TestHeader{}, fmt.Errorf("failed to decode transactions: %v", err)
if _, err := s.List(); err != nil {
return nil, TestHeader{}, fmt.Errorf("failed to enter outer list: %v", err)
}

// Self decode to convert to kaia's eth tx type
for {
var tx types.Transaction
kind, _, err := s.Kind()
if err == rlp.EOL {
break
} else if err != nil {
return nil, TestHeader{}, fmt.Errorf("failed to get RLP kind: %v", err)
}

txdata, _ := s.Raw()
ethTxDataInKaia := []byte{}
switch kind {
case rlp.List: // case of legacy
ethTxDataInKaia = txdata
case rlp.String: // case of envelope
var ethTypeIndex int
if txdata[0] < 0xb7 {
ethTypeIndex = 1
} else {
ethTypeIndex = int(txdata[0] - 0xb7 + 1)
}
switch txdata[ethTypeIndex] {
case 1, 2, 4: // eth transaction types whick kaia support
ethTxDataInKaia = append([]byte{byte(types.EthereumTxTypeEnvelope)}, txdata[ethTypeIndex:]...)
default:
ethTxDataInKaia = txdata
}
default:
return nil, TestHeader{}, fmt.Errorf("failed to get RLP kind: %v", err)
}

streamForTx := rlp.NewStream(bytes.NewReader(ethTxDataInKaia), 0)
if err := streamForTx.Decode(&tx); err == rlp.EOL {
break
} else if err != nil {
return nil, TestHeader{}, fmt.Errorf("failed to decode transaction: %v", err)
}
txs = append(txs, &tx)
}

return txs, header, nil
Expand Down

0 comments on commit 64c368f

Please sign in to comment.