Skip to content

Commit

Permalink
Bring geth updates for EIP-7623
Browse files Browse the repository at this point in the history
Refer to ethereum/go-ethereum#30946.
That PR is ongoing so we may need further updates.
  • Loading branch information
2dvorak committed Jan 7, 2025
1 parent 7b4a6f3 commit ca46720
Show file tree
Hide file tree
Showing 48 changed files with 232 additions and 163 deletions.
4 changes: 2 additions & 2 deletions accounts/abi/bind/backends/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@ func (b *BlockchainContractBackend) callContract(call kaia.CallMsg, block *types
if call.AccessList != nil {
accessList = *call.AccessList
}
intrinsicGas, err := types.IntrinsicGas(call.Data, accessList, nil, call.To == nil, b.bc.Config().Rules(block.Number()))
intrinsicGas, tokens, err := types.IntrinsicGas(call.Data, accessList, nil, call.To == nil, b.bc.Config().Rules(block.Number()))
if err != nil {
return nil, err
}

msg := types.NewMessage(call.From, call.To, 0, call.Value, call.Gas, gasPrice, nil, nil, call.Data,
false, intrinsicGas, accessList, nil)
false, intrinsicGas, tokens, accessList, nil)

txContext := blockchain.NewEVMTxContext(msg, block.Header(), b.bc.Config())
blockContext := blockchain.NewEVMBlockContext(block.Header(), b.bc, nil)
Expand Down
4 changes: 2 additions & 2 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,8 +500,8 @@ func (b *SimulatedBackend) callContract(_ context.Context, call kaia.CallMsg, bl
if call.AccessList != nil {
accessList = *call.AccessList
}
intrinsicGas, _ := types.IntrinsicGas(call.Data, accessList, nil, call.To == nil, b.config.Rules(block.Number()))
msg := types.NewMessage(call.From, call.To, nonce, call.Value, call.Gas, gasPrice, nil, nil, call.Data, true, intrinsicGas, accessList, nil)
intrinsicGas, dataTokens, _ := types.IntrinsicGas(call.Data, accessList, nil, call.To == nil, b.config.Rules(block.Number()))
msg := types.NewMessage(call.From, call.To, nonce, call.Value, call.Gas, gasPrice, nil, nil, call.Data, true, intrinsicGas, dataTokens, accessList, nil)

txContext := blockchain.NewEVMTxContext(msg, block.Header(), b.config)
blockContext := blockchain.NewEVMBlockContext(block.Header(), b.blockchain, nil)
Expand Down
8 changes: 4 additions & 4 deletions api/api_ethereum.go
Original file line number Diff line number Diff line change
Expand Up @@ -1413,11 +1413,11 @@ func EthDoCall(ctx context.Context, b Backend, args EthTransactionArgs, blockNrO
} else {
baseFee = new(big.Int).SetUint64(params.ZeroBaseFee)
}
intrinsicGas, err := types.IntrinsicGas(args.data(), args.GetAccessList(), nil, args.To == nil, b.ChainConfig().Rules(header.Number))
intrinsicGas, dataTokens, err := types.IntrinsicGas(args.data(), args.GetAccessList(), nil, args.To == nil, b.ChainConfig().Rules(header.Number))
if err != nil {
return nil, err
}
msg, err := args.ToMessage(globalGasCap, baseFee, intrinsicGas)
msg, err := args.ToMessage(globalGasCap, baseFee, intrinsicGas, dataTokens)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1570,11 +1570,11 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
precompiles := vm.ActivePrecompiles(rules)

toMsg := func() (*types.Transaction, error) {
intrinsicGas, err := types.IntrinsicGas(args.data(), nil, nil, args.To == nil, rules)
intrinsicGas, dataTokens, err := types.IntrinsicGas(args.data(), nil, nil, args.To == nil, rules)
if err != nil {
return nil, err
}
return args.ToMessage(gasCap, header.BaseFee, intrinsicGas)
return args.ToMessage(gasCap, header.BaseFee, intrinsicGas, dataTokens)
}

if args.Gas == nil {
Expand Down
8 changes: 4 additions & 4 deletions api/api_public_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
// this makes sure resources are cleaned up.
defer cancel()

intrinsicGas, err := types.IntrinsicGas(args.InputData(), args.GetAccessList(), nil, args.To == nil, b.ChainConfig().Rules(header.Number))
intrinsicGas, dataTokens, err := types.IntrinsicGas(args.InputData(), args.GetAccessList(), nil, args.To == nil, b.ChainConfig().Rules(header.Number))
if err != nil {
return nil, 0, err
}
Expand All @@ -339,7 +339,7 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
} else {
baseFee = new(big.Int).SetUint64(params.ZeroBaseFee)
}
msg, err := args.ToMessage(globalGasCap.Uint64(), baseFee, intrinsicGas)
msg, err := args.ToMessage(globalGasCap.Uint64(), baseFee, intrinsicGas, dataTokens)
if err != nil {
return nil, 0, err
}
Expand Down Expand Up @@ -689,7 +689,7 @@ func newRPCTransactionFromBlockHash(b *types.Block, hash common.Hash, config *pa
return nil
}

func (args *CallArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, intrinsicGas uint64) (*types.Transaction, error) {
func (args *CallArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, intrinsicGas uint64, dataTokens uint64) (*types.Transaction, error) {
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
} else if args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil {
Expand Down Expand Up @@ -737,5 +737,5 @@ func (args *CallArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, intrinsic
if args.AccessList != nil {
accessList = *args.AccessList
}
return types.NewMessage(addr, args.To, 0, value, gas, gasPrice, nil, nil, args.InputData(), false, intrinsicGas, accessList, nil), nil
return types.NewMessage(addr, args.To, 0, value, gas, gasPrice, nil, nil, args.InputData(), false, intrinsicGas, dataTokens, accessList, nil), nil
}
4 changes: 2 additions & 2 deletions api/tx_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ func (args *EthTransactionArgs) setDefaults(ctx context.Context, b Backend) erro
}

// ToMessage change EthTransactionArgs to types.Transaction in Kaia.
func (args *EthTransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, intrinsicGas uint64) (*types.Transaction, error) {
func (args *EthTransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, intrinsicGas uint64, dataTokens uint64) (*types.Transaction, error) {
// Reject invalid combinations of pre- and post-1559 fee styles
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
Expand Down Expand Up @@ -780,7 +780,7 @@ func (args *EthTransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int,
if args.AccessList != nil {
accessList = *args.AccessList
}
return types.NewMessage(addr, args.To, 0, value, gas, gasPrice, nil, nil, data, false, intrinsicGas, accessList, nil), nil
return types.NewMessage(addr, args.To, 0, value, gas, gasPrice, nil, nil, data, false, intrinsicGas, dataTokens, accessList, nil), nil
}

// toTransaction converts the arguments to a transaction.
Expand Down
2 changes: 1 addition & 1 deletion blockchain/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
gas, _ := types.IntrinsicGas(data, nil, nil, false, params.TestChainConfig.Rules(big.NewInt(0)))
gas, _, _ := types.IntrinsicGas(data, nil, nil, false, params.TestChainConfig.Rules(big.NewInt(0)))
signer := types.LatestSignerForChainID(params.TestChainConfig.ChainID)
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), signer, benchRootKey)
gen.AddTx(tx)
Expand Down
12 changes: 6 additions & 6 deletions blockchain/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1461,8 +1461,8 @@ func TestAccessListTx(t *testing.T) {
b.SetRewardbase(common.Address{1})

// One transaction to 0xAAAA
intrinsicGas, _ := types.IntrinsicGas([]byte{}, list, nil, false, gspec.Config.Rules(block.Number()))
tx, _ := types.SignTx(types.NewMessage(senderAddr, &contractAddr, senderNonce, big.NewInt(0), 30000, big.NewInt(1), nil, nil, []byte{}, false, intrinsicGas, list, nil), signer, senderKey)
intrinsicGas, dataTokens, _ := types.IntrinsicGas([]byte{}, list, nil, false, gspec.Config.Rules(block.Number()))
tx, _ := types.SignTx(types.NewMessage(senderAddr, &contractAddr, senderNonce, big.NewInt(0), 30000, big.NewInt(1), nil, nil, []byte{}, false, intrinsicGas, dataTokens, list, nil), signer, senderKey)
b.AddTx(tx)
})
if n, err := chain.InsertChain(blocks); err != nil {
Expand Down Expand Up @@ -2345,13 +2345,13 @@ func TestEIP7702(t *testing.T) {
b.SetRewardbase(common.Address{1})

authorizationList := []types.Authorization{*auth1, *auth2}
intrinsicGas, err := types.IntrinsicGas(nil, nil, authorizationList, false, params.TestRules)
intrinsicGas, dataTokens, err := types.IntrinsicGas(nil, nil, authorizationList, false, params.TestRules)
if err != nil {
t.Fatalf("failed to run intrinsic gas: %v", err)
}

tx, err := types.SignTx(types.NewMessage(addr1, &addr1, uint64(0), nil, 500000, nil, newGkei(50),
big.NewInt(20), nil, false, intrinsicGas, nil, authorizationList), signer, key1)
big.NewInt(20), nil, false, intrinsicGas, dataTokens, nil, authorizationList), signer, key1)
if err != nil {
t.Fatalf("failed to sign tx: %v", err)
}
Expand Down Expand Up @@ -2426,13 +2426,13 @@ func TestEIP7702(t *testing.T) {
}, key1)

