Skip to content

Commit 599a398

Browse files
authored
Merge pull request #107 from Inphi/inphi/ecotone
Support the Ecotone upgrade
2 parents 54b996d + bac17d0 commit 599a398

9 files changed

+449
-22
lines changed

optimism/client_bedrock.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ type TxExtraInfo struct {
8989

9090
// parseBedrockBlock returns a [EthTypes.Header] and [rpcBedrockBlock] for a given block or a respective error.
9191
func (c *Client) parseBedrockBlock(raw *json.RawMessage) (
92-
*EthTypes.Header,
92+
*rpcHeader,
9393
*rpcBedrockBlock,
9494
error,
9595
) {
9696
// Decode bedrock header and transactions
97-
var head EthTypes.Header
97+
var head rpcHeader
9898
var body rpcBedrockBlock
9999
if err := json.Unmarshal(*raw, &head); err != nil {
100100
return nil, nil, err

optimism/client_bedrock_test.go

+21-17
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
RosettaTypes "github.com/coinbase/rosetta-sdk-go/types"
2626
"github.com/ethereum-optimism/optimism/l2geth/params"
2727
"github.com/ethereum-optimism/optimism/l2geth/rpc"
28+
"github.com/ethereum/go-ethereum/common"
2829
EthCommon "github.com/ethereum/go-ethereum/common"
2930
EthHexutil "github.com/ethereum/go-ethereum/common/hexutil"
3031
EthTypes "github.com/ethereum/go-ethereum/core/types"
@@ -131,23 +132,26 @@ func (testSuite *ClientBedrockTestSuite) TestParseBedrockBlock() {
131132
testSuite.NoError(json.Unmarshal(file, &correctHeader))
132133
// var correctBlock *rpcBedrockBlock
133134
// testSuite.NoError(json.Unmarshal(file, &correctBlock))
134-
expectedHeader := &EthTypes.Header{
135-
ParentHash: EthCommon.HexToHash("0x70a4f8a536e03c2bb46ceafeafabe4070c3ecf56039c70bc0b4a5584684f664a"),
136-
UncleHash: EthCommon.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
137-
Coinbase: EthCommon.HexToAddress("0x4200000000000000000000000000000000000011"),
138-
Root: EthCommon.HexToHash("0x64fc9af5be01af062cfd137cf1f2cfd78dd28dac15b499b227fb0e7183da4769"),
139-
TxHash: EthCommon.HexToHash("0xada45aa72d8206747ec7a2dcbaed701b921389ca9b8275a516e6fac044f23357"),
140-
ReceiptHash: EthCommon.HexToHash("0x7be5f73e807a2564853738e784008e499fd8498ce803d8c0b3a814c996840105"),
141-
Bloom: EthTypes.BytesToBloom(EthCommon.FromHex("0x000000000000000000000003001000000001100000002000000002000000001002108040000000000000020000000000000000000204000400000000002000080040210000000000000080084000000000000040000100000008000000000000100020000000002000000000200009000000000000000000000000100000002000204000080000000000000008000008000100000000a2000800020000000000020000000000000000000000000000000400000000000000408000000000000004000002000000000000000000024800000000000000004010010001000000000010200000005000008000040000000000000000000000000000000800800000")),
142-
Difficulty: correctHeader.Difficulty,
143-
Number: convertBigInt("0x4c5836"),
144-
GasLimit: convertBigInt("0x17d7840").Uint64(),
145-
GasUsed: convertBigInt("0x4a853").Uint64(),
146-
Time: convertBigInt("0x63dd1ad0").Uint64(),
147-
Extra: []byte{},
148-
MixDigest: EthCommon.HexToHash("0x11bca9946ac51ed6451e9182f41b3513d27839aad5e102aead7b1f7f5f55bbdf"),
149-
Nonce: EthTypes.BlockNonce{},
150-
BaseFee: big.NewInt(49),
135+
expectedHeader := &rpcHeader{
136+
Header: EthTypes.Header{
137+
ParentHash: EthCommon.HexToHash("0x70a4f8a536e03c2bb46ceafeafabe4070c3ecf56039c70bc0b4a5584684f664a"),
138+
UncleHash: EthCommon.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
139+
Coinbase: EthCommon.HexToAddress("0x4200000000000000000000000000000000000011"),
140+
Root: EthCommon.HexToHash("0x64fc9af5be01af062cfd137cf1f2cfd78dd28dac15b499b227fb0e7183da4769"),
141+
TxHash: EthCommon.HexToHash("0xada45aa72d8206747ec7a2dcbaed701b921389ca9b8275a516e6fac044f23357"),
142+
ReceiptHash: EthCommon.HexToHash("0x7be5f73e807a2564853738e784008e499fd8498ce803d8c0b3a814c996840105"),
143+
Bloom: EthTypes.BytesToBloom(EthCommon.FromHex("0x000000000000000000000003001000000001100000002000000002000000001002108040000000000000020000000000000000000204000400000000002000080040210000000000000080084000000000000040000100000008000000000000100020000000002000000000200009000000000000000000000000100000002000204000080000000000000008000008000100000000a2000800020000000000020000000000000000000000000000000400000000000000408000000000000004000002000000000000000000024800000000000000004010010001000000000010200000005000008000040000000000000000000000000000000800800000")),
144+
Difficulty: correctHeader.Difficulty,
145+
Number: convertBigInt("0x4c5836"),
146+
GasLimit: convertBigInt("0x17d7840").Uint64(),
147+
GasUsed: convertBigInt("0x4a853").Uint64(),
148+
Time: convertBigInt("0x63dd1ad0").Uint64(),
149+
Extra: []byte{},
150+
MixDigest: EthCommon.HexToHash("0x11bca9946ac51ed6451e9182f41b3513d27839aad5e102aead7b1f7f5f55bbdf"),
151+
Nonce: EthTypes.BlockNonce{},
152+
BaseFee: big.NewInt(49),
153+
},
154+
Hash: common.HexToHash("0x4503cbd671b3ca292e9f54998b2d566b705a32a178fc467f311c79b43e8e1774"),
151155
}
152156
expectedBlockHash := EthCommon.HexToHash("0x4503cbd671b3ca292e9f54998b2d566b705a32a178fc467f311c79b43e8e1774")
153157

optimism/client_blocks_bedrock_handler.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ import (
2222
"math/big"
2323

2424
RosettaTypes "github.com/coinbase/rosetta-sdk-go/types"
25-
"github.com/ethereum-optimism/optimism/l2geth/common/hexutil"
2625
EthCommon "github.com/ethereum/go-ethereum/common"
26+
"github.com/ethereum/go-ethereum/common/hexutil"
2727
EthTypes "github.com/ethereum/go-ethereum/core/types"
2828
"github.com/ethereum/go-ethereum/crypto"
2929
)
@@ -131,7 +131,7 @@ func (ec *Client) getParsedBedrockBlock(
131131
return &RosettaTypes.Block{
132132
BlockIdentifier: &RosettaTypes.BlockIdentifier{
133133
Index: head.Number.Int64(),
134-
Hash: head.Hash().String(),
134+
Hash: head.Hash.String(),
135135
},
136136
ParentBlockIdentifier: &RosettaTypes.BlockIdentifier{
137137
Hash: head.ParentHash.Hex(),
@@ -146,7 +146,7 @@ func (ec *Client) getParsedBedrockBlock(
146146
// populateBedrockTransaction populates a Rosetta transaction from a bedrock transaction.
147147
func (ec *Client) populateBedrockTransaction(
148148
ctx context.Context,
149-
head *EthTypes.Header,
149+
head *rpcHeader,
150150
tx *bedrockTransaction,
151151
) (*RosettaTypes.Transaction, error) {
152152
ops, err := ec.ParseOps(tx)

optimism/client_ecotone_test.go

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright 2023 Coinbase, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package optimism
16+
17+
import (
18+
"context"
19+
"encoding/json"
20+
"math/big"
21+
"os"
22+
"testing"
23+
24+
RosettaTypes "github.com/coinbase/rosetta-sdk-go/types"
25+
"github.com/ethereum-optimism/optimism/l2geth/params"
26+
"github.com/ethereum-optimism/optimism/l2geth/rpc"
27+
EthCommon "github.com/ethereum/go-ethereum/common"
28+
mocks "github.com/inphi/optimism-rosetta/mocks/optimism"
29+
"github.com/stretchr/testify/mock"
30+
"github.com/stretchr/testify/suite"
31+
"golang.org/x/sync/semaphore"
32+
)
33+
34+
type ClientEcotoneTestSuite struct {
35+
suite.Suite
36+
37+
mockJSONRPC *mocks.JSONRPC
38+
mockGraphQL *mocks.GraphQL
39+
mockCurrencyFetcher *mocks.CurrencyFetcher
40+
}
41+
42+
func (t *ClientEcotoneTestSuite) MockJSONRPC() *mocks.JSONRPC {
43+
return t.mockJSONRPC
44+
}
45+
46+
func TestClientEcotone(t *testing.T) {
47+
suite.Run(t, new(ClientEcotoneTestSuite))
48+
}
49+
50+
func (testSuite *ClientEcotoneTestSuite) SetupTest() {
51+
testSuite.mockJSONRPC = &mocks.JSONRPC{}
52+
testSuite.mockGraphQL = &mocks.GraphQL{}
53+
testSuite.mockCurrencyFetcher = &mocks.CurrencyFetcher{}
54+
}
55+
56+
func (testSuite *ClientEcotoneTestSuite) TestEcotoneBlock() {
57+
c := &Client{
58+
c: testSuite.mockJSONRPC,
59+
g: testSuite.mockGraphQL,
60+
currencyFetcher: testSuite.mockCurrencyFetcher,
61+
tc: testBedrockTraceConfig,
62+
p: params.TestnetChainConfig,
63+
traceSemaphore: semaphore.NewWeighted(100),
64+
filterTokens: false,
65+
bedrockBlock: big.NewInt(0),
66+
}
67+
68+
ctx := context.Background()
69+
testSuite.mockJSONRPC.On(
70+
"CallContext",
71+
ctx,
72+
mock.Anything,
73+
"eth_getBlockByNumber",
74+
"latest",
75+
true,
76+
).Return(
77+
nil,
78+
).Run(
79+
func(args mock.Arguments) {
80+
r := args.Get(1).(*json.RawMessage)
81+
file, err := os.ReadFile("testdata/sepolia_ecotone_block_4089330.json")
82+
testSuite.NoError(err)
83+
*r = json.RawMessage(file)
84+
},
85+
).Once()
86+
testSuite.mockJSONRPC.On(
87+
"CallContext",
88+
ctx,
89+
mock.Anything,
90+
"eth_getBlockByNumber",
91+
[]interface{}{"latest", true},
92+
).Return(
93+
nil,
94+
).Run(
95+
func(args mock.Arguments) {
96+
r := args.Get(1).(*json.RawMessage)
97+
file, err := os.ReadFile("testdata/sepolia_ecotone_block_4089330.json")
98+
testSuite.NoError(err)
99+
*r = json.RawMessage(file)
100+
},
101+
).Once()
102+
103+
tx1 := EthCommon.HexToHash("0xd62fb327dc8df4e8f6a1ad70c9ff03099d2f85c75b9d943d5d6885e62be31069")
104+
105+
// Execute the transaction trace
106+
mockTraceTransaction(ctx, testSuite, "testdata/sepolia_ecotone_tx_trace_5003318_1.json")
107+
mockGetEcotoneTransactionReceipt(ctx, testSuite, []EthCommon.Hash{tx1}, []string{"testdata/sepolia_ecotone_tx_receipt_4089330_1.json"})
108+
109+
correctRaw, err := os.ReadFile("testdata/sepolia_ecotone_block_response_4089330.json")
110+
testSuite.NoError(err)
111+
var correct *RosettaTypes.BlockResponse
112+
testSuite.NoError(json.Unmarshal(correctRaw, &correct))
113+
114+
// Fetch the latest block and validate
115+
resp, err := c.Block(ctx, nil)
116+
testSuite.NoError(err)
117+
testSuite.Equal(correct.Block, resp)
118+
}
119+
120+
func mockGetEcotoneTransactionReceipt(ctx context.Context, testSuite *ClientEcotoneTestSuite, txhashes []EthCommon.Hash, txFileData []string) {
121+
testSuite.Equal(len(txhashes), len(txFileData))
122+
numReceipts := len(txhashes)
123+
testSuite.mockJSONRPC.On(
124+
"BatchCallContext",
125+
ctx,
126+
mock.MatchedBy(func(rpcs []rpc.BatchElem) bool {
127+
return len(rpcs) == numReceipts && rpcs[0].Method == "eth_getTransactionReceipt"
128+
}),
129+
).Return(
130+
nil,
131+
).Run(
132+
func(args mock.Arguments) {
133+
r := args.Get(1).([]rpc.BatchElem)
134+
testSuite.Len(r, numReceipts)
135+
for i := range txhashes {
136+
testSuite.Equal(
137+
txhashes[i].Hex(),
138+
r[i].Args[0],
139+
)
140+
file, err := os.ReadFile(txFileData[i])
141+
testSuite.NoError(err)
142+
*(r[i].Result.(*json.RawMessage)) = json.RawMessage(file)
143+
}
144+
},
145+
).Once()
146+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"hash": "0xf1e1eb6735860e60bfbb19fb9c3a3ade2a1e2fc51bc5549e47939aac30bc8092",
3+
"parentHash": "0x2ea5dc85c900443e6ee9615876a413ef3f7f800792886e646f03cae258e30dc4",
4+
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
5+
"miner": "0x4200000000000000000000000000000000000011",
6+
"stateRoot": "0x07697115aeffa8bcf76bc90edf9c8c6998b5bb87d8049f631c90db75a8dbe6d9",
7+
"transactionsRoot": "0xfc7fc33824e66da578de2aafbafc1d175301b8c36b56ff8ad0817b4d3a77f039",
8+
"receiptsRoot": "0xad690e8a5ce0df6f1d9554901d531a5945ed233d6408420decaff8950fefdb0d",
9+
"number": "0x3e65f2",
10+
"gasUsed": "0xb705",
11+
"gasLimit": "0x1c9c380",
12+
"extraData": "0x",
13+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
14+
"timestamp": "0x6553a790",
15+
"difficulty": "0x0",
16+
"totalDifficulty": "0x0",
17+
"sealFields": [],
18+
"uncles": [],
19+
"transactions": [
20+
{
21+
"hash": "0xd62fb327dc8df4e8f6a1ad70c9ff03099d2f85c75b9d943d5d6885e62be31069",
22+
"nonce": "0x3e65f1",
23+
"blockHash": "0xf1e1eb6735860e60bfbb19fb9c3a3ade2a1e2fc51bc5549e47939aac30bc8092",
24+
"blockNumber": "0x3e65f2",
25+
"transactionIndex": "0x0",
26+
"from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
27+
"to": "0x4200000000000000000000000000000000000015",
28+
"value": "0x0",
29+
"gasPrice": "0x0",
30+
"gas": "0xf4240",
31+
"input": "0x015d8eb90000000000000000000000000000000000000000000000000000000000479ddd000000000000000000000000000000000000000000000000000000006553a73c000000000000000000000000000000000000000000000000000000000000000e68ac0d50607ac5d009c560fafb10d165a445811924a4a1cdaa93cd85ab5fff0300000000000000000000000000000000000000000000000000000000000000030000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000a6fe0",
32+
"v": "0x0",
33+
"r": "0x0",
34+
"s": "0x0",
35+
"sourceHash": "0xb11d5cce1ac3d8ec545e49a73cc9111cf05c00f07cddffeedb777a0825bb26c6",
36+
"mint": "0x0",
37+
"isSystemTx": false,
38+
"type": "0x7e",
39+
"depositReceiptVersion": "0x1"
40+
}
41+
],
42+
"size": "0x387",
43+
"mixHash": "0x56c69fea1a23e350c8014171a2819ff4cc84a27272bae1a866d58b4ced467024",
44+
"nonce": "0x0000000000000000",
45+
"baseFeePerGas": "0x32",
46+
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
47+
"withdrawals": []
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"block": {
3+
"block_identifier": {
4+
"index": 4089330,
5+
"hash": "0xf1e1eb6735860e60bfbb19fb9c3a3ade2a1e2fc51bc5549e47939aac30bc8092"
6+
},
7+
"parent_block_identifier": {
8+
"index": 4089329,
9+
"hash": "0x2ea5dc85c900443e6ee9615876a413ef3f7f800792886e646f03cae258e30dc4"
10+
},
11+
"timestamp": 1699981200000,
12+
"transactions": [
13+
{
14+
"transaction_identifier": {
15+
"hash": "0xd62fb327dc8df4e8f6a1ad70c9ff03099d2f85c75b9d943d5d6885e62be31069"
16+
},
17+
"operations": [
18+
{
19+
"operation_identifier": {
20+
"index": 0
21+
},
22+
"type": "CALL",
23+
"status": "SUCCESS",
24+
"account": {
25+
"address": "0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001"
26+
},
27+
"amount": {
28+
"value": "0",
29+
"currency": {
30+
"symbol": "ETH",
31+
"decimals": 18
32+
}
33+
}
34+
}
35+
],
36+
"metadata": {
37+
"gas_limit": "0xf4240",
38+
"gas_price": "0x0",
39+
"receipt": {
40+
"GasPrice": 0,
41+
"GasUsed": 46853,
42+
"Logs": [],
43+
"RawMessage": {
44+
"blockHash": "0xf1e1eb6735860e60bfbb19fb9c3a3ade2a1e2fc51bc5549e47939aac30bc8092",
45+
"blockNumber": "0x3e65f2",
46+
"contractAddress": null,
47+
"cumulativeGasUsed": "0xb705",
48+
"depositNonce": "0x3e65f1",
49+
"depositReceiptVersion": "0x1",
50+
"effectiveGasPrice": "0x0",
51+
"from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
52+
"gasUsed": "0xb705",
53+
"logs": [],
54+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
55+
"status": "0x1",
56+
"to": "0x4200000000000000000000000000000000000015",
57+
"transactionHash": "0xd62fb327dc8df4e8f6a1ad70c9ff03099d2f85c75b9d943d5d6885e62be31069",
58+
"transactionIndex": "0x0",
59+
"type": "0x7e"
60+
},
61+
"TransactionFee": 0,
62+
"type": 126
63+
}
64+
}
65+
}
66+
]
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"transactionHash": "0xd62fb327dc8df4e8f6a1ad70c9ff03099d2f85c75b9d943d5d6885e62be31069",
3+
"transactionIndex": "0x0",
4+
"blockHash": "0xf1e1eb6735860e60bfbb19fb9c3a3ade2a1e2fc51bc5549e47939aac30bc8092",
5+
"blockNumber": "0x3e65f2",
6+
"from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
7+
"to": "0x4200000000000000000000000000000000000015",
8+
"cumulativeGasUsed": "0xb705",
9+
"gasUsed": "0xb705",
10+
"contractAddress": null,
11+
"logs": [],
12+
"status": "0x1",
13+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
14+
"type": "0x7e",
15+
"effectiveGasPrice": "0x0",
16+
"depositNonce": "0x3e65f1",
17+
"depositReceiptVersion": "0x1"
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
3+
"gas": "0xf4240",
4+
"gasUsed": "0xb705",
5+
"to": "0x4200000000000000000000000000000000000015",
6+
"input": "0x015d8eb90000000000000000000000000000000000000000000000000000000000479ddd000000000000000000000000000000000000000000000000000000006553a73c000000000000000000000000000000000000000000000000000000000000000e68ac0d50607ac5d009c560fafb10d165a445811924a4a1cdaa93cd85ab5fff0300000000000000000000000000000000000000000000000000000000000000030000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000a6fe0",
7+
"calls": [
8+
{
9+
"from": "0x4200000000000000000000000000000000000015",
10+
"gas": "0xe9a30",
11+
"gasUsed": "0x4a28",
12+
"to": "0xc0d3c0d3c0d3c0d3c0d3c0d3c0d3c0d3c0d30015",
13+
"input": "0x015d8eb90000000000000000000000000000000000000000000000000000000000479ddd000000000000000000000000000000000000000000000000000000006553a73c000000000000000000000000000000000000000000000000000000000000000e68ac0d50607ac5d009c560fafb10d165a445811924a4a1cdaa93cd85ab5fff0300000000000000000000000000000000000000000000000000000000000000030000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000a6fe0",
14+
"value": "0x0",
15+
"type": "DELEGATECALL"
16+
}
17+
],
18+
"value": "0x0",
19+
"type": "CALL"
20+
}

0 commit comments

Comments
 (0)