github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/internal/ethapi/api_test.go (about) 1 // Copyright 2023 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package ethapi 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/ecdsa" 23 "crypto/sha256" 24 "encoding/json" 25 "errors" 26 "fmt" 27 "math/big" 28 "os" 29 "path/filepath" 30 "reflect" 31 "slices" 32 "testing" 33 "time" 34 35 "github.com/holiman/uint256" 36 "github.com/stretchr/testify/require" 37 38 "github.com/ethereum/go-ethereum" 39 "github.com/ethereum/go-ethereum/accounts" 40 "github.com/ethereum/go-ethereum/accounts/keystore" 41 "github.com/ethereum/go-ethereum/common" 42 "github.com/ethereum/go-ethereum/common/hexutil" 43 "github.com/ethereum/go-ethereum/consensus" 44 "github.com/ethereum/go-ethereum/consensus/beacon" 45 "github.com/ethereum/go-ethereum/consensus/ethash" 46 "github.com/ethereum/go-ethereum/core" 47 "github.com/ethereum/go-ethereum/core/bloombits" 48 "github.com/ethereum/go-ethereum/core/rawdb" 49 "github.com/ethereum/go-ethereum/core/state" 50 "github.com/ethereum/go-ethereum/core/types" 51 "github.com/ethereum/go-ethereum/core/vm" 52 "github.com/ethereum/go-ethereum/crypto" 53 "github.com/ethereum/go-ethereum/crypto/kzg4844" 54 "github.com/ethereum/go-ethereum/ethdb" 55 "github.com/ethereum/go-ethereum/event" 56 "github.com/ethereum/go-ethereum/internal/blocktest" 57 "github.com/ethereum/go-ethereum/params" 58 "github.com/ethereum/go-ethereum/rpc" 59 ) 60 61 func testTransactionMarshal(t *testing.T, tests []txData, config *params.ChainConfig) { 62 t.Parallel() 63 var ( 64 signer = types.LatestSigner(config) 65 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 66 ) 67 68 for i, tt := range tests { 69 var tx2 types.Transaction 70 tx, err := types.SignNewTx(key, signer, tt.Tx) 71 if err != nil { 72 t.Fatalf("test %d: signing failed: %v", i, err) 73 } 74 // Regular transaction 75 if data, err := json.Marshal(tx); err != nil { 76 t.Fatalf("test %d: marshalling failed; %v", i, err) 77 } else if err = tx2.UnmarshalJSON(data); err != nil { 78 t.Fatalf("test %d: sunmarshal failed: %v", i, err) 79 } else if want, have := tx.Hash(), tx2.Hash(); want != have { 80 t.Fatalf("test %d: stx changed, want %x have %x", i, want, have) 81 } 82 83 // rpcTransaction 84 rpcTx := newRPCTransaction(tx, common.Hash{}, 0, 0, 0, nil, config) 85 if data, err := json.Marshal(rpcTx); err != nil { 86 t.Fatalf("test %d: marshalling failed; %v", i, err) 87 } else if err = tx2.UnmarshalJSON(data); err != nil { 88 t.Fatalf("test %d: unmarshal failed: %v", i, err) 89 } else if want, have := tx.Hash(), tx2.Hash(); want != have { 90 t.Fatalf("test %d: tx changed, want %x have %x", i, want, have) 91 } else { 92 want, have := tt.Want, string(data) 93 require.JSONEqf(t, want, have, "test %d: rpc json not match, want %s have %s", i, want, have) 94 } 95 } 96 } 97 98 func TestTransaction_RoundTripRpcJSON(t *testing.T) { 99 var ( 100 config = params.AllEthashProtocolChanges 101 tests = allTransactionTypes(common.Address{0xde, 0xad}, config) 102 ) 103 testTransactionMarshal(t, tests, config) 104 } 105 106 func TestTransactionBlobTx(t *testing.T) { 107 config := *params.TestChainConfig 108 config.ShanghaiTime = new(uint64) 109 config.CancunTime = new(uint64) 110 tests := allBlobTxs(common.Address{0xde, 0xad}, &config) 111 112 testTransactionMarshal(t, tests, &config) 113 } 114 115 type txData struct { 116 Tx types.TxData 117 Want string 118 } 119 120 func allTransactionTypes(addr common.Address, config *params.ChainConfig) []txData { 121 return []txData{ 122 { 123 Tx: &types.LegacyTx{ 124 Nonce: 5, 125 GasPrice: big.NewInt(6), 126 Gas: 7, 127 To: &addr, 128 Value: big.NewInt(8), 129 Data: []byte{0, 1, 2, 3, 4}, 130 V: big.NewInt(9), 131 R: big.NewInt(10), 132 S: big.NewInt(11), 133 }, 134 Want: `{ 135 "blockHash": null, 136 "blockNumber": null, 137 "from": "0x71562b71999873db5b286df957af199ec94617f7", 138 "gas": "0x7", 139 "gasPrice": "0x6", 140 "hash": "0x5f3240454cd09a5d8b1c5d651eefae7a339262875bcd2d0e6676f3d989967008", 141 "input": "0x0001020304", 142 "nonce": "0x5", 143 "to": "0xdead000000000000000000000000000000000000", 144 "transactionIndex": null, 145 "value": "0x8", 146 "type": "0x0", 147 "chainId": "0x539", 148 "v": "0xa96", 149 "r": "0xbc85e96592b95f7160825d837abb407f009df9ebe8f1b9158a4b8dd093377f75", 150 "s": "0x1b55ea3af5574c536967b039ba6999ef6c89cf22fc04bcb296e0e8b0b9b576f5" 151 }`, 152 }, { 153 Tx: &types.LegacyTx{ 154 Nonce: 5, 155 GasPrice: big.NewInt(6), 156 Gas: 7, 157 To: nil, 158 Value: big.NewInt(8), 159 Data: []byte{0, 1, 2, 3, 4}, 160 V: big.NewInt(32), 161 R: big.NewInt(10), 162 S: big.NewInt(11), 163 }, 164 Want: `{ 165 "blockHash": null, 166 "blockNumber": null, 167 "from": "0x71562b71999873db5b286df957af199ec94617f7", 168 "gas": "0x7", 169 "gasPrice": "0x6", 170 "hash": "0x806e97f9d712b6cb7e781122001380a2837531b0fc1e5f5d78174ad4cb699873", 171 "input": "0x0001020304", 172 "nonce": "0x5", 173 "to": null, 174 "transactionIndex": null, 175 "value": "0x8", 176 "type": "0x0", 177 "chainId": "0x539", 178 "v": "0xa96", 179 "r": "0x9dc28b267b6ad4e4af6fe9289668f9305c2eb7a3241567860699e478af06835a", 180 "s": "0xa0b51a071aa9bed2cd70aedea859779dff039e3630ea38497d95202e9b1fec7" 181 }`, 182 }, 183 { 184 Tx: &types.AccessListTx{ 185 ChainID: config.ChainID, 186 Nonce: 5, 187 GasPrice: big.NewInt(6), 188 Gas: 7, 189 To: &addr, 190 Value: big.NewInt(8), 191 Data: []byte{0, 1, 2, 3, 4}, 192 AccessList: types.AccessList{ 193 types.AccessTuple{ 194 Address: common.Address{0x2}, 195 StorageKeys: []common.Hash{types.EmptyRootHash}, 196 }, 197 }, 198 V: big.NewInt(32), 199 R: big.NewInt(10), 200 S: big.NewInt(11), 201 }, 202 Want: `{ 203 "blockHash": null, 204 "blockNumber": null, 205 "from": "0x71562b71999873db5b286df957af199ec94617f7", 206 "gas": "0x7", 207 "gasPrice": "0x6", 208 "hash": "0x121347468ee5fe0a29f02b49b4ffd1c8342bc4255146bb686cd07117f79e7129", 209 "input": "0x0001020304", 210 "nonce": "0x5", 211 "to": "0xdead000000000000000000000000000000000000", 212 "transactionIndex": null, 213 "value": "0x8", 214 "type": "0x1", 215 "accessList": [ 216 { 217 "address": "0x0200000000000000000000000000000000000000", 218 "storageKeys": [ 219 "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" 220 ] 221 } 222 ], 223 "chainId": "0x539", 224 "v": "0x0", 225 "r": "0xf372ad499239ae11d91d34c559ffc5dab4daffc0069e03afcabdcdf231a0c16b", 226 "s": "0x28573161d1f9472fa0fd4752533609e72f06414f7ab5588699a7141f65d2abf", 227 "yParity": "0x0" 228 }`, 229 }, { 230 Tx: &types.AccessListTx{ 231 ChainID: config.ChainID, 232 Nonce: 5, 233 GasPrice: big.NewInt(6), 234 Gas: 7, 235 To: nil, 236 Value: big.NewInt(8), 237 Data: []byte{0, 1, 2, 3, 4}, 238 AccessList: types.AccessList{ 239 types.AccessTuple{ 240 Address: common.Address{0x2}, 241 StorageKeys: []common.Hash{types.EmptyRootHash}, 242 }, 243 }, 244 V: big.NewInt(32), 245 R: big.NewInt(10), 246 S: big.NewInt(11), 247 }, 248 Want: `{ 249 "blockHash": null, 250 "blockNumber": null, 251 "from": "0x71562b71999873db5b286df957af199ec94617f7", 252 "gas": "0x7", 253 "gasPrice": "0x6", 254 "hash": "0x067c3baebede8027b0f828a9d933be545f7caaec623b00684ac0659726e2055b", 255 "input": "0x0001020304", 256 "nonce": "0x5", 257 "to": null, 258 "transactionIndex": null, 259 "value": "0x8", 260 "type": "0x1", 261 "accessList": [ 262 { 263 "address": "0x0200000000000000000000000000000000000000", 264 "storageKeys": [ 265 "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" 266 ] 267 } 268 ], 269 "chainId": "0x539", 270 "v": "0x1", 271 "r": "0x542981b5130d4613897fbab144796cb36d3cb3d7807d47d9c7f89ca7745b085c", 272 "s": "0x7425b9dd6c5deaa42e4ede35d0c4570c4624f68c28d812c10d806ffdf86ce63", 273 "yParity": "0x1" 274 }`, 275 }, { 276 Tx: &types.DynamicFeeTx{ 277 ChainID: config.ChainID, 278 Nonce: 5, 279 GasTipCap: big.NewInt(6), 280 GasFeeCap: big.NewInt(9), 281 Gas: 7, 282 To: &addr, 283 Value: big.NewInt(8), 284 Data: []byte{0, 1, 2, 3, 4}, 285 AccessList: types.AccessList{ 286 types.AccessTuple{ 287 Address: common.Address{0x2}, 288 StorageKeys: []common.Hash{types.EmptyRootHash}, 289 }, 290 }, 291 V: big.NewInt(32), 292 R: big.NewInt(10), 293 S: big.NewInt(11), 294 }, 295 Want: `{ 296 "blockHash": null, 297 "blockNumber": null, 298 "from": "0x71562b71999873db5b286df957af199ec94617f7", 299 "gas": "0x7", 300 "gasPrice": "0x9", 301 "maxFeePerGas": "0x9", 302 "maxPriorityFeePerGas": "0x6", 303 "hash": "0xb63e0b146b34c3e9cb7fbabb5b3c081254a7ded6f1b65324b5898cc0545d79ff", 304 "input": "0x0001020304", 305 "nonce": "0x5", 306 "to": "0xdead000000000000000000000000000000000000", 307 "transactionIndex": null, 308 "value": "0x8", 309 "type": "0x2", 310 "accessList": [ 311 { 312 "address": "0x0200000000000000000000000000000000000000", 313 "storageKeys": [ 314 "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" 315 ] 316 } 317 ], 318 "chainId": "0x539", 319 "v": "0x1", 320 "r": "0x3b167e05418a8932cd53d7578711fe1a76b9b96c48642402bb94978b7a107e80", 321 "s": "0x22f98a332d15ea2cc80386c1ebaa31b0afebfa79ebc7d039a1e0074418301fef", 322 "yParity": "0x1" 323 }`, 324 }, { 325 Tx: &types.DynamicFeeTx{ 326 ChainID: config.ChainID, 327 Nonce: 5, 328 GasTipCap: big.NewInt(6), 329 GasFeeCap: big.NewInt(9), 330 Gas: 7, 331 To: nil, 332 Value: big.NewInt(8), 333 Data: []byte{0, 1, 2, 3, 4}, 334 AccessList: types.AccessList{}, 335 V: big.NewInt(32), 336 R: big.NewInt(10), 337 S: big.NewInt(11), 338 }, 339 Want: `{ 340 "blockHash": null, 341 "blockNumber": null, 342 "from": "0x71562b71999873db5b286df957af199ec94617f7", 343 "gas": "0x7", 344 "gasPrice": "0x9", 345 "maxFeePerGas": "0x9", 346 "maxPriorityFeePerGas": "0x6", 347 "hash": "0xcbab17ee031a9d5b5a09dff909f0a28aedb9b295ac0635d8710d11c7b806ec68", 348 "input": "0x0001020304", 349 "nonce": "0x5", 350 "to": null, 351 "transactionIndex": null, 352 "value": "0x8", 353 "type": "0x2", 354 "accessList": [], 355 "chainId": "0x539", 356 "v": "0x0", 357 "r": "0x6446b8a682db7e619fc6b4f6d1f708f6a17351a41c7fbd63665f469bc78b41b9", 358 "s": "0x7626abc15834f391a117c63450047309dbf84c5ce3e8e609b607062641e2de43", 359 "yParity": "0x0" 360 }`, 361 }, 362 } 363 } 364 365 func allBlobTxs(addr common.Address, config *params.ChainConfig) []txData { 366 return []txData{ 367 { 368 Tx: &types.BlobTx{ 369 Nonce: 6, 370 GasTipCap: uint256.NewInt(1), 371 GasFeeCap: uint256.NewInt(5), 372 Gas: 6, 373 To: addr, 374 BlobFeeCap: uint256.NewInt(1), 375 BlobHashes: []common.Hash{{1}}, 376 Value: new(uint256.Int), 377 V: uint256.NewInt(32), 378 R: uint256.NewInt(10), 379 S: uint256.NewInt(11), 380 }, 381 Want: `{ 382 "blockHash": null, 383 "blockNumber": null, 384 "from": "0x71562b71999873db5b286df957af199ec94617f7", 385 "gas": "0x6", 386 "gasPrice": "0x5", 387 "maxFeePerGas": "0x5", 388 "maxPriorityFeePerGas": "0x1", 389 "maxFeePerBlobGas": "0x1", 390 "hash": "0x1f2b59a20e61efc615ad0cbe936379d6bbea6f938aafaf35eb1da05d8e7f46a3", 391 "input": "0x", 392 "nonce": "0x6", 393 "to": "0xdead000000000000000000000000000000000000", 394 "transactionIndex": null, 395 "value": "0x0", 396 "type": "0x3", 397 "accessList": [], 398 "chainId": "0x1", 399 "blobVersionedHashes": [ 400 "0x0100000000000000000000000000000000000000000000000000000000000000" 401 ], 402 "v": "0x0", 403 "r": "0x618be8908e0e5320f8f3b48042a079fe5a335ebd4ed1422a7d2207cd45d872bc", 404 "s": "0x27b2bc6c80e849a8e8b764d4549d8c2efac3441e73cf37054eb0a9b9f8e89b27", 405 "yParity": "0x0" 406 }`, 407 }, 408 } 409 } 410 411 func newTestAccountManager(t *testing.T) (*accounts.Manager, accounts.Account) { 412 var ( 413 dir = t.TempDir() 414 am = accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true}) 415 b = keystore.NewKeyStore(dir, 2, 1) 416 testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 417 ) 418 acc, err := b.ImportECDSA(testKey, "") 419 if err != nil { 420 t.Fatalf("failed to create test account: %v", err) 421 } 422 if err := b.Unlock(acc, ""); err != nil { 423 t.Fatalf("failed to unlock account: %v\n", err) 424 } 425 am.AddBackend(b) 426 return am, acc 427 } 428 429 type testBackend struct { 430 db ethdb.Database 431 chain *core.BlockChain 432 pending *types.Block 433 accman *accounts.Manager 434 acc accounts.Account 435 } 436 437 func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend { 438 var ( 439 cacheConfig = &core.CacheConfig{ 440 TrieCleanLimit: 256, 441 TrieDirtyLimit: 256, 442 TrieTimeLimit: 5 * time.Minute, 443 SnapshotLimit: 0, 444 TrieDirtyDisabled: true, // Archive mode 445 } 446 ) 447 accman, acc := newTestAccountManager(t) 448 gspec.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)} 449 // Generate blocks for testing 450 db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator) 451 txlookupLimit := uint64(0) 452 chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, &txlookupLimit) 453 if err != nil { 454 t.Fatalf("failed to create tester chain: %v", err) 455 } 456 if n, err := chain.InsertChain(blocks); err != nil { 457 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 458 } 459 460 backend := &testBackend{db: db, chain: chain, accman: accman, acc: acc} 461 return backend 462 } 463 464 func (b *testBackend) setPendingBlock(block *types.Block) { 465 b.pending = block 466 } 467 468 func (b testBackend) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} } 469 func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 470 return big.NewInt(0), nil 471 } 472 func (b testBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) { 473 return nil, nil, nil, nil, nil, nil, nil 474 } 475 func (b testBackend) BlobBaseFee(ctx context.Context) *big.Int { return new(big.Int) } 476 func (b testBackend) ChainDb() ethdb.Database { return b.db } 477 func (b testBackend) AccountManager() *accounts.Manager { return b.accman } 478 func (b testBackend) ExtRPCEnabled() bool { return false } 479 func (b testBackend) RPCGasCap() uint64 { return 10000000 } 480 func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second } 481 func (b testBackend) RPCTxFeeCap() float64 { return 0 } 482 func (b testBackend) UnprotectedAllowed() bool { return false } 483 func (b testBackend) SetHead(number uint64) {} 484 func (b testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 485 if number == rpc.LatestBlockNumber { 486 return b.chain.CurrentBlock(), nil 487 } 488 if number == rpc.PendingBlockNumber && b.pending != nil { 489 return b.pending.Header(), nil 490 } 491 return b.chain.GetHeaderByNumber(uint64(number)), nil 492 } 493 func (b testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 494 return b.chain.GetHeaderByHash(hash), nil 495 } 496 func (b testBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { 497 if blockNr, ok := blockNrOrHash.Number(); ok { 498 return b.HeaderByNumber(ctx, blockNr) 499 } 500 if blockHash, ok := blockNrOrHash.Hash(); ok { 501 return b.HeaderByHash(ctx, blockHash) 502 } 503 panic("unknown type rpc.BlockNumberOrHash") 504 } 505 func (b testBackend) CurrentHeader() *types.Header { return b.chain.CurrentBlock() } 506 func (b testBackend) CurrentBlock() *types.Header { return b.chain.CurrentBlock() } 507 func (b testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { 508 if number == rpc.LatestBlockNumber { 509 head := b.chain.CurrentBlock() 510 return b.chain.GetBlock(head.Hash(), head.Number.Uint64()), nil 511 } 512 if number == rpc.PendingBlockNumber { 513 return b.pending, nil 514 } 515 return b.chain.GetBlockByNumber(uint64(number)), nil 516 } 517 func (b testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 518 return b.chain.GetBlockByHash(hash), nil 519 } 520 func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { 521 if blockNr, ok := blockNrOrHash.Number(); ok { 522 return b.BlockByNumber(ctx, blockNr) 523 } 524 if blockHash, ok := blockNrOrHash.Hash(); ok { 525 return b.BlockByHash(ctx, blockHash) 526 } 527 panic("unknown type rpc.BlockNumberOrHash") 528 } 529 func (b testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { 530 return b.chain.GetBlock(hash, uint64(number.Int64())).Body(), nil 531 } 532 func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { 533 if number == rpc.PendingBlockNumber { 534 panic("pending state not implemented") 535 } 536 header, err := b.HeaderByNumber(ctx, number) 537 if err != nil { 538 return nil, nil, err 539 } 540 if header == nil { 541 return nil, nil, errors.New("header not found") 542 } 543 stateDb, err := b.chain.StateAt(header.Root) 544 return stateDb, header, err 545 } 546 func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { 547 if blockNr, ok := blockNrOrHash.Number(); ok { 548 return b.StateAndHeaderByNumber(ctx, blockNr) 549 } 550 panic("only implemented for number") 551 } 552 func (b testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) { panic("implement me") } 553 func (b testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 554 header, err := b.HeaderByHash(ctx, hash) 555 if header == nil || err != nil { 556 return nil, err 557 } 558 receipts := rawdb.ReadReceipts(b.db, hash, header.Number.Uint64(), header.Time, b.chain.Config()) 559 return receipts, nil 560 } 561 func (b testBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { 562 if b.pending != nil && hash == b.pending.Hash() { 563 return nil 564 } 565 return big.NewInt(1) 566 } 567 func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM { 568 if vmConfig == nil { 569 vmConfig = b.chain.GetVMConfig() 570 } 571 txContext := core.NewEVMTxContext(msg) 572 context := core.NewEVMBlockContext(header, b.chain, nil) 573 if blockContext != nil { 574 context = *blockContext 575 } 576 return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig) 577 } 578 func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { 579 panic("implement me") 580 } 581 func (b testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 582 panic("implement me") 583 } 584 func (b testBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { 585 panic("implement me") 586 } 587 func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { 588 panic("implement me") 589 } 590 func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) { 591 tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash) 592 return true, tx, blockHash, blockNumber, index, nil 593 } 594 func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") } 595 func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") } 596 func (b testBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { 597 return 0, nil 598 } 599 func (b testBackend) Stats() (pending int, queued int) { panic("implement me") } 600 func (b testBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { 601 panic("implement me") 602 } 603 func (b testBackend) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { 604 panic("implement me") 605 } 606 func (b testBackend) SubscribeNewTxsEvent(events chan<- core.NewTxsEvent) event.Subscription { 607 panic("implement me") 608 } 609 func (b testBackend) ChainConfig() *params.ChainConfig { return b.chain.Config() } 610 func (b testBackend) Engine() consensus.Engine { return b.chain.Engine() } 611 func (b testBackend) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) { 612 panic("implement me") 613 } 614 func (b testBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { 615 panic("implement me") 616 } 617 func (b testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 618 panic("implement me") 619 } 620 func (b testBackend) BloomStatus() (uint64, uint64) { panic("implement me") } 621 func (b testBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { 622 panic("implement me") 623 } 624 625 func TestEstimateGas(t *testing.T) { 626 t.Parallel() 627 // Initialize test accounts 628 var ( 629 accounts = newAccounts(2) 630 genesis = &core.Genesis{ 631 Config: params.MergedTestChainConfig, 632 Alloc: types.GenesisAlloc{ 633 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 634 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 635 }, 636 } 637 genBlocks = 10 638 signer = types.HomesteadSigner{} 639 randomAccounts = newAccounts(2) 640 ) 641 api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { 642 // Transfer from account[0] to account[1] 643 // value: 1000 wei 644 // fee: 0 wei 645 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key) 646 b.AddTx(tx) 647 b.SetPoS() 648 })) 649 var testSuite = []struct { 650 blockNumber rpc.BlockNumber 651 call TransactionArgs 652 overrides StateOverride 653 expectErr error 654 want uint64 655 }{ 656 // simple transfer on latest block 657 { 658 blockNumber: rpc.LatestBlockNumber, 659 call: TransactionArgs{ 660 From: &accounts[0].addr, 661 To: &accounts[1].addr, 662 Value: (*hexutil.Big)(big.NewInt(1000)), 663 }, 664 expectErr: nil, 665 want: 21000, 666 }, 667 // simple transfer with insufficient funds on latest block 668 { 669 blockNumber: rpc.LatestBlockNumber, 670 call: TransactionArgs{ 671 From: &randomAccounts[0].addr, 672 To: &accounts[1].addr, 673 Value: (*hexutil.Big)(big.NewInt(1000)), 674 }, 675 expectErr: core.ErrInsufficientFunds, 676 want: 21000, 677 }, 678 // empty create 679 { 680 blockNumber: rpc.LatestBlockNumber, 681 call: TransactionArgs{}, 682 expectErr: nil, 683 want: 53000, 684 }, 685 { 686 blockNumber: rpc.LatestBlockNumber, 687 call: TransactionArgs{}, 688 overrides: StateOverride{ 689 randomAccounts[0].addr: OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))}, 690 }, 691 expectErr: nil, 692 want: 53000, 693 }, 694 { 695 blockNumber: rpc.LatestBlockNumber, 696 call: TransactionArgs{ 697 From: &randomAccounts[0].addr, 698 To: &randomAccounts[1].addr, 699 Value: (*hexutil.Big)(big.NewInt(1000)), 700 }, 701 overrides: StateOverride{ 702 randomAccounts[0].addr: OverrideAccount{Balance: newRPCBalance(big.NewInt(0))}, 703 }, 704 expectErr: core.ErrInsufficientFunds, 705 }, 706 // Test for a bug where the gas price was set to zero but the basefee non-zero 707 // 708 // contract BasefeeChecker { 709 // constructor() { 710 // require(tx.gasprice >= block.basefee); 711 // if (tx.gasprice > 0) { 712 // require(block.basefee > 0); 713 // } 714 // } 715 //} 716 { 717 blockNumber: rpc.LatestBlockNumber, 718 call: TransactionArgs{ 719 From: &accounts[0].addr, 720 Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"), 721 GasPrice: (*hexutil.Big)(big.NewInt(1_000_000_000)), // Legacy as pricing 722 }, 723 expectErr: nil, 724 want: 67617, 725 }, 726 { 727 blockNumber: rpc.LatestBlockNumber, 728 call: TransactionArgs{ 729 From: &accounts[0].addr, 730 Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"), 731 MaxFeePerGas: (*hexutil.Big)(big.NewInt(1_000_000_000)), // 1559 gas pricing 732 }, 733 expectErr: nil, 734 want: 67617, 735 }, 736 { 737 blockNumber: rpc.LatestBlockNumber, 738 call: TransactionArgs{ 739 From: &accounts[0].addr, 740 Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"), 741 GasPrice: nil, // No legacy gas pricing 742 MaxFeePerGas: nil, // No 1559 gas pricing 743 }, 744 expectErr: nil, 745 want: 67595, 746 }, 747 // Blobs should have no effect on gas estimate 748 { 749 blockNumber: rpc.LatestBlockNumber, 750 call: TransactionArgs{ 751 From: &accounts[0].addr, 752 To: &accounts[1].addr, 753 Value: (*hexutil.Big)(big.NewInt(1)), 754 BlobHashes: []common.Hash{common.Hash{0x01, 0x22}}, 755 BlobFeeCap: (*hexutil.Big)(big.NewInt(1)), 756 }, 757 want: 21000, 758 }, 759 } 760 for i, tc := range testSuite { 761 result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides) 762 if tc.expectErr != nil { 763 if err == nil { 764 t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr) 765 continue 766 } 767 if !errors.Is(err, tc.expectErr) { 768 t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err) 769 } 770 continue 771 } 772 if err != nil { 773 t.Errorf("test %d: want no error, have %v", i, err) 774 continue 775 } 776 if float64(result) > float64(tc.want)*(1+estimateGasErrorRatio) { 777 t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, uint64(result), tc.want) 778 } 779 } 780 } 781 782 func TestCall(t *testing.T) { 783 t.Parallel() 784 // Initialize test accounts 785 var ( 786 accounts = newAccounts(3) 787 genesis = &core.Genesis{ 788 Config: params.MergedTestChainConfig, 789 Alloc: types.GenesisAlloc{ 790 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 791 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 792 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 793 }, 794 } 795 genBlocks = 10 796 signer = types.HomesteadSigner{} 797 ) 798 api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { 799 // Transfer from account[0] to account[1] 800 // value: 1000 wei 801 // fee: 0 wei 802 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key) 803 b.AddTx(tx) 804 b.SetPoS() 805 })) 806 randomAccounts := newAccounts(3) 807 var testSuite = []struct { 808 blockNumber rpc.BlockNumber 809 overrides StateOverride 810 call TransactionArgs 811 blockOverrides BlockOverrides 812 expectErr error 813 want string 814 }{ 815 // transfer on genesis 816 { 817 blockNumber: rpc.BlockNumber(0), 818 call: TransactionArgs{ 819 From: &accounts[0].addr, 820 To: &accounts[1].addr, 821 Value: (*hexutil.Big)(big.NewInt(1000)), 822 }, 823 expectErr: nil, 824 want: "0x", 825 }, 826 // transfer on the head 827 { 828 blockNumber: rpc.BlockNumber(genBlocks), 829 call: TransactionArgs{ 830 From: &accounts[0].addr, 831 To: &accounts[1].addr, 832 Value: (*hexutil.Big)(big.NewInt(1000)), 833 }, 834 expectErr: nil, 835 want: "0x", 836 }, 837 // transfer on a non-existent block, error expects 838 { 839 blockNumber: rpc.BlockNumber(genBlocks + 1), 840 call: TransactionArgs{ 841 From: &accounts[0].addr, 842 To: &accounts[1].addr, 843 Value: (*hexutil.Big)(big.NewInt(1000)), 844 }, 845 expectErr: errors.New("header not found"), 846 }, 847 // transfer on the latest block 848 { 849 blockNumber: rpc.LatestBlockNumber, 850 call: TransactionArgs{ 851 From: &accounts[0].addr, 852 To: &accounts[1].addr, 853 Value: (*hexutil.Big)(big.NewInt(1000)), 854 }, 855 expectErr: nil, 856 want: "0x", 857 }, 858 // Call which can only succeed if state is state overridden 859 { 860 blockNumber: rpc.LatestBlockNumber, 861 call: TransactionArgs{ 862 From: &randomAccounts[0].addr, 863 To: &randomAccounts[1].addr, 864 Value: (*hexutil.Big)(big.NewInt(1000)), 865 }, 866 overrides: StateOverride{ 867 randomAccounts[0].addr: OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))}, 868 }, 869 want: "0x", 870 }, 871 // Invalid call without state overriding 872 { 873 blockNumber: rpc.LatestBlockNumber, 874 call: TransactionArgs{ 875 From: &randomAccounts[0].addr, 876 To: &randomAccounts[1].addr, 877 Value: (*hexutil.Big)(big.NewInt(1000)), 878 }, 879 expectErr: core.ErrInsufficientFunds, 880 }, 881 // Successful simple contract call 882 // 883 // // SPDX-License-Identifier: GPL-3.0 884 // 885 // pragma solidity >=0.7.0 <0.8.0; 886 // 887 // /** 888 // * @title Storage 889 // * @dev Store & retrieve value in a variable 890 // */ 891 // contract Storage { 892 // uint256 public number; 893 // constructor() { 894 // number = block.number; 895 // } 896 // } 897 { 898 blockNumber: rpc.LatestBlockNumber, 899 call: TransactionArgs{ 900 From: &randomAccounts[0].addr, 901 To: &randomAccounts[2].addr, 902 Data: hex2Bytes("8381f58a"), // call number() 903 }, 904 overrides: StateOverride{ 905 randomAccounts[2].addr: OverrideAccount{ 906 Code: hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033"), 907 StateDiff: &map[common.Hash]common.Hash{{}: common.BigToHash(big.NewInt(123))}, 908 }, 909 }, 910 want: "0x000000000000000000000000000000000000000000000000000000000000007b", 911 }, 912 // Block overrides should work 913 { 914 blockNumber: rpc.LatestBlockNumber, 915 call: TransactionArgs{ 916 From: &accounts[1].addr, 917 Input: &hexutil.Bytes{ 918 0x43, // NUMBER 919 0x60, 0x00, 0x52, // MSTORE offset 0 920 0x60, 0x20, 0x60, 0x00, 0xf3, 921 }, 922 }, 923 blockOverrides: BlockOverrides{Number: (*hexutil.Big)(big.NewInt(11))}, 924 want: "0x000000000000000000000000000000000000000000000000000000000000000b", 925 }, 926 // Invalid blob tx 927 { 928 blockNumber: rpc.LatestBlockNumber, 929 call: TransactionArgs{ 930 From: &accounts[1].addr, 931 Input: &hexutil.Bytes{0x00}, 932 BlobHashes: []common.Hash{}, 933 }, 934 expectErr: core.ErrBlobTxCreate, 935 }, 936 // BLOBHASH opcode 937 { 938 blockNumber: rpc.LatestBlockNumber, 939 call: TransactionArgs{ 940 From: &accounts[1].addr, 941 To: &randomAccounts[2].addr, 942 BlobHashes: []common.Hash{common.Hash{0x01, 0x22}}, 943 BlobFeeCap: (*hexutil.Big)(big.NewInt(1)), 944 }, 945 overrides: StateOverride{ 946 randomAccounts[2].addr: { 947 Code: hex2Bytes("60004960005260206000f3"), 948 }, 949 }, 950 want: "0x0122000000000000000000000000000000000000000000000000000000000000", 951 }, 952 } 953 for i, tc := range testSuite { 954 result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides) 955 if tc.expectErr != nil { 956 if err == nil { 957 t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr) 958 continue 959 } 960 if !errors.Is(err, tc.expectErr) { 961 // Second try 962 if !reflect.DeepEqual(err, tc.expectErr) { 963 t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err) 964 } 965 } 966 continue 967 } 968 if err != nil { 969 t.Errorf("test %d: want no error, have %v", i, err) 970 continue 971 } 972 if !reflect.DeepEqual(result.String(), tc.want) { 973 t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, result.String(), tc.want) 974 } 975 } 976 } 977 978 func TestSignTransaction(t *testing.T) { 979 t.Parallel() 980 // Initialize test accounts 981 var ( 982 key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 983 to = crypto.PubkeyToAddress(key.PublicKey) 984 genesis = &core.Genesis{ 985 Config: params.MergedTestChainConfig, 986 Alloc: types.GenesisAlloc{}, 987 } 988 ) 989 b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { 990 b.SetPoS() 991 }) 992 api := NewTransactionAPI(b, nil) 993 res, err := api.FillTransaction(context.Background(), TransactionArgs{ 994 From: &b.acc.Address, 995 To: &to, 996 Value: (*hexutil.Big)(big.NewInt(1)), 997 }) 998 if err != nil { 999 t.Fatalf("failed to fill tx defaults: %v\n", err) 1000 } 1001 1002 res, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address)) 1003 if err != nil { 1004 t.Fatalf("failed to sign tx: %v\n", err) 1005 } 1006 tx, err := json.Marshal(res.Tx) 1007 if err != nil { 1008 t.Fatal(err) 1009 } 1010 expect := `{"type":"0x2","chainId":"0x1","nonce":"0x0","to":"0x703c4b2bd70c169f5717101caee543299fc946c7","gas":"0x5208","gasPrice":null,"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x684ee180","value":"0x1","input":"0x","accessList":[],"v":"0x0","r":"0x8fabeb142d585dd9247f459f7e6fe77e2520c88d50ba5d220da1533cea8b34e1","s":"0x582dd68b21aef36ba23f34e49607329c20d981d30404daf749077f5606785ce7","yParity":"0x0","hash":"0x93927839207cfbec395da84b8a2bc38b7b65d2cb2819e9fef1f091f5b1d4cc8f"}` 1011 if !bytes.Equal(tx, []byte(expect)) { 1012 t.Errorf("result mismatch. Have:\n%s\nWant:\n%s\n", tx, expect) 1013 } 1014 } 1015 1016 func TestSignBlobTransaction(t *testing.T) { 1017 t.Parallel() 1018 // Initialize test accounts 1019 var ( 1020 key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1021 to = crypto.PubkeyToAddress(key.PublicKey) 1022 genesis = &core.Genesis{ 1023 Config: params.MergedTestChainConfig, 1024 Alloc: types.GenesisAlloc{}, 1025 } 1026 ) 1027 b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { 1028 b.SetPoS() 1029 }) 1030 api := NewTransactionAPI(b, nil) 1031 res, err := api.FillTransaction(context.Background(), TransactionArgs{ 1032 From: &b.acc.Address, 1033 To: &to, 1034 Value: (*hexutil.Big)(big.NewInt(1)), 1035 BlobHashes: []common.Hash{{0x01, 0x22}}, 1036 }) 1037 if err != nil { 1038 t.Fatalf("failed to fill tx defaults: %v\n", err) 1039 } 1040 1041 _, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address)) 1042 if err != nil { 1043 t.Fatalf("should not fail on blob transaction") 1044 } 1045 } 1046 1047 func TestSendBlobTransaction(t *testing.T) { 1048 t.Parallel() 1049 // Initialize test accounts 1050 var ( 1051 key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1052 to = crypto.PubkeyToAddress(key.PublicKey) 1053 genesis = &core.Genesis{ 1054 Config: params.MergedTestChainConfig, 1055 Alloc: types.GenesisAlloc{}, 1056 } 1057 ) 1058 b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { 1059 b.SetPoS() 1060 }) 1061 api := NewTransactionAPI(b, nil) 1062 res, err := api.FillTransaction(context.Background(), TransactionArgs{ 1063 From: &b.acc.Address, 1064 To: &to, 1065 Value: (*hexutil.Big)(big.NewInt(1)), 1066 BlobHashes: []common.Hash{common.Hash{0x01, 0x22}}, 1067 }) 1068 if err != nil { 1069 t.Fatalf("failed to fill tx defaults: %v\n", err) 1070 } 1071 1072 _, err = api.SendTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address)) 1073 if err == nil { 1074 t.Errorf("sending tx should have failed") 1075 } else if !errors.Is(err, errBlobTxNotSupported) { 1076 t.Errorf("unexpected error. Have %v, want %v\n", err, errBlobTxNotSupported) 1077 } 1078 } 1079 1080 func TestFillBlobTransaction(t *testing.T) { 1081 t.Parallel() 1082 // Initialize test accounts 1083 var ( 1084 key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1085 to = crypto.PubkeyToAddress(key.PublicKey) 1086 genesis = &core.Genesis{ 1087 Config: params.MergedTestChainConfig, 1088 Alloc: types.GenesisAlloc{}, 1089 } 1090 emptyBlob = new(kzg4844.Blob) 1091 emptyBlobs = []kzg4844.Blob{*emptyBlob} 1092 emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) 1093 emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) 1094 emptyBlobHash common.Hash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit) 1095 ) 1096 b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { 1097 b.SetPoS() 1098 }) 1099 api := NewTransactionAPI(b, nil) 1100 type result struct { 1101 Hashes []common.Hash 1102 Sidecar *types.BlobTxSidecar 1103 } 1104 suite := []struct { 1105 name string 1106 args TransactionArgs 1107 err string 1108 want *result 1109 }{ 1110 { 1111 name: "TestInvalidParamsCombination1", 1112 args: TransactionArgs{ 1113 From: &b.acc.Address, 1114 To: &to, 1115 Value: (*hexutil.Big)(big.NewInt(1)), 1116 Blobs: []kzg4844.Blob{{}}, 1117 Proofs: []kzg4844.Proof{{}}, 1118 }, 1119 err: `blob proofs provided while commitments were not`, 1120 }, 1121 { 1122 name: "TestInvalidParamsCombination2", 1123 args: TransactionArgs{ 1124 From: &b.acc.Address, 1125 To: &to, 1126 Value: (*hexutil.Big)(big.NewInt(1)), 1127 Blobs: []kzg4844.Blob{{}}, 1128 Commitments: []kzg4844.Commitment{{}}, 1129 }, 1130 err: `blob commitments provided while proofs were not`, 1131 }, 1132 { 1133 name: "TestInvalidParamsCount1", 1134 args: TransactionArgs{ 1135 From: &b.acc.Address, 1136 To: &to, 1137 Value: (*hexutil.Big)(big.NewInt(1)), 1138 Blobs: []kzg4844.Blob{{}}, 1139 Commitments: []kzg4844.Commitment{{}, {}}, 1140 Proofs: []kzg4844.Proof{{}, {}}, 1141 }, 1142 err: `number of blobs and commitments mismatch (have=2, want=1)`, 1143 }, 1144 { 1145 name: "TestInvalidParamsCount2", 1146 args: TransactionArgs{ 1147 From: &b.acc.Address, 1148 To: &to, 1149 Value: (*hexutil.Big)(big.NewInt(1)), 1150 Blobs: []kzg4844.Blob{{}, {}}, 1151 Commitments: []kzg4844.Commitment{{}, {}}, 1152 Proofs: []kzg4844.Proof{{}}, 1153 }, 1154 err: `number of blobs and proofs mismatch (have=1, want=2)`, 1155 }, 1156 { 1157 name: "TestInvalidProofVerification", 1158 args: TransactionArgs{ 1159 From: &b.acc.Address, 1160 To: &to, 1161 Value: (*hexutil.Big)(big.NewInt(1)), 1162 Blobs: []kzg4844.Blob{{}, {}}, 1163 Commitments: []kzg4844.Commitment{{}, {}}, 1164 Proofs: []kzg4844.Proof{{}, {}}, 1165 }, 1166 err: `failed to verify blob proof: short buffer`, 1167 }, 1168 { 1169 name: "TestGenerateBlobHashes", 1170 args: TransactionArgs{ 1171 From: &b.acc.Address, 1172 To: &to, 1173 Value: (*hexutil.Big)(big.NewInt(1)), 1174 Blobs: emptyBlobs, 1175 Commitments: []kzg4844.Commitment{emptyBlobCommit}, 1176 Proofs: []kzg4844.Proof{emptyBlobProof}, 1177 }, 1178 want: &result{ 1179 Hashes: []common.Hash{emptyBlobHash}, 1180 Sidecar: &types.BlobTxSidecar{ 1181 Blobs: emptyBlobs, 1182 Commitments: []kzg4844.Commitment{emptyBlobCommit}, 1183 Proofs: []kzg4844.Proof{emptyBlobProof}, 1184 }, 1185 }, 1186 }, 1187 { 1188 name: "TestValidBlobHashes", 1189 args: TransactionArgs{ 1190 From: &b.acc.Address, 1191 To: &to, 1192 Value: (*hexutil.Big)(big.NewInt(1)), 1193 BlobHashes: []common.Hash{emptyBlobHash}, 1194 Blobs: emptyBlobs, 1195 Commitments: []kzg4844.Commitment{emptyBlobCommit}, 1196 Proofs: []kzg4844.Proof{emptyBlobProof}, 1197 }, 1198 want: &result{ 1199 Hashes: []common.Hash{emptyBlobHash}, 1200 Sidecar: &types.BlobTxSidecar{ 1201 Blobs: emptyBlobs, 1202 Commitments: []kzg4844.Commitment{emptyBlobCommit}, 1203 Proofs: []kzg4844.Proof{emptyBlobProof}, 1204 }, 1205 }, 1206 }, 1207 { 1208 name: "TestInvalidBlobHashes", 1209 args: TransactionArgs{ 1210 From: &b.acc.Address, 1211 To: &to, 1212 Value: (*hexutil.Big)(big.NewInt(1)), 1213 BlobHashes: []common.Hash{{0x01, 0x22}}, 1214 Blobs: emptyBlobs, 1215 Commitments: []kzg4844.Commitment{emptyBlobCommit}, 1216 Proofs: []kzg4844.Proof{emptyBlobProof}, 1217 }, 1218 err: fmt.Sprintf("blob hash verification failed (have=%s, want=%s)", common.Hash{0x01, 0x22}, emptyBlobHash), 1219 }, 1220 { 1221 name: "TestGenerateBlobProofs", 1222 args: TransactionArgs{ 1223 From: &b.acc.Address, 1224 To: &to, 1225 Value: (*hexutil.Big)(big.NewInt(1)), 1226 Blobs: emptyBlobs, 1227 }, 1228 want: &result{ 1229 Hashes: []common.Hash{emptyBlobHash}, 1230 Sidecar: &types.BlobTxSidecar{ 1231 Blobs: emptyBlobs, 1232 Commitments: []kzg4844.Commitment{emptyBlobCommit}, 1233 Proofs: []kzg4844.Proof{emptyBlobProof}, 1234 }, 1235 }, 1236 }, 1237 } 1238 for _, tc := range suite { 1239 t.Run(tc.name, func(t *testing.T) { 1240 res, err := api.FillTransaction(context.Background(), tc.args) 1241 if len(tc.err) > 0 { 1242 if err == nil { 1243 t.Fatalf("missing error. want: %s", tc.err) 1244 } else if err.Error() != tc.err { 1245 t.Fatalf("error mismatch. want: %s, have: %s", tc.err, err.Error()) 1246 } 1247 return 1248 } 1249 if err != nil && len(tc.err) == 0 { 1250 t.Fatalf("expected no error. have: %s", err) 1251 } 1252 if res == nil { 1253 t.Fatal("result missing") 1254 } 1255 want, err := json.Marshal(tc.want) 1256 if err != nil { 1257 t.Fatalf("failed to encode expected: %v", err) 1258 } 1259 have, err := json.Marshal(result{Hashes: res.Tx.BlobHashes(), Sidecar: res.Tx.BlobTxSidecar()}) 1260 if err != nil { 1261 t.Fatalf("failed to encode computed sidecar: %v", err) 1262 } 1263 if !bytes.Equal(have, want) { 1264 t.Errorf("blob sidecar mismatch. Have: %s, want: %s", have, want) 1265 } 1266 }) 1267 } 1268 } 1269 1270 func argsFromTransaction(tx *types.Transaction, from common.Address) TransactionArgs { 1271 var ( 1272 gas = tx.Gas() 1273 nonce = tx.Nonce() 1274 input = tx.Data() 1275 accessList *types.AccessList 1276 ) 1277 if acl := tx.AccessList(); acl != nil { 1278 accessList = &acl 1279 } 1280 return TransactionArgs{ 1281 From: &from, 1282 To: tx.To(), 1283 Gas: (*hexutil.Uint64)(&gas), 1284 MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()), 1285 MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()), 1286 Value: (*hexutil.Big)(tx.Value()), 1287 Nonce: (*hexutil.Uint64)(&nonce), 1288 Input: (*hexutil.Bytes)(&input), 1289 ChainID: (*hexutil.Big)(tx.ChainId()), 1290 AccessList: accessList, 1291 BlobFeeCap: (*hexutil.Big)(tx.BlobGasFeeCap()), 1292 BlobHashes: tx.BlobHashes(), 1293 } 1294 } 1295 1296 type account struct { 1297 key *ecdsa.PrivateKey 1298 addr common.Address 1299 } 1300 1301 func newAccounts(n int) (accounts []account) { 1302 for i := 0; i < n; i++ { 1303 key, _ := crypto.GenerateKey() 1304 addr := crypto.PubkeyToAddress(key.PublicKey) 1305 accounts = append(accounts, account{key: key, addr: addr}) 1306 } 1307 slices.SortFunc(accounts, func(a, b account) int { return a.addr.Cmp(b.addr) }) 1308 return accounts 1309 } 1310 1311 func newRPCBalance(balance *big.Int) **hexutil.Big { 1312 rpcBalance := (*hexutil.Big)(balance) 1313 return &rpcBalance 1314 } 1315 1316 func hex2Bytes(str string) *hexutil.Bytes { 1317 rpcBytes := hexutil.Bytes(common.Hex2Bytes(str)) 1318 return &rpcBytes 1319 } 1320 1321 func TestRPCMarshalBlock(t *testing.T) { 1322 t.Parallel() 1323 var ( 1324 txs []*types.Transaction 1325 to = common.BytesToAddress([]byte{0x11}) 1326 ) 1327 for i := uint64(1); i <= 4; i++ { 1328 var tx *types.Transaction 1329 if i%2 == 0 { 1330 tx = types.NewTx(&types.LegacyTx{ 1331 Nonce: i, 1332 GasPrice: big.NewInt(11111), 1333 Gas: 1111, 1334 To: &to, 1335 Value: big.NewInt(111), 1336 Data: []byte{0x11, 0x11, 0x11}, 1337 }) 1338 } else { 1339 tx = types.NewTx(&types.AccessListTx{ 1340 ChainID: big.NewInt(1337), 1341 Nonce: i, 1342 GasPrice: big.NewInt(11111), 1343 Gas: 1111, 1344 To: &to, 1345 Value: big.NewInt(111), 1346 Data: []byte{0x11, 0x11, 0x11}, 1347 }) 1348 } 1349 txs = append(txs, tx) 1350 } 1351 block := types.NewBlock(&types.Header{Number: big.NewInt(100)}, &types.Body{Transactions: txs}, nil, blocktest.NewHasher()) 1352 1353 var testSuite = []struct { 1354 inclTx bool 1355 fullTx bool 1356 want string 1357 }{ 1358 // without txs 1359 { 1360 inclTx: false, 1361 fullTx: false, 1362 want: `{ 1363 "difficulty": "0x0", 1364 "extraData": "0x", 1365 "gasLimit": "0x0", 1366 "gasUsed": "0x0", 1367 "hash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", 1368 "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 1369 "miner": "0x0000000000000000000000000000000000000000", 1370 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 1371 "nonce": "0x0000000000000000", 1372 "number": "0x64", 1373 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 1374 "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 1375 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 1376 "size": "0x296", 1377 "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", 1378 "timestamp": "0x0", 1379 "transactionsRoot": "0x661a9febcfa8f1890af549b874faf9fa274aede26ef489d9db0b25daa569450e", 1380 "uncles": [] 1381 }`, 1382 }, 1383 // only tx hashes 1384 { 1385 inclTx: true, 1386 fullTx: false, 1387 want: `{ 1388 "difficulty": "0x0", 1389 "extraData": "0x", 1390 "gasLimit": "0x0", 1391 "gasUsed": "0x0", 1392 "hash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", 1393 "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 1394 "miner": "0x0000000000000000000000000000000000000000", 1395 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 1396 "nonce": "0x0000000000000000", 1397 "number": "0x64", 1398 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 1399 "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 1400 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 1401 "size": "0x296", 1402 "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", 1403 "timestamp": "0x0", 1404 "transactions": [ 1405 "0x7d39df979e34172322c64983a9ad48302c2b889e55bda35324afecf043a77605", 1406 "0x9bba4c34e57c875ff57ac8d172805a26ae912006985395dc1bdf8f44140a7bf4", 1407 "0x98909ea1ff040da6be56bc4231d484de1414b3c1dac372d69293a4beb9032cb5", 1408 "0x12e1f81207b40c3bdcc13c0ee18f5f86af6d31754d57a0ea1b0d4cfef21abef1" 1409 ], 1410 "transactionsRoot": "0x661a9febcfa8f1890af549b874faf9fa274aede26ef489d9db0b25daa569450e", 1411 "uncles": [] 1412 }`, 1413 }, 1414 // full tx details 1415 { 1416 inclTx: true, 1417 fullTx: true, 1418 want: `{ 1419 "difficulty": "0x0", 1420 "extraData": "0x", 1421 "gasLimit": "0x0", 1422 "gasUsed": "0x0", 1423 "hash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", 1424 "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 1425 "miner": "0x0000000000000000000000000000000000000000", 1426 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 1427 "nonce": "0x0000000000000000", 1428 "number": "0x64", 1429 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 1430 "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 1431 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 1432 "size": "0x296", 1433 "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", 1434 "timestamp": "0x0", 1435 "transactions": [ 1436 { 1437 "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", 1438 "blockNumber": "0x64", 1439 "from": "0x0000000000000000000000000000000000000000", 1440 "gas": "0x457", 1441 "gasPrice": "0x2b67", 1442 "hash": "0x7d39df979e34172322c64983a9ad48302c2b889e55bda35324afecf043a77605", 1443 "input": "0x111111", 1444 "nonce": "0x1", 1445 "to": "0x0000000000000000000000000000000000000011", 1446 "transactionIndex": "0x0", 1447 "value": "0x6f", 1448 "type": "0x1", 1449 "accessList": [], 1450 "chainId": "0x539", 1451 "v": "0x0", 1452 "r": "0x0", 1453 "s": "0x0", 1454 "yParity": "0x0" 1455 }, 1456 { 1457 "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", 1458 "blockNumber": "0x64", 1459 "from": "0x0000000000000000000000000000000000000000", 1460 "gas": "0x457", 1461 "gasPrice": "0x2b67", 1462 "hash": "0x9bba4c34e57c875ff57ac8d172805a26ae912006985395dc1bdf8f44140a7bf4", 1463 "input": "0x111111", 1464 "nonce": "0x2", 1465 "to": "0x0000000000000000000000000000000000000011", 1466 "transactionIndex": "0x1", 1467 "value": "0x6f", 1468 "type": "0x0", 1469 "chainId": "0x7fffffffffffffee", 1470 "v": "0x0", 1471 "r": "0x0", 1472 "s": "0x0" 1473 }, 1474 { 1475 "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", 1476 "blockNumber": "0x64", 1477 "from": "0x0000000000000000000000000000000000000000", 1478 "gas": "0x457", 1479 "gasPrice": "0x2b67", 1480 "hash": "0x98909ea1ff040da6be56bc4231d484de1414b3c1dac372d69293a4beb9032cb5", 1481 "input": "0x111111", 1482 "nonce": "0x3", 1483 "to": "0x0000000000000000000000000000000000000011", 1484 "transactionIndex": "0x2", 1485 "value": "0x6f", 1486 "type": "0x1", 1487 "accessList": [], 1488 "chainId": "0x539", 1489 "v": "0x0", 1490 "r": "0x0", 1491 "s": "0x0", 1492 "yParity": "0x0" 1493 }, 1494 { 1495 "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", 1496 "blockNumber": "0x64", 1497 "from": "0x0000000000000000000000000000000000000000", 1498 "gas": "0x457", 1499 "gasPrice": "0x2b67", 1500 "hash": "0x12e1f81207b40c3bdcc13c0ee18f5f86af6d31754d57a0ea1b0d4cfef21abef1", 1501 "input": "0x111111", 1502 "nonce": "0x4", 1503 "to": "0x0000000000000000000000000000000000000011", 1504 "transactionIndex": "0x3", 1505 "value": "0x6f", 1506 "type": "0x0", 1507 "chainId": "0x7fffffffffffffee", 1508 "v": "0x0", 1509 "r": "0x0", 1510 "s": "0x0" 1511 } 1512 ], 1513 "transactionsRoot": "0x661a9febcfa8f1890af549b874faf9fa274aede26ef489d9db0b25daa569450e", 1514 "uncles": [] 1515 }`, 1516 }, 1517 } 1518 1519 for i, tc := range testSuite { 1520 resp := RPCMarshalBlock(block, tc.inclTx, tc.fullTx, params.MainnetChainConfig) 1521 out, err := json.Marshal(resp) 1522 if err != nil { 1523 t.Errorf("test %d: json marshal error: %v", i, err) 1524 continue 1525 } 1526 require.JSONEqf(t, tc.want, string(out), "test %d", i) 1527 } 1528 } 1529 1530 func TestRPCGetBlockOrHeader(t *testing.T) { 1531 t.Parallel() 1532 1533 // Initialize test accounts 1534 var ( 1535 acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1536 acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 1537 acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) 1538 acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) 1539 genesis = &core.Genesis{ 1540 Config: params.TestChainConfig, 1541 Alloc: types.GenesisAlloc{ 1542 acc1Addr: {Balance: big.NewInt(params.Ether)}, 1543 acc2Addr: {Balance: big.NewInt(params.Ether)}, 1544 }, 1545 } 1546 genBlocks = 10 1547 signer = types.HomesteadSigner{} 1548 tx = types.NewTx(&types.LegacyTx{ 1549 Nonce: 11, 1550 GasPrice: big.NewInt(11111), 1551 Gas: 1111, 1552 To: &acc2Addr, 1553 Value: big.NewInt(111), 1554 Data: []byte{0x11, 0x11, 0x11}, 1555 }) 1556 withdrawal = &types.Withdrawal{ 1557 Index: 0, 1558 Validator: 1, 1559 Address: common.Address{0x12, 0x34}, 1560 Amount: 10, 1561 } 1562 pending = types.NewBlock(&types.Header{Number: big.NewInt(11), Time: 42}, &types.Body{Transactions: types.Transactions{tx}, Withdrawals: types.Withdrawals{withdrawal}}, nil, blocktest.NewHasher()) 1563 ) 1564 backend := newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) { 1565 // Transfer from account[0] to account[1] 1566 // value: 1000 wei 1567 // fee: 0 wei 1568 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &acc2Addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, acc1Key) 1569 b.AddTx(tx) 1570 }) 1571 backend.setPendingBlock(pending) 1572 api := NewBlockChainAPI(backend) 1573 blockHashes := make([]common.Hash, genBlocks+1) 1574 ctx := context.Background() 1575 for i := 0; i <= genBlocks; i++ { 1576 header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(i)) 1577 if err != nil { 1578 t.Errorf("failed to get block: %d err: %v", i, err) 1579 } 1580 blockHashes[i] = header.Hash() 1581 } 1582 pendingHash := pending.Hash() 1583 1584 var testSuite = []struct { 1585 blockNumber rpc.BlockNumber 1586 blockHash *common.Hash 1587 fullTx bool 1588 reqHeader bool 1589 file string 1590 expectErr error 1591 }{ 1592 // 0. latest header 1593 { 1594 blockNumber: rpc.LatestBlockNumber, 1595 reqHeader: true, 1596 file: "tag-latest", 1597 }, 1598 // 1. genesis header 1599 { 1600 blockNumber: rpc.BlockNumber(0), 1601 reqHeader: true, 1602 file: "number-0", 1603 }, 1604 // 2. #1 header 1605 { 1606 blockNumber: rpc.BlockNumber(1), 1607 reqHeader: true, 1608 file: "number-1", 1609 }, 1610 // 3. latest-1 header 1611 { 1612 blockNumber: rpc.BlockNumber(9), 1613 reqHeader: true, 1614 file: "number-latest-1", 1615 }, 1616 // 4. latest+1 header 1617 { 1618 blockNumber: rpc.BlockNumber(11), 1619 reqHeader: true, 1620 file: "number-latest+1", 1621 }, 1622 // 5. pending header 1623 { 1624 blockNumber: rpc.PendingBlockNumber, 1625 reqHeader: true, 1626 file: "tag-pending", 1627 }, 1628 // 6. latest block 1629 { 1630 blockNumber: rpc.LatestBlockNumber, 1631 file: "tag-latest", 1632 }, 1633 // 7. genesis block 1634 { 1635 blockNumber: rpc.BlockNumber(0), 1636 file: "number-0", 1637 }, 1638 // 8. #1 block 1639 { 1640 blockNumber: rpc.BlockNumber(1), 1641 file: "number-1", 1642 }, 1643 // 9. latest-1 block 1644 { 1645 blockNumber: rpc.BlockNumber(9), 1646 fullTx: true, 1647 file: "number-latest-1", 1648 }, 1649 // 10. latest+1 block 1650 { 1651 blockNumber: rpc.BlockNumber(11), 1652 fullTx: true, 1653 file: "number-latest+1", 1654 }, 1655 // 11. pending block 1656 { 1657 blockNumber: rpc.PendingBlockNumber, 1658 file: "tag-pending", 1659 }, 1660 // 12. pending block + fullTx 1661 { 1662 blockNumber: rpc.PendingBlockNumber, 1663 fullTx: true, 1664 file: "tag-pending-fullTx", 1665 }, 1666 // 13. latest header by hash 1667 { 1668 blockHash: &blockHashes[len(blockHashes)-1], 1669 reqHeader: true, 1670 file: "hash-latest", 1671 }, 1672 // 14. genesis header by hash 1673 { 1674 blockHash: &blockHashes[0], 1675 reqHeader: true, 1676 file: "hash-0", 1677 }, 1678 // 15. #1 header 1679 { 1680 blockHash: &blockHashes[1], 1681 reqHeader: true, 1682 file: "hash-1", 1683 }, 1684 // 16. latest-1 header 1685 { 1686 blockHash: &blockHashes[len(blockHashes)-2], 1687 reqHeader: true, 1688 file: "hash-latest-1", 1689 }, 1690 // 17. empty hash 1691 { 1692 blockHash: &common.Hash{}, 1693 reqHeader: true, 1694 file: "hash-empty", 1695 }, 1696 // 18. pending hash 1697 { 1698 blockHash: &pendingHash, 1699 reqHeader: true, 1700 file: `hash-pending`, 1701 }, 1702 // 19. latest block 1703 { 1704 blockHash: &blockHashes[len(blockHashes)-1], 1705 file: "hash-latest", 1706 }, 1707 // 20. genesis block 1708 { 1709 blockHash: &blockHashes[0], 1710 file: "hash-genesis", 1711 }, 1712 // 21. #1 block 1713 { 1714 blockHash: &blockHashes[1], 1715 file: "hash-1", 1716 }, 1717 // 22. latest-1 block 1718 { 1719 blockHash: &blockHashes[len(blockHashes)-2], 1720 fullTx: true, 1721 file: "hash-latest-1-fullTx", 1722 }, 1723 // 23. empty hash + body 1724 { 1725 blockHash: &common.Hash{}, 1726 fullTx: true, 1727 file: "hash-empty-fullTx", 1728 }, 1729 // 24. pending block 1730 { 1731 blockHash: &pendingHash, 1732 file: `hash-pending`, 1733 }, 1734 // 25. pending block + fullTx 1735 { 1736 blockHash: &pendingHash, 1737 fullTx: true, 1738 file: "hash-pending-fullTx", 1739 }, 1740 } 1741 1742 for i, tt := range testSuite { 1743 var ( 1744 result map[string]interface{} 1745 err error 1746 rpc string 1747 ) 1748 if tt.blockHash != nil { 1749 if tt.reqHeader { 1750 result = api.GetHeaderByHash(context.Background(), *tt.blockHash) 1751 rpc = "eth_getHeaderByHash" 1752 } else { 1753 result, err = api.GetBlockByHash(context.Background(), *tt.blockHash, tt.fullTx) 1754 rpc = "eth_getBlockByHash" 1755 } 1756 } else { 1757 if tt.reqHeader { 1758 result, err = api.GetHeaderByNumber(context.Background(), tt.blockNumber) 1759 rpc = "eth_getHeaderByNumber" 1760 } else { 1761 result, err = api.GetBlockByNumber(context.Background(), tt.blockNumber, tt.fullTx) 1762 rpc = "eth_getBlockByNumber" 1763 } 1764 } 1765 if tt.expectErr != nil { 1766 if err == nil { 1767 t.Errorf("test %d: want error %v, have nothing", i, tt.expectErr) 1768 continue 1769 } 1770 if !errors.Is(err, tt.expectErr) { 1771 t.Errorf("test %d: error mismatch, want %v, have %v", i, tt.expectErr, err) 1772 } 1773 continue 1774 } 1775 if err != nil { 1776 t.Errorf("test %d: want no error, have %v", i, err) 1777 continue 1778 } 1779 1780 testRPCResponseWithFile(t, i, result, rpc, tt.file) 1781 } 1782 } 1783 1784 func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Hash) { 1785 config := *params.MergedTestChainConfig 1786 var ( 1787 acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1788 acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 1789 acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) 1790 acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) 1791 contract = common.HexToAddress("0000000000000000000000000000000000031ec7") 1792 genesis = &core.Genesis{ 1793 Config: &config, 1794 ExcessBlobGas: new(uint64), 1795 BlobGasUsed: new(uint64), 1796 Alloc: types.GenesisAlloc{ 1797 acc1Addr: {Balance: big.NewInt(params.Ether)}, 1798 acc2Addr: {Balance: big.NewInt(params.Ether)}, 1799 // // SPDX-License-Identifier: GPL-3.0 1800 // pragma solidity >=0.7.0 <0.9.0; 1801 // 1802 // contract Token { 1803 // event Transfer(address indexed from, address indexed to, uint256 value); 1804 // function transfer(address to, uint256 value) public returns (bool) { 1805 // emit Transfer(msg.sender, to, value); 1806 // return true; 1807 // } 1808 // } 1809 contract: {Balance: big.NewInt(params.Ether), Code: common.FromHex("0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a9059cbb14610030575b600080fd5b61004a6004803603810190610045919061016a565b610060565b60405161005791906101c5565b60405180910390f35b60008273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516100bf91906101ef565b60405180910390a36001905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610101826100d6565b9050919050565b610111816100f6565b811461011c57600080fd5b50565b60008135905061012e81610108565b92915050565b6000819050919050565b61014781610134565b811461015257600080fd5b50565b6000813590506101648161013e565b92915050565b60008060408385031215610181576101806100d1565b5b600061018f8582860161011f565b92505060206101a085828601610155565b9150509250929050565b60008115159050919050565b6101bf816101aa565b82525050565b60006020820190506101da60008301846101b6565b92915050565b6101e981610134565b82525050565b600060208201905061020460008301846101e0565b9291505056fea2646970667358221220b469033f4b77b9565ee84e0a2f04d496b18160d26034d54f9487e57788fd36d564736f6c63430008120033")}, 1810 }, 1811 } 1812 signer = types.LatestSignerForChainID(params.TestChainConfig.ChainID) 1813 txHashes = make([]common.Hash, genBlocks) 1814 ) 1815 1816 backend := newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { 1817 var ( 1818 tx *types.Transaction 1819 err error 1820 ) 1821 b.SetPoS() 1822 switch i { 1823 case 0: 1824 // transfer 1000wei 1825 tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &acc2Addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), types.HomesteadSigner{}, acc1Key) 1826 case 1: 1827 // create contract 1828 tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: nil, Gas: 53100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040")}), signer, acc1Key) 1829 case 2: 1830 // with logs 1831 // transfer(address to, uint256 value) 1832 data := fmt.Sprintf("0xa9059cbb%s%s", common.HexToHash(common.BigToAddress(big.NewInt(int64(i + 1))).Hex()).String()[2:], common.BytesToHash([]byte{byte(i + 11)}).String()[2:]) 1833 tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &contract, Gas: 60000, GasPrice: b.BaseFee(), Data: common.FromHex(data)}), signer, acc1Key) 1834 case 3: 1835 // dynamic fee with logs 1836 // transfer(address to, uint256 value) 1837 data := fmt.Sprintf("0xa9059cbb%s%s", common.HexToHash(common.BigToAddress(big.NewInt(int64(i + 1))).Hex()).String()[2:], common.BytesToHash([]byte{byte(i + 11)}).String()[2:]) 1838 fee := big.NewInt(500) 1839 fee.Add(fee, b.BaseFee()) 1840 tx, err = types.SignTx(types.NewTx(&types.DynamicFeeTx{Nonce: uint64(i), To: &contract, Gas: 60000, Value: big.NewInt(1), GasTipCap: big.NewInt(500), GasFeeCap: fee, Data: common.FromHex(data)}), signer, acc1Key) 1841 case 4: 1842 // access list with contract create 1843 accessList := types.AccessList{{ 1844 Address: contract, 1845 StorageKeys: []common.Hash{{0}}, 1846 }} 1847 tx, err = types.SignTx(types.NewTx(&types.AccessListTx{Nonce: uint64(i), To: nil, Gas: 58100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040"), AccessList: accessList}), signer, acc1Key) 1848 case 5: 1849 // blob tx 1850 fee := big.NewInt(500) 1851 fee.Add(fee, b.BaseFee()) 1852 tx, err = types.SignTx(types.NewTx(&types.BlobTx{ 1853 Nonce: uint64(i), 1854 GasTipCap: uint256.NewInt(1), 1855 GasFeeCap: uint256.MustFromBig(fee), 1856 Gas: params.TxGas, 1857 To: acc2Addr, 1858 BlobFeeCap: uint256.NewInt(1), 1859 BlobHashes: []common.Hash{{1}}, 1860 Value: new(uint256.Int), 1861 }), signer, acc1Key) 1862 } 1863 if err != nil { 1864 t.Errorf("failed to sign tx: %v", err) 1865 } 1866 if tx != nil { 1867 b.AddTx(tx) 1868 txHashes[i] = tx.Hash() 1869 } 1870 }) 1871 return backend, txHashes 1872 } 1873 1874 func TestRPCGetTransactionReceipt(t *testing.T) { 1875 t.Parallel() 1876 1877 var ( 1878 backend, txHashes = setupReceiptBackend(t, 6) 1879 api = NewTransactionAPI(backend, new(AddrLocker)) 1880 ) 1881 1882 var testSuite = []struct { 1883 txHash common.Hash 1884 file string 1885 }{ 1886 // 0. normal success 1887 { 1888 txHash: txHashes[0], 1889 file: "normal-transfer-tx", 1890 }, 1891 // 1. create contract 1892 { 1893 txHash: txHashes[1], 1894 file: "create-contract-tx", 1895 }, 1896 // 2. with logs success 1897 { 1898 txHash: txHashes[2], 1899 file: "with-logs", 1900 }, 1901 // 3. dynamic tx with logs success 1902 { 1903 txHash: txHashes[3], 1904 file: `dynamic-tx-with-logs`, 1905 }, 1906 // 4. access list tx with create contract 1907 { 1908 txHash: txHashes[4], 1909 file: "create-contract-with-access-list", 1910 }, 1911 // 5. txhash empty 1912 { 1913 txHash: common.Hash{}, 1914 file: "txhash-empty", 1915 }, 1916 // 6. txhash not found 1917 { 1918 txHash: common.HexToHash("deadbeef"), 1919 file: "txhash-notfound", 1920 }, 1921 // 7. blob tx 1922 { 1923 txHash: txHashes[5], 1924 file: "blob-tx", 1925 }, 1926 } 1927 1928 for i, tt := range testSuite { 1929 var ( 1930 result interface{} 1931 err error 1932 ) 1933 result, err = api.GetTransactionReceipt(context.Background(), tt.txHash) 1934 if err != nil { 1935 t.Errorf("test %d: want no error, have %v", i, err) 1936 continue 1937 } 1938 testRPCResponseWithFile(t, i, result, "eth_getTransactionReceipt", tt.file) 1939 } 1940 } 1941 1942 func TestRPCGetBlockReceipts(t *testing.T) { 1943 t.Parallel() 1944 1945 var ( 1946 genBlocks = 6 1947 backend, _ = setupReceiptBackend(t, genBlocks) 1948 api = NewBlockChainAPI(backend) 1949 ) 1950 blockHashes := make([]common.Hash, genBlocks+1) 1951 ctx := context.Background() 1952 for i := 0; i <= genBlocks; i++ { 1953 header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(i)) 1954 if err != nil { 1955 t.Errorf("failed to get block: %d err: %v", i, err) 1956 } 1957 blockHashes[i] = header.Hash() 1958 } 1959 1960 var testSuite = []struct { 1961 test rpc.BlockNumberOrHash 1962 file string 1963 }{ 1964 // 0. block without any txs(hash) 1965 { 1966 test: rpc.BlockNumberOrHashWithHash(blockHashes[0], false), 1967 file: "number-0", 1968 }, 1969 // 1. block without any txs(number) 1970 { 1971 test: rpc.BlockNumberOrHashWithNumber(0), 1972 file: "number-1", 1973 }, 1974 // 2. earliest tag 1975 { 1976 test: rpc.BlockNumberOrHashWithNumber(rpc.EarliestBlockNumber), 1977 file: "tag-earliest", 1978 }, 1979 // 3. latest tag 1980 { 1981 test: rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber), 1982 file: "tag-latest", 1983 }, 1984 // 4. block with legacy transfer tx(hash) 1985 { 1986 test: rpc.BlockNumberOrHashWithHash(blockHashes[1], false), 1987 file: "block-with-legacy-transfer-tx", 1988 }, 1989 // 5. block with contract create tx(number) 1990 { 1991 test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(2)), 1992 file: "block-with-contract-create-tx", 1993 }, 1994 // 6. block with legacy contract call tx(hash) 1995 { 1996 test: rpc.BlockNumberOrHashWithHash(blockHashes[3], false), 1997 file: "block-with-legacy-contract-call-tx", 1998 }, 1999 // 7. block with dynamic fee tx(number) 2000 { 2001 test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(4)), 2002 file: "block-with-dynamic-fee-tx", 2003 }, 2004 // 8. block is empty 2005 { 2006 test: rpc.BlockNumberOrHashWithHash(common.Hash{}, false), 2007 file: "hash-empty", 2008 }, 2009 // 9. block is not found 2010 { 2011 test: rpc.BlockNumberOrHashWithHash(common.HexToHash("deadbeef"), false), 2012 file: "hash-notfound", 2013 }, 2014 // 10. block is not found 2015 { 2016 test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(genBlocks + 1)), 2017 file: "block-notfound", 2018 }, 2019 // 11. block with blob tx 2020 { 2021 test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(6)), 2022 file: "block-with-blob-tx", 2023 }, 2024 } 2025 2026 for i, tt := range testSuite { 2027 var ( 2028 result interface{} 2029 err error 2030 ) 2031 result, err = api.GetBlockReceipts(context.Background(), tt.test) 2032 if err != nil { 2033 t.Errorf("test %d: want no error, have %v", i, err) 2034 continue 2035 } 2036 testRPCResponseWithFile(t, i, result, "eth_getBlockReceipts", tt.file) 2037 } 2038 } 2039 2040 func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc string, file string) { 2041 data, err := json.MarshalIndent(result, "", " ") 2042 if err != nil { 2043 t.Errorf("test %d: json marshal error", testid) 2044 return 2045 } 2046 outputFile := filepath.Join("testdata", fmt.Sprintf("%s-%s.json", rpc, file)) 2047 if os.Getenv("WRITE_TEST_FILES") != "" { 2048 os.WriteFile(outputFile, data, 0644) 2049 } 2050 want, err := os.ReadFile(outputFile) 2051 if err != nil { 2052 t.Fatalf("error reading expected test file: %s output: %v", outputFile, err) 2053 } 2054 require.JSONEqf(t, string(want), string(data), "test %d: json not match, want: %s, have: %s", testid, string(want), string(data)) 2055 }