Skip to content

Commit 98d222b

Browse files
committed
core/vm: BLOBHASH opcode 0x49 (ethereum#27356)
1 parent 4693a1a commit 98d222b

File tree

4 files changed

+71
-0
lines changed

4 files changed

+71
-0
lines changed

core/vm/eips.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,13 +256,38 @@ func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
256256
return nil, nil
257257
}
258258

259+
// opBlobHash implements the BLOBHASH opcode
260+
func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
261+
index := scope.Stack.peek()
262+
// xdc chain have no blob hash, so len(interpreter.evm.TxContext.BlobHashes) is always 0
263+
// and index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) is always false
264+
// if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) {
265+
// blobHash := interpreter.evm.TxContext.BlobHashes[index.Uint64()]
266+
// index.SetBytes32(blobHash[:])
267+
// } else {
268+
// index.Clear()
269+
// }
270+
index.Clear()
271+
return nil, nil
272+
}
273+
259274
// opBlobBaseFee implements BLOBBASEFEE opcode
260275
func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
261276
blobBaseFee := new(uint256.Int)
262277
scope.Stack.push(blobBaseFee)
263278
return nil, nil
264279
}
265280

281+
// enable4844 applies EIP-4844 (BLOBHASH opcode)
282+
func enable4844(jt *JumpTable) {
283+
jt[BLOBHASH] = &operation{
284+
execute: opBlobHash,
285+
constantGas: GasFastestStep,
286+
minStack: minStack(1, 1),
287+
maxStack: maxStack(1, 1),
288+
}
289+
}
290+
266291
// enable7516 applies EIP-7516 (BLOBBASEFEE opcode)
267292
func enable7516(jt *JumpTable) {
268293
jt[BLOBBASEFEE] = &operation{

core/vm/instructions_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,48 @@ func TestRandom(t *testing.T) {
755755
}
756756
}
757757

758+
func TestBlobHash(t *testing.T) {
759+
type testcase struct {
760+
name string
761+
idx uint64
762+
expect common.Hash
763+
hashes []common.Hash
764+
}
765+
var (
766+
zero = common.Hash{0}
767+
one = common.Hash{1}
768+
two = common.Hash{2}
769+
three = common.Hash{3}
770+
)
771+
for _, tt := range []testcase{
772+
{name: "[{1}]", idx: 0, expect: zero, hashes: []common.Hash{one}},
773+
{name: "[1,{2},3]", idx: 2, expect: zero, hashes: []common.Hash{one, two, three}},
774+
{name: "out-of-bounds (empty)", idx: 10, expect: zero, hashes: []common.Hash{}},
775+
{name: "out-of-bounds", idx: 25, expect: zero, hashes: []common.Hash{one, two, three}},
776+
{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
777+
} {
778+
var (
779+
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
780+
stack = newstack()
781+
pc = uint64(0)
782+
)
783+
// evm.SetTxContext(TxContext{BlobHashes: tt.hashes})
784+
stack.push(uint256.NewInt(tt.idx))
785+
opBlobHash(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
786+
if len(stack.data) != 1 {
787+
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
788+
}
789+
actual := stack.pop()
790+
expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes()))
791+
if overflow {
792+
t.Errorf("Testcase %v: invalid overflow", tt.name)
793+
}
794+
if actual.Cmp(expected) != 0 {
795+
t.Errorf("Testcase %v: expected %x, got %x", tt.name, expected, actual)
796+
}
797+
}
798+
}
799+
758800
func TestOpMCopy(t *testing.T) {
759801
// Test cases from https://eips.ethereum.org/EIPS/eip-5656#test-cases
760802
for i, tc := range []struct {

core/vm/jump_table.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ func validate(jt JumpTable) JumpTable {
8282

8383
func newCancunInstructionSet() JumpTable {
8484
instructionSet := newEip1559InstructionSet()
85+
enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode)
8586
enable7516(&instructionSet) // EIP-7516 (BLOBBASEFEE opcode)
8687
enable1153(&instructionSet) // EIP-1153 "Transient Storage"
8788
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)

core/vm/opcodes.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ const (
100100
CHAINID OpCode = 0x46
101101
SELFBALANCE OpCode = 0x47
102102
BASEFEE OpCode = 0x48
103+
BLOBHASH OpCode = 0x49
103104
BLOBBASEFEE OpCode = 0x4a
104105
)
105106

@@ -285,6 +286,7 @@ var opCodeToString = [256]string{
285286
CHAINID: "CHAINID",
286287
SELFBALANCE: "SELFBALANCE",
287288
BASEFEE: "BASEFEE",
289+
BLOBHASH: "BLOBHASH",
288290
BLOBBASEFEE: "BLOBBASEFEE",
289291

290292
// 0x50 range - 'storage' and execution.
@@ -460,6 +462,7 @@ var stringToOp = map[string]OpCode{
460462
"GASLIMIT": GASLIMIT,
461463
"SELFBALANCE": SELFBALANCE,
462464
"BASEFEE": BASEFEE,
465+
"BLOBHASH": BLOBHASH,
463466
"BLOBBASEFEE": BLOBBASEFEE,
464467
"POP": POP,
465468
"MLOAD": MLOAD,

0 commit comments

Comments
 (0)