mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
EIP-XXXX: AuthCreate
This commit is contained in:
parent
e6689fe090
commit
8c04f95f1e
12 changed files with 115 additions and 1 deletions
|
|
@ -268,6 +268,8 @@ const (
|
||||||
GasChangeCallStorageColdAccess GasChangeReason = 13
|
GasChangeCallStorageColdAccess GasChangeReason = 13
|
||||||
// GasChangeCallFailedExecution is the burning of the remaining gas when the execution failed without a revert.
|
// GasChangeCallFailedExecution is the burning of the remaining gas when the execution failed without a revert.
|
||||||
GasChangeCallFailedExecution GasChangeReason = 14
|
GasChangeCallFailedExecution GasChangeReason = 14
|
||||||
|
// GasChangeContractCreation is the amount of gas that will be burned for a AUTH_CREATE.
|
||||||
|
GasChangeCallAuthCreation GasChangeReason = 15
|
||||||
|
|
||||||
// GasChangeIgnored is a special value that can be used to indicate that the gas change should be ignored as
|
// 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.
|
// it will be "manually" tracked by a direct emit of the gas change event.
|
||||||
|
|
|
||||||
|
|
@ -319,3 +319,14 @@ func enable6780(jt *JumpTable) {
|
||||||
maxStack: maxStack(1, 0),
|
maxStack: maxStack(1, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func enableXXXX(jt *JumpTable) {
|
||||||
|
jt[AUTH_CREATE] = &operation{
|
||||||
|
execute: opAuthCreate,
|
||||||
|
constantGas: params.AuthCreateGas,
|
||||||
|
dynamicGas: gasAuthCreate,
|
||||||
|
minStack: minStack(3, 1),
|
||||||
|
maxStack: maxStack(3, 1),
|
||||||
|
memorySize: memoryAuthCreate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ var (
|
||||||
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
||||||
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
|
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
|
||||||
ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
|
ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
|
||||||
|
ErrAuthCreateSigType = errors.New("auth_create signature type not found ")
|
||||||
|
|
||||||
// errStopToken is an internal token indicating interpreter loop termination,
|
// errStopToken is an internal token indicating interpreter loop termination,
|
||||||
// never returned to outside callers.
|
// never returned to outside callers.
|
||||||
|
|
|
||||||
|
|
@ -523,6 +523,36 @@ func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *
|
||||||
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
|
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (evm *EVM) AuthCreate(caller ContractRef, data []byte, gas uint64, endowment *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||||
|
if data[0] >= 4 {
|
||||||
|
return nil, common.Address{}, 0, ErrAuthCreateSigType
|
||||||
|
}
|
||||||
|
|
||||||
|
code := make([]byte, len(data)-65)
|
||||||
|
copy(code[:], data[65:])
|
||||||
|
codeAndHash := &codeAndHash{code: code}
|
||||||
|
|
||||||
|
sig := make([]byte, 65)
|
||||||
|
copy(sig, data)
|
||||||
|
|
||||||
|
msg := []byte{params.AuthCreateMagic}
|
||||||
|
msg = append(msg, common.LeftPadBytes(evm.chainConfig.ChainID.Bytes(), 32)...)
|
||||||
|
msg = append(msg, codeAndHash.Hash().Bytes()...)
|
||||||
|
msg = crypto.Keccak256(msg)
|
||||||
|
|
||||||
|
sig = append(sig[1:], sig[0])
|
||||||
|
pub, err := crypto.Ecrecover(msg, sig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, common.Address{}, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var eoaAddr common.Address
|
||||||
|
copy(eoaAddr[:], crypto.Keccak256(pub[1:])[12:])
|
||||||
|
|
||||||
|
evm.StateDB.SetNonce(eoaAddr, 0)
|
||||||
|
return evm.create(caller, codeAndHash, gas, endowment, eoaAddr, AUTH_CREATE)
|
||||||
|
}
|
||||||
|
|
||||||
// ChainConfig returns the environment's chain configuration
|
// ChainConfig returns the environment's chain configuration
|
||||||
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
|
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -484,3 +484,20 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gasAuthCreate(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
gas, err := memoryGasCost(mem, memorySize)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
size, overflow := stack.Back(2).Uint64WithOverflow()
|
||||||
|
if overflow || size > params.MaxInitCodeSize {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
// Since size <= params.MaxInitCodeSize, these multiplication cannot overflow
|
||||||
|
moreGas := (params.InitCodeWordGas + params.Keccak256WordGas) * ((size + 31) / 32)
|
||||||
|
if gas, overflow = math.SafeAdd(gas, moreGas); overflow {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
return gas, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -652,6 +652,40 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func opAuthCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
if interpreter.readOnly {
|
||||||
|
return nil, ErrWriteProtection
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
endowment = scope.Stack.pop()
|
||||||
|
offset, size = scope.Stack.pop(), scope.Stack.pop()
|
||||||
|
data = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
|
||||||
|
gas = scope.Contract.Gas
|
||||||
|
)
|
||||||
|
// Apply EIP150
|
||||||
|
gas -= gas / 64
|
||||||
|
scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallAuthCreation)
|
||||||
|
// reuse size int for stackvalue
|
||||||
|
stackvalue := size
|
||||||
|
res, addr, returnGas, suberr := interpreter.evm.AuthCreate(scope.Contract, data, gas, &endowment)
|
||||||
|
// Push item on the stack based on the returned error.
|
||||||
|
if suberr != nil {
|
||||||
|
stackvalue.Clear()
|
||||||
|
} else {
|
||||||
|
stackvalue.SetBytes(addr.Bytes())
|
||||||
|
}
|
||||||
|
scope.Stack.push(&stackvalue)
|
||||||
|
|
||||||
|
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||||
|
|
||||||
|
if suberr == ErrExecutionReverted {
|
||||||
|
interpreter.returnData = res // set REVERT data to return data buffer
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
interpreter.returnData = nil // clear dirty return data buffer
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
// Pop gas. The actual gas in interpreter.evm.callGasTemp.
|
// Pop gas. The actual gas in interpreter.evm.callGasTemp.
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,8 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||||
// If jump table was not initialised we set the default one.
|
// If jump table was not initialised we set the default one.
|
||||||
var table *JumpTable
|
var table *JumpTable
|
||||||
switch {
|
switch {
|
||||||
|
case evm.chainRules.IsPrague:
|
||||||
|
table = &pragueInstructionSet
|
||||||
case evm.chainRules.IsCancun:
|
case evm.chainRules.IsCancun:
|
||||||
table = &cancunInstructionSet
|
table = &cancunInstructionSet
|
||||||
case evm.chainRules.IsShanghai:
|
case evm.chainRules.IsShanghai:
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ var (
|
||||||
mergeInstructionSet = newMergeInstructionSet()
|
mergeInstructionSet = newMergeInstructionSet()
|
||||||
shanghaiInstructionSet = newShanghaiInstructionSet()
|
shanghaiInstructionSet = newShanghaiInstructionSet()
|
||||||
cancunInstructionSet = newCancunInstructionSet()
|
cancunInstructionSet = newCancunInstructionSet()
|
||||||
|
pragueInstructionSet = newPraugeInstructionSet()
|
||||||
)
|
)
|
||||||
|
|
||||||
// JumpTable contains the EVM opcodes supported at a given fork.
|
// JumpTable contains the EVM opcodes supported at a given fork.
|
||||||
|
|
@ -80,6 +81,12 @@ func validate(jt JumpTable) JumpTable {
|
||||||
return jt
|
return jt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newPraugeInstructionSet() JumpTable {
|
||||||
|
instructionSet := newCancunInstructionSet()
|
||||||
|
enableXXXX(&instructionSet) // EIP-XXXX AuthCreate
|
||||||
|
return validate(instructionSet)
|
||||||
|
}
|
||||||
|
|
||||||
func newCancunInstructionSet() JumpTable {
|
func newCancunInstructionSet() JumpTable {
|
||||||
instructionSet := newShanghaiInstructionSet()
|
instructionSet := newShanghaiInstructionSet()
|
||||||
enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode)
|
enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,10 @@ func memoryCreate2(stack *Stack) (uint64, bool) {
|
||||||
return calcMemSize64(stack.Back(1), stack.Back(2))
|
return calcMemSize64(stack.Back(1), stack.Back(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func memoryAuthCreate(stack *Stack) (uint64, bool) {
|
||||||
|
return calcMemSize64(stack.Back(1), stack.Back(2))
|
||||||
|
}
|
||||||
|
|
||||||
func memoryCall(stack *Stack) (uint64, bool) {
|
func memoryCall(stack *Stack) (uint64, bool) {
|
||||||
x, overflow := calcMemSize64(stack.Back(5), stack.Back(6))
|
x, overflow := calcMemSize64(stack.Back(5), stack.Back(6))
|
||||||
if overflow {
|
if overflow {
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ const (
|
||||||
RETURN OpCode = 0xf3
|
RETURN OpCode = 0xf3
|
||||||
DELEGATECALL OpCode = 0xf4
|
DELEGATECALL OpCode = 0xf4
|
||||||
CREATE2 OpCode = 0xf5
|
CREATE2 OpCode = 0xf5
|
||||||
|
AUTH_CREATE OpCode = 0xf6
|
||||||
|
|
||||||
STATICCALL OpCode = 0xfa
|
STATICCALL OpCode = 0xfa
|
||||||
REVERT OpCode = 0xfd
|
REVERT OpCode = 0xfd
|
||||||
|
|
@ -391,6 +392,7 @@ var opCodeToString = [256]string{
|
||||||
CALLCODE: "CALLCODE",
|
CALLCODE: "CALLCODE",
|
||||||
DELEGATECALL: "DELEGATECALL",
|
DELEGATECALL: "DELEGATECALL",
|
||||||
CREATE2: "CREATE2",
|
CREATE2: "CREATE2",
|
||||||
|
AUTH_CREATE: "AUTH_CREATE",
|
||||||
STATICCALL: "STATICCALL",
|
STATICCALL: "STATICCALL",
|
||||||
REVERT: "REVERT",
|
REVERT: "REVERT",
|
||||||
INVALID: "INVALID",
|
INVALID: "INVALID",
|
||||||
|
|
@ -548,6 +550,7 @@ var stringToOp = map[string]OpCode{
|
||||||
"LOG4": LOG4,
|
"LOG4": LOG4,
|
||||||
"CREATE": CREATE,
|
"CREATE": CREATE,
|
||||||
"CREATE2": CREATE2,
|
"CREATE2": CREATE2,
|
||||||
|
"AUTH_CREATE": AUTH_CREATE,
|
||||||
"CALL": CALL,
|
"CALL": CALL,
|
||||||
"RETURN": RETURN,
|
"RETURN": RETURN,
|
||||||
"CALLCODE": CALLCODE,
|
"CALLCODE": CALLCODE,
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ var (
|
||||||
GrayGlacierBlock: big.NewInt(0),
|
GrayGlacierBlock: big.NewInt(0),
|
||||||
ShanghaiTime: newUint64(0),
|
ShanghaiTime: newUint64(0),
|
||||||
CancunTime: newUint64(0),
|
CancunTime: newUint64(0),
|
||||||
|
PragueTime: newUint64(0),
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
TerminalTotalDifficultyPassed: true,
|
TerminalTotalDifficultyPassed: true,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ const (
|
||||||
LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
|
LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
|
||||||
CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction.
|
CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction.
|
||||||
Create2Gas uint64 = 32000 // Once per CREATE2 operation
|
Create2Gas uint64 = 32000 // Once per CREATE2 operation
|
||||||
|
AuthCreateGas uint64 = 32000 // Once per CREATE2 operation
|
||||||
SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation.
|
SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation.
|
||||||
MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
|
MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
|
||||||
|
|
||||||
|
|
@ -187,5 +188,6 @@ var (
|
||||||
// BeaconRootsAddress is the address where historical beacon roots are stored as per EIP-4788
|
// BeaconRootsAddress is the address where historical beacon roots are stored as per EIP-4788
|
||||||
BeaconRootsAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
|
BeaconRootsAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
|
||||||
// SystemAddress is where the system-transaction is sent from as per EIP-4788
|
// SystemAddress is where the system-transaction is sent from as per EIP-4788
|
||||||
SystemAddress = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
|
SystemAddress = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
|
||||||
|
AuthCreateMagic = byte(0x04)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue