mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 11:20:45 +00:00
f(eip-8141): add opcodes
This commit is contained in:
parent
23c6a6c174
commit
0b11863ec4
6 changed files with 440 additions and 0 deletions
|
|
@ -38,6 +38,7 @@ var activators = map[int]func(*JumpTable){
|
||||||
2200: enable2200,
|
2200: enable2200,
|
||||||
1884: enable1884,
|
1884: enable1884,
|
||||||
1344: enable1344,
|
1344: enable1344,
|
||||||
|
8141: enable8141,
|
||||||
1153: enable1153,
|
1153: enable1153,
|
||||||
4762: enable4762,
|
4762: enable4762,
|
||||||
7702: enable7702,
|
7702: enable7702,
|
||||||
|
|
@ -579,3 +580,37 @@ func enable7702(jt *JumpTable) {
|
||||||
jt[STATICCALL].dynamicGas = gasStaticCallEIP7702
|
jt[STATICCALL].dynamicGas = gasStaticCallEIP7702
|
||||||
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP7702
|
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP7702
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func enable8141(jt *JumpTable) {
|
||||||
|
jt[APPROVE] = &operation{
|
||||||
|
execute: opApprove,
|
||||||
|
constantGas: 0,
|
||||||
|
dynamicGas: gasApprove,
|
||||||
|
minStack: minStack(3, 0),
|
||||||
|
maxStack: maxStack(3, 0),
|
||||||
|
memorySize: memoryApprove,
|
||||||
|
}
|
||||||
|
|
||||||
|
jt[TXPARAMLOAD] = &operation{
|
||||||
|
execute: opTxParamLoad,
|
||||||
|
constantGas: GasFastestStep,
|
||||||
|
minStack: minStack(3, 1),
|
||||||
|
maxStack: maxStack(3, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
jt[TXPARAMSIZE] = &operation{
|
||||||
|
execute: opTxParamSize,
|
||||||
|
constantGas: GasQuickStep,
|
||||||
|
minStack: minStack(2, 1),
|
||||||
|
maxStack: maxStack(2, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
jt[TXPARAMCOPY] = &operation{
|
||||||
|
execute: opTxParamCopy,
|
||||||
|
constantGas: GasFastestStep,
|
||||||
|
dynamicGas: gasTxParamCopy,
|
||||||
|
minStack: minStack(5, 0),
|
||||||
|
maxStack: maxStack(5, 0),
|
||||||
|
memorySize: memoryTxParamCopy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,36 @@ type EVM struct {
|
||||||
|
|
||||||
readOnly bool // Whether to throw on stateful modifications
|
readOnly bool // Whether to throw on stateful modifications
|
||||||
returnData []byte // Last CALL's return data for subsequent reuse
|
returnData []byte // Last CALL's return data for subsequent reuse
|
||||||
|
|
||||||
|
// FrameTxContext holds frame transaction state, set during frame tx execution.
|
||||||
|
FrameTxCtx *FrameTxContext
|
||||||
|
}
|
||||||
|
|
||||||
|
type FrameTxContext struct {
|
||||||
|
Sender common.Address
|
||||||
|
Frames []FrameInfo
|
||||||
|
FrameStatuses []uint8
|
||||||
|
SenderApproved bool
|
||||||
|
PayerApproved bool
|
||||||
|
Payer common.Address
|
||||||
|
SigHash common.Hash
|
||||||
|
CurrentFrame int
|
||||||
|
Nonce uint64
|
||||||
|
GasTipCap *big.Int
|
||||||
|
GasFeeCap *big.Int
|
||||||
|
TxFee *big.Int
|
||||||
|
ApproveCalledInFrame bool
|
||||||
|
|
||||||
|
BlobFeeCap *big.Int
|
||||||
|
BlobVersionedHashes []common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrameInfo holds the definition of a single frame within a FrameTx.
|
||||||
|
type FrameInfo struct {
|
||||||
|
Mode uint8
|
||||||
|
Target common.Address
|
||||||
|
GasLimit uint64
|
||||||
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEVM constructs an EVM instance with the supplied block context, state
|
// NewEVM constructs an EVM instance with the supplied block context, state
|
||||||
|
|
@ -144,6 +174,8 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
|
||||||
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
case evm.chainRules.IsBogota:
|
||||||
|
evm.table = &bogotaInstructionSet
|
||||||
case evm.chainRules.IsOsaka:
|
case evm.chainRules.IsOsaka:
|
||||||
evm.table = &osakaInstructionSet
|
evm.table = &osakaInstructionSet
|
||||||
case evm.chainRules.IsVerkle:
|
case evm.chainRules.IsVerkle:
|
||||||
|
|
|
||||||
|
|
@ -1144,3 +1144,344 @@ func makeDup(size int) executionFunc {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 8141
|
||||||
|
|
||||||
|
func getTxParamData(evm *EVM, ftx *FrameTxContext, selector, frameIdx uint64) ([]byte, bool) {
|
||||||
|
switch selector {
|
||||||
|
|
||||||
|
case 0x00: // tx type = 6
|
||||||
|
val := new(uint256.Int).SetUint64(6)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x01: // nonce
|
||||||
|
val := new(uint256.Int).SetUint64(ftx.Nonce)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x02: // sender (left-padded to 32 bytes)
|
||||||
|
return common.LeftPadBytes(ftx.Sender.Bytes(), 32), true
|
||||||
|
|
||||||
|
case 0x03: // max_priority_fee_per_gas
|
||||||
|
val, _ := uint256.FromBig(ftx.GasTipCap)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x04: // max_fee_per_gas
|
||||||
|
val, _ := uint256.FromBig(ftx.GasFeeCap)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x05: // max_fee_per_blob_gas
|
||||||
|
if ftx.BlobFeeCap == nil {
|
||||||
|
b32 := new(uint256.Int).Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
}
|
||||||
|
val, _ := uint256.FromBig(ftx.BlobFeeCap)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x06: // max cost
|
||||||
|
val, _ := uint256.FromBig(ftx.TxFee)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x07: // len(blob_versioned_hashes)
|
||||||
|
count := uint64(len(ftx.BlobVersionedHashes))
|
||||||
|
val := new(uint256.Int).SetUint64(count)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x08: // compute_sig_hash(tx)
|
||||||
|
return ftx.SigHash[:], true
|
||||||
|
|
||||||
|
case 0x09: // len(frames)
|
||||||
|
val := new(uint256.Int).SetUint64(uint64(len(ftx.Frames)))
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x10: // current frame index
|
||||||
|
if ftx.CurrentFrame < 0 {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
val := new(uint256.Int).SetUint64(uint64(ftx.CurrentFrame))
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x11: // frame[index].target
|
||||||
|
if int(frameIdx) >= len(ftx.Frames) {
|
||||||
|
return nil, false // TxParamOutOfBounds → exceptional halt
|
||||||
|
}
|
||||||
|
f := ftx.Frames[frameIdx]
|
||||||
|
if f.Target == (common.Address{}) {
|
||||||
|
// null target
|
||||||
|
return make([]byte, 32), true
|
||||||
|
}
|
||||||
|
return common.LeftPadBytes(f.Target.Bytes(), 32), true
|
||||||
|
|
||||||
|
case 0x12: // frame[index].data
|
||||||
|
// EELS:
|
||||||
|
// if index >= len(tx.frames): raise TxParamOutOfBounds
|
||||||
|
// if frame.mode == FRAME_MODE_VERIFY: return (b"", Uint(0))
|
||||||
|
// data = bytes(frame.data)
|
||||||
|
// return (data, Uint(len(data)))
|
||||||
|
if int(frameIdx) >= len(ftx.Frames) {
|
||||||
|
return nil, false // TxParamOutOfBounds
|
||||||
|
}
|
||||||
|
f := ftx.Frames[frameIdx]
|
||||||
|
if f.Mode == types.FrameModeVerify {
|
||||||
|
return []byte{}, true
|
||||||
|
}
|
||||||
|
return f.Data, true
|
||||||
|
|
||||||
|
case 0x13: // frame[index].gas_limit
|
||||||
|
if int(frameIdx) >= len(ftx.Frames) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
val := new(uint256.Int).SetUint64(ftx.Frames[frameIdx].GasLimit)
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x14: // frame[index].mode
|
||||||
|
if int(frameIdx) >= len(ftx.Frames) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
val := new(uint256.Int).SetUint64(uint64(ftx.Frames[frameIdx].Mode))
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
case 0x15: // frame[index].status
|
||||||
|
if int(frameIdx) >= len(ftx.Frames) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if int(frameIdx) >= ftx.CurrentFrame {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if int(frameIdx) >= len(ftx.FrameStatuses) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
val := new(uint256.Int).SetUint64(uint64(ftx.FrameStatuses[frameIdx]))
|
||||||
|
b32 := val.Bytes32()
|
||||||
|
return b32[:], true
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TXPARAMLOAD (0xB0)
|
||||||
|
// Stack: [selector, index, offset] → [value]
|
||||||
|
// Gas: GAS_VERY_LOW (3)
|
||||||
|
|
||||||
|
func opTxParamLoad(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
|
ftx := evm.FrameTxCtx
|
||||||
|
if ftx == nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
selector := scope.Stack.pop()
|
||||||
|
index := scope.Stack.pop()
|
||||||
|
offset := scope.Stack.pop()
|
||||||
|
data, ok := getTxParamData(evm, ftx, selector.Uint64(), index.Uint64())
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
var result [32]byte
|
||||||
|
offsetU64 := offset.Uint64()
|
||||||
|
if offsetU64 < uint64(len(data)) {
|
||||||
|
copy(result[:], data[offsetU64:])
|
||||||
|
}
|
||||||
|
scope.Stack.push(new(uint256.Int).SetBytes(result[:]))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TXPARAMSIZE (0xB1)
|
||||||
|
// Stack: [selector, index] → [size]
|
||||||
|
// Gas: GAS_BASE (2)
|
||||||
|
|
||||||
|
func opTxParamSize(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
|
ftx := evm.FrameTxCtx
|
||||||
|
if ftx == nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
selector := scope.Stack.pop()
|
||||||
|
index := scope.Stack.pop()
|
||||||
|
data, ok := getTxParamData(evm, ftx, selector.Uint64(), index.Uint64())
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(data))))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TXPARAMCOPY (0xB2)
|
||||||
|
// Stack: [selector, index, dest_offset, src_offset, length] → []
|
||||||
|
// Gas: GAS_VERY_LOW + GAS_VERY_LOW * words + memory_expansion
|
||||||
|
|
||||||
|
func opTxParamCopy(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
|
selector := scope.Stack.pop()
|
||||||
|
index := scope.Stack.pop()
|
||||||
|
memOffset := scope.Stack.pop()
|
||||||
|
dataOffset := scope.Stack.pop()
|
||||||
|
length := scope.Stack.pop()
|
||||||
|
lengthU64 := length.Uint64()
|
||||||
|
if lengthU64 == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
ftx := evm.FrameTxCtx
|
||||||
|
if ftx == nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
data, ok := getTxParamData(evm, ftx, selector.Uint64(), index.Uint64())
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
dataOffsetU64 := dataOffset.Uint64()
|
||||||
|
dataCopy := make([]byte, lengthU64)
|
||||||
|
if dataOffsetU64 < uint64(len(data)) {
|
||||||
|
end := dataOffsetU64 + lengthU64
|
||||||
|
if end > uint64(len(data)) {
|
||||||
|
end = uint64(len(data))
|
||||||
|
}
|
||||||
|
copy(dataCopy, data[dataOffsetU64:end])
|
||||||
|
}
|
||||||
|
scope.Memory.Set(memOffset.Uint64(), lengthU64, dataCopy)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// APPROVE (0xAA)
|
||||||
|
// Stack: [offset, length, scope] -> [] (terminates frame)
|
||||||
|
// Gas: GAS_ZERO + memory_expansion
|
||||||
|
|
||||||
|
func opApprove(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
|
offset := scope.Stack.pop()
|
||||||
|
length := scope.Stack.pop()
|
||||||
|
scp := scope.Stack.pop()
|
||||||
|
|
||||||
|
// GAS already charged + memory already extended by gasApprove()
|
||||||
|
ftx := evm.FrameTxCtx
|
||||||
|
if ftx == nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
// EELS: tx_approval = _get_frame_tx_approval(evm)
|
||||||
|
s := scp.Uint64()
|
||||||
|
if s > 2 {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
if ftx.CurrentFrame < 0 || ftx.CurrentFrame >= len(ftx.Frames) {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
frame := ftx.Frames[ftx.CurrentFrame]
|
||||||
|
|
||||||
|
var frameTarget common.Address
|
||||||
|
if frame.Target == (common.Address{}) {
|
||||||
|
frameTarget = ftx.Sender
|
||||||
|
} else {
|
||||||
|
frameTarget = frame.Target
|
||||||
|
}
|
||||||
|
|
||||||
|
if scope.Contract.Caller() != frameTarget {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
switch s {
|
||||||
|
|
||||||
|
case 0x0:
|
||||||
|
if ftx.SenderApproved {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
if scope.Contract.Caller() != ftx.Sender {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
ftx.SenderApproved = true
|
||||||
|
|
||||||
|
case 0x1:
|
||||||
|
if ftx.PayerApproved {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
if !ftx.SenderApproved {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
balance := evm.StateDB.GetBalance(frameTarget).ToBig()
|
||||||
|
if balance.Cmp(ftx.TxFee) < 0 {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
fee, _ := uint256.FromBig(ftx.TxFee)
|
||||||
|
evm.StateDB.SubBalance(frameTarget, fee, tracing.BalanceDecreaseGasBuy)
|
||||||
|
evm.StateDB.SetNonce(ftx.Sender, evm.StateDB.GetNonce(ftx.Sender)+1, tracing.NonceChangeEoACall)
|
||||||
|
ftx.PayerApproved = true
|
||||||
|
ftx.Payer = frameTarget
|
||||||
|
|
||||||
|
case 0x2:
|
||||||
|
if ftx.SenderApproved || ftx.PayerApproved {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
if scope.Contract.Caller() != ftx.Sender {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
balance := evm.StateDB.GetBalance(frameTarget).ToBig()
|
||||||
|
if balance.Cmp(ftx.TxFee) < 0 {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
fee, _ := uint256.FromBig(ftx.TxFee)
|
||||||
|
evm.StateDB.SubBalance(frameTarget, fee, tracing.BalanceDecreaseGasBuy)
|
||||||
|
evm.StateDB.SetNonce(ftx.Sender, evm.StateDB.GetNonce(ftx.Sender)+1, tracing.NonceChangeEoACall)
|
||||||
|
ftx.SenderApproved = true
|
||||||
|
ftx.PayerApproved = true
|
||||||
|
ftx.Payer = frameTarget
|
||||||
|
}
|
||||||
|
|
||||||
|
ftx.ApproveCalledInFrame = true
|
||||||
|
|
||||||
|
// Mirror opReturn
|
||||||
|
ret := scope.Memory.GetCopy(offset.Uint64(), length.Uint64())
|
||||||
|
return ret, errStopToken
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo(jvn): All these Memory extension and Gas Estimation verify correctness across EELS
|
||||||
|
|
||||||
|
// memoryApprove computes memory size for APPROVE dynamic gas.
|
||||||
|
func memoryApprove(stack *Stack) (uint64, bool) {
|
||||||
|
// Stack at this point (before pops): [offset, length, scope]
|
||||||
|
return calcMemSize64(stack.Back(0), stack.Back(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// gasApprove computes dynamic gas for APPROVE (memory expansion only).
|
||||||
|
// EELS: charge_gas(evm, GAS_ZERO + extend_memory.cost)
|
||||||
|
func gasApprove(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return memoryGasCost(mem, memorySize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// memoryTxParamCopy computes memory size for TXPARAMCOPY dynamic gas.
|
||||||
|
func memoryTxParamCopy(stack *Stack) (uint64, bool) {
|
||||||
|
// destOffset is Back(2), length is Back(4)
|
||||||
|
return calcMemSize64(stack.Back(2), stack.Back(4))
|
||||||
|
}
|
||||||
|
|
||||||
|
// gasTxParamCopy computes dynamic gas for TXPARAMCOPY.
|
||||||
|
func gasTxParamCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
gas, err := memoryGasCost(mem, memorySize)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
length := stack.Back(4)
|
||||||
|
words, overflow := length.Uint64WithOverflow()
|
||||||
|
if overflow {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
// words = ceil(length / 32)
|
||||||
|
wordSize := toWordSize(words)
|
||||||
|
copyGas := wordSize * params.CopyGas
|
||||||
|
// overflow check
|
||||||
|
if wordSize != 0 && copyGas/wordSize != params.CopyGas {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
total := gas + copyGas
|
||||||
|
if total < gas {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
return total, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ type StateDB interface {
|
||||||
|
|
||||||
GetTransientState(addr common.Address, key common.Hash) common.Hash
|
GetTransientState(addr common.Address, key common.Hash) common.Hash
|
||||||
SetTransientState(addr common.Address, key, value common.Hash)
|
SetTransientState(addr common.Address, key, value common.Hash)
|
||||||
|
ClearTransientStorage()
|
||||||
|
|
||||||
SelfDestruct(common.Address)
|
SelfDestruct(common.Address)
|
||||||
HasSelfDestructed(common.Address) bool
|
HasSelfDestructed(common.Address) bool
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ var (
|
||||||
verkleInstructionSet = newVerkleInstructionSet()
|
verkleInstructionSet = newVerkleInstructionSet()
|
||||||
pragueInstructionSet = newPragueInstructionSet()
|
pragueInstructionSet = newPragueInstructionSet()
|
||||||
osakaInstructionSet = newOsakaInstructionSet()
|
osakaInstructionSet = newOsakaInstructionSet()
|
||||||
|
bogotaInstructionSet = newBogotaInstructionSet()
|
||||||
)
|
)
|
||||||
|
|
||||||
// JumpTable contains the EVM opcodes supported at a given fork.
|
// JumpTable contains the EVM opcodes supported at a given fork.
|
||||||
|
|
@ -92,6 +93,12 @@ func newVerkleInstructionSet() JumpTable {
|
||||||
return validate(instructionSet)
|
return validate(instructionSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newBogotaInstructionSet() JumpTable {
|
||||||
|
instructionSet := newOsakaInstructionSet()
|
||||||
|
enable8141(&instructionSet) // EIP-7939 (CLZ opcode)
|
||||||
|
return validate(instructionSet)
|
||||||
|
}
|
||||||
|
|
||||||
func newOsakaInstructionSet() JumpTable {
|
func newOsakaInstructionSet() JumpTable {
|
||||||
instructionSet := newPragueInstructionSet()
|
instructionSet := newPragueInstructionSet()
|
||||||
enable7939(&instructionSet) // EIP-7939 (CLZ opcode)
|
enable7939(&instructionSet) // EIP-7939 (CLZ opcode)
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,18 @@ const (
|
||||||
LOG4
|
LOG4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 0xaa range - Frame Transaction opcodes.
|
||||||
|
const (
|
||||||
|
APPROVE OpCode = 0xaa //Approve execution/payment in VERIFY frame.
|
||||||
|
)
|
||||||
|
|
||||||
|
// 0xb0 range - transaction parameter opcodes.
|
||||||
|
const (
|
||||||
|
TXPARAMLOAD OpCode = 0xb0 // Load 32-byte word from tx parameter.
|
||||||
|
TXPARAMSIZE OpCode = 0xb1 // Get size of tx parameter.
|
||||||
|
TXPARAMCOPY OpCode = 0xb2 // Copy tx parameter data to memory.
|
||||||
|
)
|
||||||
|
|
||||||
// 0xd0 range - eof operations.
|
// 0xd0 range - eof operations.
|
||||||
const (
|
const (
|
||||||
DATALOAD OpCode = 0xd0
|
DATALOAD OpCode = 0xd0
|
||||||
|
|
@ -416,6 +428,14 @@ var opCodeToString = [256]string{
|
||||||
LOG3: "LOG3",
|
LOG3: "LOG3",
|
||||||
LOG4: "LOG4",
|
LOG4: "LOG4",
|
||||||
|
|
||||||
|
// 0xaa - opcodes.
|
||||||
|
APPROVE: "APPROVE",
|
||||||
|
|
||||||
|
// 0xb0 range - tx param opcodes.
|
||||||
|
TXPARAMLOAD: "TXPARAMLOAD",
|
||||||
|
TXPARAMSIZE: "TXPARAMSIZE",
|
||||||
|
TXPARAMCOPY: "TXPARAMCOPY",
|
||||||
|
|
||||||
// 0xd range - eof ops.
|
// 0xd range - eof ops.
|
||||||
DATALOAD: "DATALOAD",
|
DATALOAD: "DATALOAD",
|
||||||
DATALOADN: "DATALOADN",
|
DATALOADN: "DATALOADN",
|
||||||
|
|
@ -631,6 +651,10 @@ var stringToOp = map[string]OpCode{
|
||||||
"REVERT": REVERT,
|
"REVERT": REVERT,
|
||||||
"INVALID": INVALID,
|
"INVALID": INVALID,
|
||||||
"SELFDESTRUCT": SELFDESTRUCT,
|
"SELFDESTRUCT": SELFDESTRUCT,
|
||||||
|
"APPROVE": APPROVE,
|
||||||
|
"TXPARAMLOAD": TXPARAMLOAD,
|
||||||
|
"TXPARAMSIZE": TXPARAMSIZE,
|
||||||
|
"TXPARAMCOPY": TXPARAMCOPY,
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToOp finds the opcode whose name is stored in `str`.
|
// StringToOp finds the opcode whose name is stored in `str`.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue