mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-07 23:48:36 +00:00
core, core/vm: implement EIP-7708
This commit is contained in:
parent
d2dbbe48c4
commit
50b7009201
6 changed files with 55 additions and 7 deletions
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -141,7 +142,10 @@ func CanTransfer(db vm.StateDB, addr common.Address, amount *uint256.Int) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
|
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
|
||||||
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int) {
|
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int, blockNumber *big.Int, rules *params.Rules) {
|
||||||
db.SubBalance(sender, amount, tracing.BalanceChangeTransfer)
|
db.SubBalance(sender, amount, tracing.BalanceChangeTransfer)
|
||||||
db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer)
|
db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer)
|
||||||
|
if rules.IsAmsterdam && !amount.IsZero() {
|
||||||
|
db.AddLog(types.EthTransferLog(blockNumber, sender, recipient, amount))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,11 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run ../../rlp/rlpgen -type Log -out gen_log_rlp.go
|
//go:generate go run ../../rlp/rlpgen -type Log -out gen_log_rlp.go
|
||||||
|
|
@ -62,3 +65,30 @@ type logMarshaling struct {
|
||||||
BlockTimestamp hexutil.Uint64
|
BlockTimestamp hexutil.Uint64
|
||||||
Index hexutil.Uint
|
Index hexutil.Uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// system contract address
|
||||||
|
EthTransferLogAddress = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
|
||||||
|
// keccak256('Transfer(address,address,uint256)')
|
||||||
|
EthTransferLogTopic0 = common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
|
||||||
|
)
|
||||||
|
|
||||||
|
// EthTransferLog creates and ETH transfer log according to EIP-7708.
|
||||||
|
// Specification: https://eips.ethereum.org/EIPS/eip-7708
|
||||||
|
func EthTransferLog(blockNumber *big.Int, from, to common.Address, amount *uint256.Int) *Log {
|
||||||
|
topics := make([]common.Hash, 3)
|
||||||
|
topics[0] = EthTransferLogTopic0
|
||||||
|
copy(topics[1][common.HashLength-common.AddressLength:], from[:])
|
||||||
|
copy(topics[2][common.HashLength-common.AddressLength:], to[:])
|
||||||
|
amount32 := amount.Bytes32()
|
||||||
|
data := make([]byte, 32)
|
||||||
|
copy(data, amount32[:])
|
||||||
|
return &Log{
|
||||||
|
Address: EthTransferLogAddress,
|
||||||
|
Topics: topics,
|
||||||
|
Data: data,
|
||||||
|
// This is a non-consensus field, but assigned here because
|
||||||
|
// core/state doesn't know the current block number.
|
||||||
|
BlockNumber: blockNumber.Uint64(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type (
|
||||||
// CanTransferFunc is the signature of a transfer guard function
|
// CanTransferFunc is the signature of a transfer guard function
|
||||||
CanTransferFunc func(StateDB, common.Address, *uint256.Int) bool
|
CanTransferFunc func(StateDB, common.Address, *uint256.Int) bool
|
||||||
// TransferFunc is the signature of a transfer function
|
// TransferFunc is the signature of a transfer function
|
||||||
TransferFunc func(StateDB, common.Address, common.Address, *uint256.Int)
|
TransferFunc func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules)
|
||||||
// GetHashFunc returns the n'th block hash in the blockchain
|
// GetHashFunc returns the n'th block hash in the blockchain
|
||||||
// and is used by the BLOCKHASH EVM op code.
|
// and is used by the BLOCKHASH EVM op code.
|
||||||
GetHashFunc func(uint64) common.Hash
|
GetHashFunc func(uint64) common.Hash
|
||||||
|
|
@ -283,7 +283,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
||||||
}
|
}
|
||||||
evm.StateDB.CreateAccount(addr)
|
evm.StateDB.CreateAccount(addr)
|
||||||
}
|
}
|
||||||
evm.Context.Transfer(evm.StateDB, caller, addr, value)
|
evm.Context.Transfer(evm.StateDB, caller, addr, value, evm.Context.BlockNumber, &evm.chainRules)
|
||||||
|
|
||||||
if isPrecompile {
|
if isPrecompile {
|
||||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||||
|
|
@ -560,7 +560,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
||||||
}
|
}
|
||||||
gas = gas - consumed
|
gas = gas - consumed
|
||||||
}
|
}
|
||||||
evm.Context.Transfer(evm.StateDB, caller, address, value)
|
evm.Context.Transfer(evm.StateDB, caller, address, value, evm.Context.BlockNumber, &evm.chainRules)
|
||||||
|
|
||||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||||
// The contract is a scoped environment for this execution context only.
|
// The contract is a scoped environment for this execution context only.
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ func TestEIP2200(t *testing.T) {
|
||||||
|
|
||||||
vmctx := BlockContext{
|
vmctx := BlockContext{
|
||||||
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
|
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules) {},
|
||||||
}
|
}
|
||||||
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
|
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
|
||||||
|
|
||||||
|
|
@ -144,7 +144,7 @@ func TestCreateGas(t *testing.T) {
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
vmctx := BlockContext{
|
vmctx := BlockContext{
|
||||||
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
|
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules) {},
|
||||||
BlockNumber: big.NewInt(0),
|
BlockNumber: big.NewInt(0),
|
||||||
}
|
}
|
||||||
config := Config{}
|
config := Config{}
|
||||||
|
|
|
||||||
|
|
@ -895,6 +895,13 @@ func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
}
|
}
|
||||||
// Clear any leftover funds for the account being destructed.
|
// Clear any leftover funds for the account being destructed.
|
||||||
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
||||||
|
if evm.chainRules.IsAmsterdam && !balance.IsZero() {
|
||||||
|
if this != beneficiary {
|
||||||
|
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, beneficiary, balance))
|
||||||
|
} else {
|
||||||
|
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, common.Address{}, balance))
|
||||||
|
}
|
||||||
|
}
|
||||||
evm.StateDB.SelfDestruct(this)
|
evm.StateDB.SelfDestruct(this)
|
||||||
|
|
||||||
if tracer := evm.Config.Tracer; tracer != nil {
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
|
|
@ -933,6 +940,13 @@ func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, erro
|
||||||
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
||||||
evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct)
|
evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct)
|
||||||
}
|
}
|
||||||
|
if evm.chainRules.IsAmsterdam && !balance.IsZero() {
|
||||||
|
if this != beneficiary {
|
||||||
|
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, beneficiary, balance))
|
||||||
|
} else if newContract {
|
||||||
|
evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, common.Address{}, balance))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if tracer := evm.Config.Tracer; tracer != nil {
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
if tracer.OnEnter != nil {
|
if tracer.OnEnter != nil {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ var loopInterruptTests = []string{
|
||||||
func TestLoopInterrupt(t *testing.T) {
|
func TestLoopInterrupt(t *testing.T) {
|
||||||
address := common.BytesToAddress([]byte("contract"))
|
address := common.BytesToAddress([]byte("contract"))
|
||||||
vmctx := BlockContext{
|
vmctx := BlockContext{
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
|
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int, *big.Int, *params.Rules) {},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range loopInterruptTests {
|
for i, tt := range loopInterruptTests {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue