mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +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
|
||||
// GasChangeCallFailedExecution is the burning of the remaining gas when the execution failed without a revert.
|
||||
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
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
|
||||
ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
|
||||
ErrAuthCreateSigType = errors.New("auth_create signature type not found ")
|
||||
|
||||
// errStopToken is an internal token indicating interpreter loop termination,
|
||||
// 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)
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
stack := scope.Stack
|
||||
// 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.
|
||||
var table *JumpTable
|
||||
switch {
|
||||
case evm.chainRules.IsPrague:
|
||||
table = &pragueInstructionSet
|
||||
case evm.chainRules.IsCancun:
|
||||
table = &cancunInstructionSet
|
||||
case evm.chainRules.IsShanghai:
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ var (
|
|||
mergeInstructionSet = newMergeInstructionSet()
|
||||
shanghaiInstructionSet = newShanghaiInstructionSet()
|
||||
cancunInstructionSet = newCancunInstructionSet()
|
||||
pragueInstructionSet = newPraugeInstructionSet()
|
||||
)
|
||||
|
||||
// JumpTable contains the EVM opcodes supported at a given fork.
|
||||
|
|
@ -80,6 +81,12 @@ func validate(jt JumpTable) JumpTable {
|
|||
return jt
|
||||
}
|
||||
|
||||
func newPraugeInstructionSet() JumpTable {
|
||||
instructionSet := newCancunInstructionSet()
|
||||
enableXXXX(&instructionSet) // EIP-XXXX AuthCreate
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
||||
func newCancunInstructionSet() JumpTable {
|
||||
instructionSet := newShanghaiInstructionSet()
|
||||
enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ func memoryCreate2(stack *Stack) (uint64, bool) {
|
|||
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) {
|
||||
x, overflow := calcMemSize64(stack.Back(5), stack.Back(6))
|
||||
if overflow {
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ const (
|
|||
RETURN OpCode = 0xf3
|
||||
DELEGATECALL OpCode = 0xf4
|
||||
CREATE2 OpCode = 0xf5
|
||||
AUTH_CREATE OpCode = 0xf6
|
||||
|
||||
STATICCALL OpCode = 0xfa
|
||||
REVERT OpCode = 0xfd
|
||||
|
|
@ -391,6 +392,7 @@ var opCodeToString = [256]string{
|
|||
CALLCODE: "CALLCODE",
|
||||
DELEGATECALL: "DELEGATECALL",
|
||||
CREATE2: "CREATE2",
|
||||
AUTH_CREATE: "AUTH_CREATE",
|
||||
STATICCALL: "STATICCALL",
|
||||
REVERT: "REVERT",
|
||||
INVALID: "INVALID",
|
||||
|
|
@ -548,6 +550,7 @@ var stringToOp = map[string]OpCode{
|
|||
"LOG4": LOG4,
|
||||
"CREATE": CREATE,
|
||||
"CREATE2": CREATE2,
|
||||
"AUTH_CREATE": AUTH_CREATE,
|
||||
"CALL": CALL,
|
||||
"RETURN": RETURN,
|
||||
"CALLCODE": CALLCODE,
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ var (
|
|||
GrayGlacierBlock: big.NewInt(0),
|
||||
ShanghaiTime: newUint64(0),
|
||||
CancunTime: newUint64(0),
|
||||
PragueTime: newUint64(0),
|
||||
TerminalTotalDifficulty: big.NewInt(0),
|
||||
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.
|
||||
CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction.
|
||||
Create2Gas uint64 = 32000 // Once per CREATE2 operation
|
||||
AuthCreateGas uint64 = 32000 // Once per CREATE2 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.
|
||||
|
||||
|
|
@ -188,4 +189,5 @@ var (
|
|||
BeaconRootsAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
|
||||
// SystemAddress is where the system-transaction is sent from as per EIP-4788
|
||||
SystemAddress = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
|
||||
AuthCreateMagic = byte(0x04)
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue