diff --git a/core/vm/eips.go b/core/vm/eips.go index c229dd25aa..afa8c37b06 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -256,6 +256,21 @@ func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by return nil, nil } +// opBlobHash implements the BLOBHASH opcode +func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + index := scope.Stack.peek() + // xdc chain have no blob hash, so len(interpreter.evm.TxContext.BlobHashes) is always 0 + // and index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) is always false + // if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) { + // blobHash := interpreter.evm.TxContext.BlobHashes[index.Uint64()] + // index.SetBytes32(blobHash[:]) + // } else { + // index.Clear() + // } + index.Clear() + return nil, nil +} + // opBlobBaseFee implements BLOBBASEFEE opcode func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { blobBaseFee := new(uint256.Int) @@ -263,6 +278,16 @@ func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) return nil, nil } +// enable4844 applies EIP-4844 (BLOBHASH opcode) +func enable4844(jt *JumpTable) { + jt[BLOBHASH] = &operation{ + execute: opBlobHash, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + } +} + // enable7516 applies EIP-7516 (BLOBBASEFEE opcode) func enable7516(jt *JumpTable) { jt[BLOBBASEFEE] = &operation{ diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index b432a2c8b5..8b9356d566 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -756,6 +756,48 @@ func TestRandom(t *testing.T) { } } +func TestBlobHash(t *testing.T) { + type testcase struct { + name string + idx uint64 + expect common.Hash + hashes []common.Hash + } + var ( + zero = common.Hash{0} + one = common.Hash{1} + two = common.Hash{2} + three = common.Hash{3} + ) + for _, tt := range []testcase{ + {name: "[{1}]", idx: 0, expect: zero, hashes: []common.Hash{one}}, + {name: "[1,{2},3]", idx: 2, expect: zero, hashes: []common.Hash{one, two, three}}, + {name: "out-of-bounds (empty)", idx: 10, expect: zero, hashes: []common.Hash{}}, + {name: "out-of-bounds", idx: 25, expect: zero, hashes: []common.Hash{one, two, three}}, + {name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil}, + } { + var ( + evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{}) + stack = newstack() + pc = uint64(0) + ) + // evm.SetTxContext(TxContext{BlobHashes: tt.hashes}) + stack.push(uint256.NewInt(tt.idx)) + opBlobHash(&pc, evm.interpreter, &ScopeContext{nil, stack, nil}) + if len(stack.data) != 1 { + t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data)) + } + actual := stack.pop() + expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes())) + if overflow { + t.Errorf("Testcase %v: invalid overflow", tt.name) + } + if actual.Cmp(expected) != 0 { + t.Errorf("Testcase %v: expected %x, got %x", tt.name, expected, actual) + } + } +} + func TestOpMCopy(t *testing.T) { // Test cases from https://eips.ethereum.org/EIPS/eip-5656#test-cases for i, tc := range []struct { diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 667778e73a..60fe63ef4f 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -82,6 +82,7 @@ func validate(jt JumpTable) JumpTable { func newCancunInstructionSet() JumpTable { instructionSet := newEip1559InstructionSet() + enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode) enable7516(&instructionSet) // EIP-7516 (BLOBBASEFEE opcode) enable1153(&instructionSet) // EIP-1153 "Transient Storage" enable5656(&instructionSet) // EIP-5656 (MCOPY opcode) diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 75a0e31d41..66b429079d 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -100,6 +100,7 @@ const ( CHAINID OpCode = 0x46 SELFBALANCE OpCode = 0x47 BASEFEE OpCode = 0x48 + BLOBHASH OpCode = 0x49 BLOBBASEFEE OpCode = 0x4a ) @@ -285,6 +286,7 @@ var opCodeToString = [256]string{ CHAINID: "CHAINID", SELFBALANCE: "SELFBALANCE", BASEFEE: "BASEFEE", + BLOBHASH: "BLOBHASH", BLOBBASEFEE: "BLOBBASEFEE", // 0x50 range - 'storage' and execution. @@ -460,6 +462,7 @@ var stringToOp = map[string]OpCode{ "GASLIMIT": GASLIMIT, "SELFBALANCE": SELFBALANCE, "BASEFEE": BASEFEE, + "BLOBHASH": BLOBHASH, "BLOBBASEFEE": BLOBBASEFEE, "POP": POP, "MLOAD": MLOAD,