mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 10:50:44 +00:00
core/vm: update EIP-8024 - Missing immediate byte is now treated as 0x00 (#33614)
This PR updates the EIP-8024 implementation to match the latest spec clarification. --------- Co-authored-by: lightclient <lightclient@protonmail.com>
This commit is contained in:
parent
1022c7637d
commit
251b863107
2 changed files with 49 additions and 37 deletions
|
|
@ -973,11 +973,11 @@ func opDupN(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
code := scope.Contract.Code
|
code := scope.Contract.Code
|
||||||
i := *pc + 1
|
i := *pc + 1
|
||||||
|
|
||||||
// Ensure an immediate byte exists after DUPN
|
// If the immediate byte is missing, treat as 0x00 (same convention as PUSHn).
|
||||||
if i >= uint64(len(code)) {
|
var x byte
|
||||||
return nil, &ErrInvalidOpCode{opcode: INVALID}
|
if i < uint64(len(code)) {
|
||||||
|
x = code[i]
|
||||||
}
|
}
|
||||||
x := code[i]
|
|
||||||
|
|
||||||
// This range is excluded to preserve compatibility with existing opcodes.
|
// This range is excluded to preserve compatibility with existing opcodes.
|
||||||
if x > 90 && x < 128 {
|
if x > 90 && x < 128 {
|
||||||
|
|
@ -1000,11 +1000,11 @@ func opSwapN(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
code := scope.Contract.Code
|
code := scope.Contract.Code
|
||||||
i := *pc + 1
|
i := *pc + 1
|
||||||
|
|
||||||
// Ensure an immediate byte exists after SWAPN
|
// If the immediate byte is missing, treat as 0x00 (same convention as PUSHn).
|
||||||
if i >= uint64(len(code)) {
|
var x byte
|
||||||
return nil, &ErrInvalidOpCode{opcode: INVALID}
|
if i < uint64(len(code)) {
|
||||||
|
x = code[i]
|
||||||
}
|
}
|
||||||
x := code[i]
|
|
||||||
|
|
||||||
// This range is excluded to preserve compatibility with existing opcodes.
|
// This range is excluded to preserve compatibility with existing opcodes.
|
||||||
if x > 90 && x < 128 {
|
if x > 90 && x < 128 {
|
||||||
|
|
@ -1029,11 +1029,11 @@ func opExchange(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
code := scope.Contract.Code
|
code := scope.Contract.Code
|
||||||
i := *pc + 1
|
i := *pc + 1
|
||||||
|
|
||||||
// Ensure an immediate byte exists after EXCHANGE
|
// If the immediate byte is missing, treat as 0x00 (same convention as PUSHn).
|
||||||
if i >= uint64(len(code)) {
|
var x byte
|
||||||
return nil, &ErrInvalidOpCode{opcode: INVALID}
|
if i < uint64(len(code)) {
|
||||||
|
x = code[i]
|
||||||
}
|
}
|
||||||
x := code[i]
|
|
||||||
|
|
||||||
// This range is excluded both to preserve compatibility with existing opcodes
|
// This range is excluded both to preserve compatibility with existing opcodes
|
||||||
// and to keep decode_pair’s 16-aligned arithmetic mapping valid (0–79, 128–255).
|
// and to keep decode_pair’s 16-aligned arithmetic mapping valid (0–79, 128–255).
|
||||||
|
|
|
||||||
|
|
@ -1027,6 +1027,15 @@ func TestEIP8024_Execution(t *testing.T) {
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "DUPN_MISSING_IMMEDIATE",
|
||||||
|
codeHex: "60016000808080808080808080808080808080e6",
|
||||||
|
wantVals: []uint64{
|
||||||
|
1,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "SWAPN",
|
name: "SWAPN",
|
||||||
codeHex: "600160008080808080808080808080808080806002e700",
|
codeHex: "600160008080808080808080808080808080806002e700",
|
||||||
|
|
@ -1036,11 +1045,29 @@ func TestEIP8024_Execution(t *testing.T) {
|
||||||
2,
|
2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "SWAPN_MISSING_IMMEDIATE",
|
||||||
|
codeHex: "600160008080808080808080808080808080806002e7",
|
||||||
|
wantVals: []uint64{
|
||||||
|
1,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
2,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "EXCHANGE",
|
name: "EXCHANGE",
|
||||||
codeHex: "600060016002e801",
|
codeHex: "600060016002e801",
|
||||||
wantVals: []uint64{2, 0, 1},
|
wantVals: []uint64{2, 0, 1},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "EXCHANGE_MISSING_IMMEDIATE",
|
||||||
|
codeHex: "600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060016002e8",
|
||||||
|
wantVals: []uint64{
|
||||||
|
2,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "INVALID_SWAPN_LOW",
|
name: "INVALID_SWAPN_LOW",
|
||||||
codeHex: "e75b",
|
codeHex: "e75b",
|
||||||
|
|
@ -1092,21 +1119,6 @@ func TestEIP8024_Execution(t *testing.T) {
|
||||||
codeHex: "60016002e801", // (n,m)=(1,2), need 3 items, have 2
|
codeHex: "60016002e801", // (n,m)=(1,2), need 3 items, have 2
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "MISSING_IMMEDIATE_DUPN",
|
|
||||||
codeHex: "e6", // no operand
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MISSING_IMMEDIATE_SWAPN",
|
|
||||||
codeHex: "e7", // no operand
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MISSING_IMMEDIATE_EXCHANGE",
|
|
||||||
codeHex: "e8", // no operand
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "PC_INCREMENT",
|
name: "PC_INCREMENT",
|
||||||
codeHex: "600060006000e80115",
|
codeHex: "600060006000e80115",
|
||||||
|
|
@ -1123,25 +1135,25 @@ func TestEIP8024_Execution(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
for pc < uint64(len(code)) && err == nil {
|
for pc < uint64(len(code)) && err == nil {
|
||||||
op := code[pc]
|
op := code[pc]
|
||||||
switch op {
|
switch OpCode(op) {
|
||||||
case 0x00:
|
case STOP:
|
||||||
return
|
return
|
||||||
case 0x60:
|
case PUSH1:
|
||||||
_, err = opPush1(&pc, evm, scope)
|
_, err = opPush1(&pc, evm, scope)
|
||||||
case 0x80:
|
case DUP1:
|
||||||
dup1 := makeDup(1)
|
dup1 := makeDup(1)
|
||||||
_, err = dup1(&pc, evm, scope)
|
_, err = dup1(&pc, evm, scope)
|
||||||
case 0x56:
|
case JUMP:
|
||||||
_, err = opJump(&pc, evm, scope)
|
_, err = opJump(&pc, evm, scope)
|
||||||
case 0x5b:
|
case JUMPDEST:
|
||||||
_, err = opJumpdest(&pc, evm, scope)
|
_, err = opJumpdest(&pc, evm, scope)
|
||||||
case 0x15:
|
case ISZERO:
|
||||||
_, err = opIszero(&pc, evm, scope)
|
_, err = opIszero(&pc, evm, scope)
|
||||||
case 0xe6:
|
case DUPN:
|
||||||
_, err = opDupN(&pc, evm, scope)
|
_, err = opDupN(&pc, evm, scope)
|
||||||
case 0xe7:
|
case SWAPN:
|
||||||
_, err = opSwapN(&pc, evm, scope)
|
_, err = opSwapN(&pc, evm, scope)
|
||||||
case 0xe8:
|
case EXCHANGE:
|
||||||
_, err = opExchange(&pc, evm, scope)
|
_, err = opExchange(&pc, evm, scope)
|
||||||
default:
|
default:
|
||||||
err = &ErrInvalidOpCode{opcode: OpCode(op)}
|
err = &ErrInvalidOpCode{opcode: OpCode(op)}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue