mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
partial review feedback
This commit is contained in:
parent
54bdfb42bd
commit
f534a4dc35
9 changed files with 59 additions and 48 deletions
|
|
@ -194,7 +194,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
}
|
||||
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
||||
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb, big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp)
|
||||
}
|
||||
|
||||
for i := 0; txIt.Next(); i++ {
|
||||
|
|
|
|||
|
|
@ -361,8 +361,10 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
|
|||
amount = amount.Mul(amount, uint256.NewInt(params.GWei))
|
||||
state.AddBalance(w.Address, amount, tracing.BalanceIncreaseWithdrawal)
|
||||
|
||||
// Add the balance of each withdrawal to the witness, no gas will
|
||||
// be charged.
|
||||
if chain.Config().IsEIP4762(header.Number, header.Time) {
|
||||
state.Witness().TouchFullAccount(w.Address[:], true)
|
||||
state.Witness().TouchBalance(w.Address[:], true)
|
||||
}
|
||||
}
|
||||
// No block reward which is issued by consensus layer instead.
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ func (aw *AccessWitness) Copy() *AccessWitness {
|
|||
return naw
|
||||
}
|
||||
|
||||
// TouchFullAccount returns the gas to be charged for each of the currently cold
|
||||
// member fields of an account.
|
||||
func (aw *AccessWitness) TouchFullAccount(addr []byte, isWrite bool) uint64 {
|
||||
var gas uint64
|
||||
for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ {
|
||||
|
|
@ -97,6 +99,9 @@ func (aw *AccessWitness) TouchFullAccount(addr []byte, isWrite bool) uint64 {
|
|||
return gas
|
||||
}
|
||||
|
||||
// TouchAndChargeMessageCall returns the gas to be charged for each of the currently
|
||||
// cold member fields of an account, that need to be touched when making a message
|
||||
// call to that account.
|
||||
func (aw *AccessWitness) TouchAndChargeMessageCall(destination []byte) uint64 {
|
||||
var gas uint64
|
||||
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, false)
|
||||
|
|
@ -104,6 +109,8 @@ func (aw *AccessWitness) TouchAndChargeMessageCall(destination []byte) uint64 {
|
|||
return gas
|
||||
}
|
||||
|
||||
// TouchAndChargeValueTransfer returns the gas to be charged for each of the currently
|
||||
// cold balance member fields of the caller and the callee accounts.
|
||||
func (aw *AccessWitness) TouchAndChargeValueTransfer(callerAddr, targetAddr []byte) uint64 {
|
||||
var gas uint64
|
||||
gas += aw.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
|
||||
|
|
@ -111,8 +118,8 @@ func (aw *AccessWitness) TouchAndChargeValueTransfer(callerAddr, targetAddr []by
|
|||
return gas
|
||||
}
|
||||
|
||||
// TouchAndChargeContractCreateInit charges access costs to initiate
|
||||
// a contract creation
|
||||
// TouchAndChargeContractCreateInit returns the access gas costs for the initialization of
|
||||
// a contract creation.
|
||||
func (aw *AccessWitness) TouchAndChargeContractCreateInit(addr []byte, createSendsValue bool) uint64 {
|
||||
var gas uint64
|
||||
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, true)
|
||||
|
|
@ -123,41 +130,30 @@ func (aw *AccessWitness) TouchAndChargeContractCreateInit(addr []byte, createSen
|
|||
return gas
|
||||
}
|
||||
|
||||
func (aw *AccessWitness) TouchTxOriginAndComputeGas(originAddr []byte) uint64 {
|
||||
// TouchTxOrigin adds the member fields of the sender account to the witness,
|
||||
// so that cold accesses are not charged, since they are covered by the 21000 gas.
|
||||
func (aw *AccessWitness) TouchTxOrigin(originAddr []byte) {
|
||||
for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ {
|
||||
aw.touchAddressAndChargeGas(originAddr, zeroTreeIndex, byte(i), i == utils.BalanceLeafKey || i == utils.NonceLeafKey)
|
||||
}
|
||||
|
||||
// Kaustinen note: we're currently experimenting with stop chargin gas for the origin address
|
||||
// so simple transfer still take 21000 gas. This is to potentially avoid breaking existing tooling.
|
||||
// This is the reason why we return 0 instead of `gas`.
|
||||
// Note that we still have to touch the addresses to make sure the witness is correct.
|
||||
return 0
|
||||
}
|
||||
|
||||
func (aw *AccessWitness) TouchTxExistingAndComputeGas(targetAddr []byte, sendsValue bool) uint64 {
|
||||
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.VersionLeafKey, false)
|
||||
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.CodeSizeLeafKey, false)
|
||||
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.CodeKeccakLeafKey, false)
|
||||
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.NonceLeafKey, false)
|
||||
if sendsValue {
|
||||
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
|
||||
} else {
|
||||
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, false)
|
||||
// TouchTxDestination adds the member fields of the sender account to the witness,
|
||||
// so that cold accesses are not charged, since they are covered by the 21000 gas.
|
||||
func (aw *AccessWitness) TouchTxDestination(targetAddr []byte, sendsValue bool) {
|
||||
for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ {
|
||||
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, byte(i), i == utils.VersionLeafKey && sendsValue)
|
||||
}
|
||||
|
||||
// Kaustinen note: we're currently experimenting with stop chargin gas for the origin address
|
||||
// so simple transfer still take 21000 gas. This is to potentially avoid breaking existing tooling.
|
||||
// This is the reason why we return 0 instead of `gas`.
|
||||
// Note that we still have to touch the addresses to make sure the witness is correct.
|
||||
return 0
|
||||
}
|
||||
|
||||
// TouchSlotAndChargeGas returns the amount of gas to be charged for a cold storage access.
|
||||
func (aw *AccessWitness) TouchSlotAndChargeGas(addr []byte, slot common.Hash, isWrite bool) uint64 {
|
||||
treeIndex, subIndex := utils.StorageIndex(slot.Bytes())
|
||||
return aw.touchAddressAndChargeGas(addr, *treeIndex, subIndex, isWrite)
|
||||
}
|
||||
|
||||
// touchAddressAndChargeGas adds any missing access event to the witness, and returns the cold
|
||||
// access cost to be charged, if need be.
|
||||
func (aw *AccessWitness) touchAddressAndChargeGas(addr []byte, treeIndex uint256.Int, subIndex byte, isWrite bool) uint64 {
|
||||
stemRead, selectorRead, stemWrite, selectorWrite, selectorFill := aw.touchAddress(addr, treeIndex, subIndex, isWrite)
|
||||
|
||||
|
|
|
|||
|
|
@ -423,17 +423,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||
targetAddr := msg.To
|
||||
originAddr := msg.From
|
||||
|
||||
statelessGasOrigin := st.evm.Accesses.TouchTxOriginAndComputeGas(originAddr.Bytes())
|
||||
if !tryConsumeGas(&st.gasRemaining, statelessGasOrigin) {
|
||||
return nil, fmt.Errorf("%w: Insufficient funds to cover witness access costs for transaction: have %d, want %d", ErrInsufficientBalanceWitness, st.gasRemaining, gas)
|
||||
}
|
||||
st.evm.Accesses.TouchTxOrigin(originAddr.Bytes())
|
||||
originNonce := st.evm.StateDB.GetNonce(originAddr)
|
||||
|
||||
if msg.To != nil {
|
||||
statelessGasDest := st.evm.Accesses.TouchTxExistingAndComputeGas(targetAddr.Bytes(), msg.Value.Sign() != 0)
|
||||
if !tryConsumeGas(&st.gasRemaining, statelessGasDest) {
|
||||
return nil, fmt.Errorf("%w: Insufficient funds to cover witness access costs for transaction: have %d, want %d", ErrInsufficientBalanceWitness, st.gasRemaining, gas)
|
||||
}
|
||||
st.evm.Accesses.TouchTxDestination(targetAddr.Bytes(), msg.Value.Sign() != 0)
|
||||
|
||||
// ensure the code size ends up in the access witness
|
||||
st.evm.StateDB.GetCodeSize(*targetAddr)
|
||||
|
|
@ -501,7 +495,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||
|
||||
// add the coinbase to the witness iff the fee is greater than 0
|
||||
if rules.IsEIP4762 && fee.Sign() != 0 {
|
||||
st.evm.Accesses.TouchFullAccount(st.evm.Context.Coinbase[:], true)
|
||||
st.evm.Accesses.TouchBalance(st.evm.Context.Coinbase[:], true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -272,6 +272,12 @@ const (
|
|||
GasChangeCallStorageColdAccess GasChangeReason = 13
|
||||
// GasChangeCallFailedExecution is the burning of the remaining gas when the execution failed without a revert.
|
||||
GasChangeCallFailedExecution GasChangeReason = 14
|
||||
// GasChangeWitnessContractInit is the amount charged for adding to the witness during the contract creation initialization step
|
||||
GasChangeWitnessContractInit GasChangeReason = 15
|
||||
// GasChangeWitnessContractCreation is the amount charged for adding to the witness during the contract creation finalization step
|
||||
GasChangeWitnessContractCreation GasChangeReason = 16
|
||||
// GasChangeWitnessCodeChunk is the amount charged for touching one or more contract code chunks
|
||||
GasChangeWitnessCodeChunk GasChangeReason = 17
|
||||
|
||||
// GasChangeIgnored is a special value that can be used to indicate that the gas change should be ignored as
|
||||
// it will be "manually" tracked by a direct emit of the gas change event.
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ func enable4762(jt *JumpTable) {
|
|||
jt[EXTCODEHASH].dynamicGas = gasExtCodeHash4762
|
||||
jt[EXTCODECOPY].constantGas = 0
|
||||
jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP4762
|
||||
jt[CODECOPY].dynamicGas = gasCodeCopyEip4762
|
||||
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP4762
|
||||
jt[CREATE].constantGas = params.CreateNGasEip4762
|
||||
jt[CREATE2].constantGas = params.CreateNGasEip4762
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
|
||||
// Charge the contract creation init gas in verkle mode
|
||||
if evm.chainRules.IsEIP4762 {
|
||||
if !contract.UseGas(evm.Accesses.TouchAndChargeContractCreateInit(address.Bytes(), value.Sign() != 0), evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
||||
if !contract.UseGas(evm.Accesses.TouchAndChargeContractCreateInit(address.Bytes(), value.Sign() != 0), evm.Config.Tracer, tracing.GasChangeWitnessContractInit) {
|
||||
err = ErrOutOfGas
|
||||
}
|
||||
}
|
||||
|
|
@ -541,11 +541,11 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
}
|
||||
} else {
|
||||
// Contract creation completed, touch the missing fields in the contract
|
||||
if !contract.UseGas(evm.Accesses.TouchFullAccount(address.Bytes()[:], true), evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
||||
if !contract.UseGas(evm.Accesses.TouchFullAccount(address.Bytes()[:], true), evm.Config.Tracer, tracing.GasChangeWitnessContractCreation) {
|
||||
err = ErrOutOfGas
|
||||
}
|
||||
|
||||
if err != nil && len(ret) > 0 && !contract.UseGas(evm.Accesses.TouchCodeChunksRangeAndChargeGas(address.Bytes(), 0, uint64(len(ret)), uint64(len(ret)), true), evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
||||
if err != nil && len(ret) > 0 && !contract.UseGas(evm.Accesses.TouchCodeChunksRangeAndChargeGas(address.Bytes(), 0, uint64(len(ret)), uint64(len(ret)), true), evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk) {
|
||||
err = ErrOutOfGas
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -364,16 +364,8 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
uint64CodeOffset = math.MaxUint64
|
||||
}
|
||||
|
||||
contractAddr := scope.Contract.Address()
|
||||
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(scope.Contract.Code, uint64CodeOffset, length.Uint64())
|
||||
if interpreter.evm.chainRules.IsEIP4762 && !scope.Contract.IsDeployment {
|
||||
statelessGas := interpreter.evm.Accesses.TouchCodeChunksRangeAndChargeGas(contractAddr[:], copyOffset, nonPaddedCopyLength, uint64(len(scope.Contract.Code)), false)
|
||||
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
||||
scope.Contract.Gas = 0
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
}
|
||||
scope.Memory.Set(memOffset.Uint64(), uint64(len(paddedCodeCopy)), paddedCodeCopy)
|
||||
codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64())
|
||||
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,26 @@ func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Mem
|
|||
return statelessGas, nil
|
||||
}
|
||||
|
||||
func gasCodeCopyEip4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
gas, err := gasCodeCopy(evm, contract, stack, mem, memorySize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var (
|
||||
codeOffset = stack.Back(1)
|
||||
length = stack.Back(2)
|
||||
)
|
||||
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
||||
if overflow {
|
||||
uint64CodeOffset = math.MaxUint64
|
||||
}
|
||||
_, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(contract.Code, uint64CodeOffset, length.Uint64())
|
||||
if !contract.IsDeployment {
|
||||
gas += evm.Accesses.TouchCodeChunksRangeAndChargeGas(contract.Address().Bytes(), copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
|
||||
func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
// memory expansion first (dynamic part of pre-2929 implementation)
|
||||
gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize)
|
||||
|
|
|
|||
Loading…
Reference in a new issue