authorizationList := []types.Authorization{*authForEmpty}
intrinsicGas, err := types.IntrinsicGas(nil, nil, authorizationList, false, params.TestRules)
intrinsicGas, dataTokens, err := types.IntrinsicGas(nil, nil, authorizationList, false, params.TestRules)
if err != nil {
t.Fatalf("failed to run intrinsic gas: %v", err)
}

tx, err := types.SignTx(types.NewMessage(addr1, &addr1, state.GetNonce(addr1), nil, 500000, nil, newGkei(50),
big.NewInt(20), nil, false, intrinsicGas, nil, authorizationList), signer, key1)
big.NewInt(20), nil, false, intrinsicGas, dataTokens, nil, authorizationList), signer, key1)
if err != nil {
t.Fatalf("failed to sign tx: %v", err)
}
Expand Down
4 changes: 4 additions & 0 deletions blockchain/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ var (
// than required to start the invocation.
ErrIntrinsicGas = errors.New("intrinsic gas too low")

// ErrDataFloorGas is returned if the transaction is specified to use less gas
// than required for the data floor cost.
ErrDataFloorGas = errors.New("insufficient gas for data floor cost")

// ErrGasLimit is returned if a transaction's requested gas limit exceeds the
// maximum allowance of the current block.
ErrGasLimit = errors.New("exceeds block gas limit")
Expand Down
3 changes: 2 additions & 1 deletion blockchain/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func ProcessParentBlockHash(header *types.Header, vmenv *vm.EVM, statedb vm.Stat
gasLimit = uint64(30_000_000)
)

intrinsicGas, err := types.IntrinsicGas(data, nil, nil, false, rules)
intrinsicGas, dataTokens, err := types.IntrinsicGas(data, nil, nil, false, rules)
if err != nil {
return err
}
Expand All @@ -129,6 +129,7 @@ func ProcessParentBlockHash(header *types.Header, vmenv *vm.EVM, statedb vm.Stat
data,
false,
intrinsicGas,
dataTokens,
nil,
nil,
)
Expand Down
39 changes: 34 additions & 5 deletions blockchain/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ package blockchain
import (
"errors"
"fmt"
"math"
"math/big"

"github.com/kaiachain/kaia/blockchain/types"
Expand Down Expand Up @@ -83,7 +84,7 @@ type Message interface {

// ValidatedIntrinsicGas returns the intrinsic gas of the transaction.
// The returned intrinsic gas should be derived by calling AsMessageAccountKeyPicker().
ValidatedIntrinsicGas() uint64
ValidatedIntrinsicGas() *types.ValidatedIntrinsicGas

// FeeRatio returns a ratio of tx fee paid by the fee payer in percentage.
// For example, if it is 30, 30% of tx fee will be paid by the fee payer.
Expand Down Expand Up @@ -111,7 +112,7 @@ type Message interface {

// IntrinsicGas returns `intrinsic gas` based on the tx type.
// This value is used to differentiate tx fee based on the tx type.
IntrinsicGas(currentBlockNumber uint64) (uint64, error)
IntrinsicGas(currentBlockNumber uint64) (uint64, uint64, error)

// Type returns the transaction type of the message.
Type() types.TxType
Expand Down Expand Up @@ -345,11 +346,20 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
}

// Check clauses 4-5, subtract intrinsic gas if everything is correct
amount := msg.ValidatedIntrinsicGas()
if st.gas < amount {
validatedGas := msg.ValidatedIntrinsicGas()
if st.gas < validatedGas.Gas {
return nil, ErrIntrinsicGas
}
st.gas -= amount
if st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber).IsPrague {
floorGas, err := FloorDataGas(validatedGas.Tokens)
if err != nil {
return nil, err
}
if st.gas < floorGas {
return nil, fmt.Errorf("%w: have %d, want %d", ErrDataFloorGas, st.gas, floorGas)
}
}
st.gas -= validatedGas.Gas

// Check clause 6
if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.ValidatedSender(), msg.Value()) {
Expand Down Expand Up @@ -408,6 +418,15 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
return nil, vm.ErrTotalTimeLimitReached
}

if st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber).IsPrague {
// After EIP-7623: Data-heavy transactions pay the floor gas.
// Overflow error has already been checked and can be ignored here.
floorGas, _ := FloorDataGas(validatedGas.Tokens)
if st.gasUsed() < floorGas {
st.gas = st.initialGas - floorGas
}
}

if rules.IsKore {
// After EIP-3529: refunds are capped to gasUsed / 5
st.refundGas(params.RefundQuotientEIP3529)
Expand Down Expand Up @@ -582,3 +601,13 @@ func (st *StateTransition) processAuthorizationList(authList types.Authorization
}
}
}

// FloorDataGas calculates the minimum gas required for a transaction
// based on its data tokens (EIP-7623).
func FloorDataGas(tokens uint64) (uint64, error) {
// Check for overflow
if (math.MaxUint64-params.TxGas)/params.CostFloorPerToken7623 < tokens {
return 0, types.ErrGasUintOverflow
}
return params.TxGas + tokens*params.CostFloorPerToken7623, nil
}
3 changes: 2 additions & 1 deletion blockchain/system/multicall.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func (caller *ContractCallerForMultiCall) CallContract(ctx context.Context, call
gasPrice := big.NewInt(0) // execute call regardless of the balance of the sender
gasLimit := uint64(1e8) // enough gas limit to execute multicall contract functions
intrinsicGas := uint64(0) // read operation doesn't require intrinsicGas
dataTokens := uint64(0) // read operation has no calldata

// call.From: zero address will be assigned if nothing is specified
// call.To: the target contract address will be assigned by `BoundContract`
Expand All @@ -63,7 +64,7 @@ func (caller *ContractCallerForMultiCall) CallContract(ctx context.Context, call
}

msg := types.NewMessage(call.From, call.To, caller.state.GetNonce(call.From),
call.Value, gasLimit, gasPrice, nil, nil, call.Data, false, intrinsicGas, nil, nil)
call.Value, gasLimit, gasPrice, nil, nil, call.Data, false, intrinsicGas, dataTokens, nil, nil)

blockContext := blockchain.NewEVMBlockContext(caller.header, caller.chain, nil)
txContext := blockchain.NewEVMTxContext(msg, caller.header, caller.chain.Config())
Expand Down
3 changes: 2 additions & 1 deletion blockchain/system/rebalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func (caller *Kip103ContractCaller) CallContract(ctx context.Context, call kaia.
gasPrice := big.NewInt(0) // execute call regardless of the balance of the sender
gasLimit := uint64(1e8) // enough gas limit to execute kip103 contract functions
intrinsicGas := uint64(0) // read operation doesn't require intrinsicGas
dataTokens := uint64(0) // read operation has no calldata

// call.From: zero address will be assigned if nothing is specified
// call.To: the target contract address will be assigned by `BoundContract`
Expand All @@ -122,7 +123,7 @@ func (caller *Kip103ContractCaller) CallContract(ctx context.Context, call kaia.
// return nil, err
//}
msg := types.NewMessage(call.From, call.To, caller.state.GetNonce(call.From),
call.Value, gasLimit, gasPrice, nil, nil, call.Data, false, intrinsicGas, nil, nil)
call.Value, gasLimit, gasPrice, nil, nil, call.Data, false, intrinsicGas, dataTokens, nil, nil)

blockContext := blockchain.NewEVMBlockContext(caller.header, caller.chain, nil)
txContext := blockchain.NewEVMTxContext(msg, caller.header, caller.chain.Config())
Expand Down
12 changes: 11 additions & 1 deletion blockchain/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -836,14 +836,24 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
}
}

intrGas, err := tx.IntrinsicGas(pool.currentBlockNumber)
intrGas, dataTokens, err := tx.IntrinsicGas(pool.currentBlockNumber)
intrGas += gasFrom + gasFeePayer
if err != nil {
return err
}
if tx.Gas() < intrGas {
return ErrIntrinsicGas
}
// Ensure the transaction can cover floor data gas.
if pool.rules.IsPrague {
floorGas, err := FloorDataGas(dataTokens)
if err != nil {
return err
}
if tx.Gas() < floorGas {
return fmt.Errorf("%w: gas %v, minimum needed %v", ErrDataFloorGas, tx.Gas(), floorGas)
}
}

// "tx.Validate()" conducts additional validation for each new txType.
// Validate humanReadable address when this tx has "true" in the humanReadable field.
Expand Down
19 changes: 12 additions & 7 deletions blockchain/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ func ErrFeePayer(err error) error {
return fmt.Errorf("invalid fee payer: %s", err)
}

type ValidatedIntrinsicGas struct {
Gas uint64
Tokens uint64
}

type Transaction struct {
data TxInternalData
time time.Time
Expand All @@ -90,7 +95,7 @@ type Transaction struct {
validatedFeePayer common.Address
// validatedIntrinsicGas represents intrinsic gas of the transaction to be used for ApplyTransaction().
// This value is set in AsMessageWithAccountKeyPicker().
validatedIntrinsicGas uint64
validatedIntrinsicGas *ValidatedIntrinsicGas
// The account's nonce is checked only if `checkNonce` is true.
checkNonce bool
// This value is set when the tx is invalidated in block tx validation, and is used to remove pending tx in txPool.
Expand Down Expand Up @@ -385,15 +390,15 @@ func (tx *Transaction) ValidatedFeePayer() common.Address {
return tx.validatedFeePayer
}

func (tx *Transaction) ValidatedIntrinsicGas() uint64 {
func (tx *Transaction) ValidatedIntrinsicGas() *ValidatedIntrinsicGas {
tx.mu.RLock()
defer tx.mu.RUnlock()
return tx.validatedIntrinsicGas
}
func (tx *Transaction) MakeRPCOutput() map[string]interface{} { return tx.data.MakeRPCOutput() }
func (tx *Transaction) GetTxInternalData() TxInternalData { return tx.data }

func (tx *Transaction) IntrinsicGas(currentBlockNumber uint64) (uint64, error) {
func (tx *Transaction) IntrinsicGas(currentBlockNumber uint64) (uint64, uint64, error) {
return tx.data.IntrinsicGas(currentBlockNumber)
}

Expand Down Expand Up @@ -584,7 +589,7 @@ func (tx *Transaction) Execute(vm VM, stateDB StateDB, currentBlockNumber uint64
// XXX Rename message to something less arbitrary?
// TODO-Kaia: Message is removed and this function will return *Transaction.
func (tx *Transaction) AsMessageWithAccountKeyPicker(s Signer, picker AccountKeyPicker, currentBlockNumber uint64) (*Transaction, error) {
intrinsicGas, err := tx.IntrinsicGas(currentBlockNumber)
intrinsicGas, dataTokens, err := tx.IntrinsicGas(currentBlockNumber)
if err != nil {
return nil, err
}
Expand All @@ -607,7 +612,7 @@ func (tx *Transaction) AsMessageWithAccountKeyPicker(s Signer, picker AccountKey
}

tx.mu.Lock()
tx.validatedIntrinsicGas = intrinsicGas + gasFrom + gasFeePayer
tx.validatedIntrinsicGas = &ValidatedIntrinsicGas{Gas: intrinsicGas + gasFrom + gasFeePayer, Tokens: dataTokens}
tx.mu.Unlock()

return tx, err
Expand Down Expand Up @@ -1079,9 +1084,9 @@ func (t *TransactionsByPriceAndNonce) Clear() {
}

// NewMessage returns a `*Transaction` object with the given arguments.
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, checkNonce bool, intrinsicGas uint64, list AccessList, auth AuthorizationList) *Transaction {
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, checkNonce bool, intrinsicGas uint64, dataTokens uint64, list AccessList, auth AuthorizationList) *Transaction {
transaction := &Transaction{
validatedIntrinsicGas: intrinsicGas,
validatedIntrinsicGas: &ValidatedIntrinsicGas{Gas: intrinsicGas, Tokens: dataTokens},
validatedFeePayer: from,
validatedSender: from,
checkNonce: checkNonce,
Expand Down
Loading

0 comments on commit ca46720

Please sign in to comment.