github.com/ethereum-optimism/optimism/l2geth@v0.0.0-20230612200230-50b04ade19e3/rollup/sync_service_test.go (about) 1 package rollup 2 3 import ( 4 "context" 5 "crypto/rand" 6 "errors" 7 "fmt" 8 "math/big" 9 "reflect" 10 "sync" 11 "testing" 12 "time" 13 14 "github.com/ethereum-optimism/optimism/l2geth/common" 15 "github.com/ethereum-optimism/optimism/l2geth/consensus/ethash" 16 "github.com/ethereum-optimism/optimism/l2geth/core" 17 "github.com/ethereum-optimism/optimism/l2geth/core/rawdb" 18 "github.com/ethereum-optimism/optimism/l2geth/core/types" 19 "github.com/ethereum-optimism/optimism/l2geth/core/vm" 20 "github.com/ethereum-optimism/optimism/l2geth/crypto" 21 "github.com/ethereum-optimism/optimism/l2geth/eth/gasprice" 22 "github.com/ethereum-optimism/optimism/l2geth/ethdb" 23 "github.com/ethereum-optimism/optimism/l2geth/event" 24 "github.com/ethereum-optimism/optimism/l2geth/params" 25 "github.com/ethereum-optimism/optimism/l2geth/rollup/rcfg" 26 ) 27 28 // Test that the timestamps are updated correctly. 29 // This impacts execution, for `block.timestamp` 30 func TestSyncServiceTimestampUpdate(t *testing.T) { 31 service, txCh, _, err := newTestSyncService(false, nil) 32 if err != nil { 33 t.Fatal(err) 34 } 35 36 // Get the timestamp from the sync service 37 // It should be initialized to 0 38 ts := service.GetLatestL1Timestamp() 39 if ts != 0 { 40 t.Fatalf("Unexpected timestamp: %d", ts) 41 } 42 43 // Create a mock transaction and assert that its timestamp 44 // a value. This tests the case that the timestamp does 45 // not get malleated when it is set to a non zero value 46 timestamp := uint64(1) 47 tx1 := setMockTxL1Timestamp(mockTx(), timestamp) 48 if tx1.GetMeta().L1Timestamp != timestamp { 49 t.Fatalf("Expecting mock timestamp to be %d", timestamp) 50 } 51 if tx1.GetMeta().QueueOrigin != types.QueueOriginSequencer { 52 t.Fatalf("Expecting mock queue origin to be queue origin sequencer") 53 } 54 55 go func() { 56 err = service.applyTransactionToTip(tx1) 57 }() 58 event1 := <-txCh 59 60 // Ensure that the timestamp isn't malleated 61 if event1.Txs[0].GetMeta().L1Timestamp != timestamp { 62 t.Fatalf("Timestamp was malleated: %d", event1.Txs[0].GetMeta().L1Timestamp) 63 } 64 // Ensure that the timestamp in the sync service was updated 65 if service.GetLatestL1Timestamp() != timestamp { 66 t.Fatal("timestamp updated in sync service") 67 } 68 69 // Now test the case for when a transaction is malleated. 70 // If the timestamp is 0, then it should be malleated and set 71 // equal to whatever the latestL1Timestamp is 72 tx2 := mockTx() 73 if tx2.GetMeta().L1Timestamp != 0 { 74 t.Fatal("Expecting mock timestamp to be 0") 75 } 76 go func() { 77 err = service.applyTransactionToTip(tx2) 78 }() 79 event2 := <-txCh 80 81 // Ensure that the sync service timestamp is updated 82 if service.GetLatestL1Timestamp() == 0 { 83 t.Fatal("timestamp not updated") 84 } 85 // Ensure that the timestamp is malleated to be equal to what the sync 86 // service has as the latest timestamp 87 if event2.Txs[0].GetMeta().L1Timestamp != service.GetLatestL1Timestamp() { 88 t.Fatal("unexpected timestamp update") 89 } 90 91 // L1ToL2 transactions should have their timestamp malleated 92 // Be sure to set the timestamp to a non zero value so that 93 // its specifically testing the fact its a deposit tx 94 tx3 := setMockQueueOrigin(setMockTxL1Timestamp(mockTx(), 100), types.QueueOriginL1ToL2) 95 // Get a reference to the timestamp before transaction execution 96 ts3 := service.GetLatestL1Timestamp() 97 98 go func() { 99 err = service.applyTransactionToTip(tx3) 100 }() 101 event3 := <-txCh 102 103 if event3.Txs[0].GetMeta().L1Timestamp != ts3 { 104 t.Fatal("bad malleation") 105 } 106 // Ensure that the timestamp didn't change 107 if ts3 != service.GetLatestL1Timestamp() { 108 t.Fatal("timestamp updated when it shouldn't have") 109 } 110 } 111 112 // Test that the L1 blocknumber is updated correctly 113 func TestSyncServiceL1BlockNumberUpdate(t *testing.T) { 114 service, txCh, _, err := newTestSyncService(false, nil) 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 // Get the L1 blocknumber from the sync service 120 // It should be initialized to 0 121 bn := service.GetLatestL1BlockNumber() 122 if bn != 0 { 123 t.Fatalf("Unexpected timestamp: %d", bn) 124 } 125 126 tx1 := setMockTxL1BlockNumber(mockTx(), new(big.Int).SetUint64(1)) 127 go func() { 128 err = service.applyTransactionToTip(tx1) 129 }() 130 event1 := <-txCh 131 132 // Ensure that the L1 blocknumber was not 133 // malleated 134 if event1.Txs[0].L1BlockNumber().Uint64() != 1 { 135 t.Fatal("wrong l1 blocknumber") 136 } 137 138 // Ensure that the latest L1 blocknumber was 139 // updated 140 if service.GetLatestL1BlockNumber() != 1 { 141 t.Fatal("sync service latest l1 blocknumber not updated") 142 } 143 144 // Ensure that a tx without a L1 blocknumber gets one 145 // assigned 146 tx2 := setMockTxL1BlockNumber(mockTx(), nil) 147 if tx2.L1BlockNumber() != nil { 148 t.Fatal("non nil l1 blocknumber") 149 } 150 go func() { 151 err = service.applyTransactionToTip(tx2) 152 }() 153 event2 := <-txCh 154 155 if event2.Txs[0].L1BlockNumber() == nil { 156 t.Fatal("tx not assigned an l1 blocknumber") 157 } 158 if event2.Txs[0].L1BlockNumber().Uint64() != service.GetLatestL1BlockNumber() { 159 t.Fatal("tx assigned incorrect l1 blocknumber") 160 } 161 162 // Ensure that the latest L1 blocknumber doesn't go backwards 163 latest := service.GetLatestL1BlockNumber() 164 tx3 := setMockTxL1BlockNumber(mockTx(), new(big.Int).SetUint64(latest-1)) 165 go func() { 166 err = service.applyTransactionToTip(tx3) 167 }() 168 event3 := <-txCh 169 if service.GetLatestL1BlockNumber() != latest { 170 t.Fatal("block number went backwards") 171 } 172 173 if event3.Txs[0].L1BlockNumber().Uint64() != latest-1 { 174 t.Fatal("l1 block number was malleated") 175 } 176 } 177 178 // Test that the `RollupTransaction` ends up in the transaction cache 179 // after the transaction enqueued event is emitted. Set `false` as 180 // the argument to start as a sequencer 181 func TestSyncServiceTransactionEnqueued(t *testing.T) { 182 service, txCh, _, err := newTestSyncService(false, nil) 183 if err != nil { 184 t.Fatal(err) 185 } 186 187 // The timestamp is in the rollup transaction 188 timestamp := uint64(24) 189 // The target is the `to` field on the transaction 190 target := common.HexToAddress("0x04668ec2f57cc15c381b461b9fedab5d451c8f7f") 191 // The layer one transaction origin is in the txmeta on the transaction 192 l1TxOrigin := common.HexToAddress("0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8") 193 // The gasLimit is the `gasLimit` on the transaction 194 gasLimit := uint64(66) 195 // The data is the `data` on the transaction 196 data := []byte{0x02, 0x92} 197 // The L1 blocknumber for the transaction's evm context 198 l1BlockNumber := big.NewInt(100) 199 // The queue index of the L1 to L2 transaction 200 queueIndex := uint64(0) 201 // The index in the ctc 202 index := uint64(0) 203 204 tx := types.NewTransaction(0, target, big.NewInt(0), gasLimit, big.NewInt(0), data) 205 txMeta := types.NewTransactionMeta( 206 l1BlockNumber, 207 timestamp, 208 &l1TxOrigin, 209 types.QueueOriginL1ToL2, 210 &index, 211 &queueIndex, 212 nil, 213 ) 214 tx.SetTransactionMeta(txMeta) 215 216 setupMockClient(service, map[string]interface{}{ 217 "GetEnqueue": []*types.Transaction{ 218 tx, 219 }, 220 }) 221 222 // Run an iteration of the eloop 223 err = nil 224 go func() { 225 err = service.syncQueueToTip() 226 }() 227 // Wait for the tx to be confirmed into the chain and then 228 // make sure it is the transactions that was set up with in the mockclient 229 event := <-txCh 230 if err != nil { 231 t.Fatal("sequencing failed", err) 232 } 233 if len(event.Txs) != 1 { 234 t.Fatal("Unexpected number of transactions") 235 } 236 confirmed := event.Txs[0] 237 238 if !reflect.DeepEqual(tx, confirmed) { 239 t.Fatal("different txs") 240 } 241 } 242 243 func TestTransactionToTipNoIndex(t *testing.T) { 244 service, txCh, _, err := newTestSyncService(false, nil) 245 if err != nil { 246 t.Fatal(err) 247 } 248 249 // Get a reference to the current next index to compare with the index that 250 // is set to the transaction that is ingested 251 nextIndex := service.GetNextIndex() 252 253 timestamp := uint64(24) 254 target := common.HexToAddress("0x04668ec2f57cc15c381b461b9fedab5d451c8f7f") 255 l1TxOrigin := common.HexToAddress("0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8") 256 gasLimit := uint64(66) 257 data := []byte{0x02, 0x92} 258 l1BlockNumber := big.NewInt(100) 259 260 tx := types.NewTransaction(0, target, big.NewInt(0), gasLimit, big.NewInt(0), data) 261 meta := types.NewTransactionMeta( 262 l1BlockNumber, 263 timestamp, 264 &l1TxOrigin, 265 types.QueueOriginL1ToL2, 266 nil, // The index is `nil`, expect it to be set afterwards 267 nil, 268 nil, 269 ) 270 tx.SetTransactionMeta(meta) 271 272 go func() { 273 err = service.applyTransactionToTip(tx) 274 }() 275 event := <-txCh 276 if err != nil { 277 t.Fatal("Cannot apply transaction to the tip") 278 } 279 confirmed := event.Txs[0] 280 // The transaction was applied without an index so the chain gave it the 281 // next index 282 index := confirmed.GetMeta().Index 283 if index == nil { 284 t.Fatal("Did not set index after applying tx to tip") 285 } 286 if *index != *service.GetLatestIndex() { 287 t.Fatal("Incorrect latest index") 288 } 289 if *index != nextIndex { 290 t.Fatal("Incorrect index") 291 } 292 } 293 294 func TestTransactionToTipTimestamps(t *testing.T) { 295 service, txCh, _, err := newTestSyncService(false, nil) 296 if err != nil { 297 t.Fatal(err) 298 } 299 300 // Create two mock transactions with `nil` indices. This will allow 301 // assertions around the indices being updated correctly. Set the timestamp 302 // to 1 and 2 and assert that the timestamps in the sync service are updated 303 // correctly 304 tx1 := setMockTxL1Timestamp(mockTx(), 1) 305 tx2 := setMockTxL1Timestamp(mockTx(), 2) 306 307 txs := []*types.Transaction{ 308 tx1, 309 tx2, 310 } 311 312 for _, tx := range txs { 313 nextIndex := service.GetNextIndex() 314 315 go func() { 316 err = service.applyTransactionToTip(tx) 317 }() 318 event := <-txCh 319 if err != nil { 320 t.Fatal(err) 321 } 322 323 conf := event.Txs[0] 324 // The index should be set to the next 325 if conf.GetMeta().Index == nil { 326 t.Fatal("Index is nil") 327 } 328 // The index that the sync service is tracking should be updated 329 if *conf.GetMeta().Index != *service.GetLatestIndex() { 330 t.Fatal("index on the service was not updated") 331 } 332 // The indexes should be incrementing by 1 333 if *conf.GetMeta().Index != nextIndex { 334 t.Fatalf("Mismatched index: got %d, expect %d", *conf.GetMeta().Index, nextIndex) 335 } 336 // The tx timestamp should be setting the services timestamp 337 if conf.L1Timestamp() != service.GetLatestL1Timestamp() { 338 t.Fatal("Mismatched timestamp") 339 } 340 } 341 342 // Ensure that the timestamp was updated correctly 343 ts := service.GetLatestL1Timestamp() 344 if ts != tx2.L1Timestamp() { 345 t.Fatal("timestamp not updated correctly") 346 } 347 348 // Send a transaction with no timestamp and then let it be updated 349 // by the sync service. This will prevent monotonicity errors as well. 350 // as give timestamps to queue origin sequencer transactions 351 // Ensure that the timestamp is set to `time.Now` 352 // when it is not set. 353 tx3 := setMockTxL1Timestamp(mockTx(), 0) 354 now := time.Now() 355 go func() { 356 err = service.applyTransactionToTip(tx3) 357 }() 358 result := <-txCh 359 service.chainHeadCh <- core.ChainHeadEvent{} 360 361 if result.Txs[0].L1Timestamp() != uint64(now.Unix()) { 362 t.Fatal("Timestamp not updated correctly") 363 } 364 365 if service.GetLatestL1Timestamp() != uint64(now.Unix()) { 366 t.Fatal("latest timestamp not updated correctly") 367 } 368 } 369 370 func TestApplyIndexedTransaction(t *testing.T) { 371 service, txCh, _, err := newTestSyncService(true, nil) 372 if err != nil { 373 t.Fatal(err) 374 } 375 376 // Create three transactions, two of which have a duplicate index. 377 // The first two transactions can be ingested without a problem and the 378 // third transaction has a duplicate index so it will not be ingested. 379 // Expect an error for the third transaction and expect the SyncService 380 // global index to be updated with the first two transactions 381 tx0 := setMockTxIndex(mockTx(), 0) 382 tx1 := setMockTxIndex(mockTx(), 1) 383 tx1a := setMockTxIndex(mockTx(), 1) 384 385 go func() { 386 err = service.applyIndexedTransaction(tx0) 387 }() 388 <-txCh 389 if err != nil { 390 t.Fatal(err) 391 } 392 if *tx0.GetMeta().Index != *service.GetLatestIndex() { 393 t.Fatal("Latest index mismatch") 394 } 395 396 go func() { 397 err = service.applyIndexedTransaction(tx1) 398 }() 399 <-txCh 400 if err != nil { 401 t.Fatal(err) 402 } 403 if *tx1.GetMeta().Index != *service.GetLatestIndex() { 404 t.Fatal("Latest index mismatch") 405 } 406 407 err = service.applyIndexedTransaction(tx1a) 408 if err == nil { 409 t.Fatal(err) 410 } 411 } 412 413 func TestApplyBatchedTransaction(t *testing.T) { 414 service, txCh, _, err := newTestSyncService(true, nil) 415 if err != nil { 416 t.Fatal(err) 417 } 418 419 // Create a transactoin with the index of 0 420 tx0 := setMockTxIndex(mockTx(), 0) 421 422 // Ingest through applyBatchedTransaction which should set the latest 423 // verified index to the index of the transaction 424 go func() { 425 err = service.applyBatchedTransaction(tx0) 426 }() 427 service.chainHeadCh <- core.ChainHeadEvent{} 428 <-txCh 429 430 // Catch race conditions with the database write 431 wg := new(sync.WaitGroup) 432 wg.Add(1) 433 go func() { 434 for { 435 if service.GetLatestVerifiedIndex() != nil { 436 wg.Done() 437 return 438 } 439 time.Sleep(100 * time.Millisecond) 440 } 441 }() 442 wg.Wait() 443 444 // Assert that the verified index is the same as the transaction index 445 if *tx0.GetMeta().Index != *service.GetLatestVerifiedIndex() { 446 t.Fatal("Latest verified index mismatch") 447 } 448 } 449 450 func TestIsAtTip(t *testing.T) { 451 service, _, _, err := newTestSyncService(true, nil) 452 if err != nil { 453 t.Fatal(err) 454 } 455 456 data := []struct { 457 tip *uint64 458 get indexGetter 459 expect bool 460 err error 461 }{ 462 { 463 tip: newUint64(1), 464 get: func() (*uint64, error) { 465 return newUint64(1), nil 466 }, 467 expect: true, 468 err: nil, 469 }, 470 { 471 tip: newUint64(0), 472 get: func() (*uint64, error) { 473 return newUint64(1), nil 474 }, 475 expect: false, 476 err: nil, 477 }, 478 { 479 tip: newUint64(1), 480 get: func() (*uint64, error) { 481 return newUint64(0), nil 482 }, 483 expect: false, 484 err: errShortRemoteTip, 485 }, 486 { 487 tip: nil, 488 get: func() (*uint64, error) { 489 return nil, nil 490 }, 491 expect: true, 492 err: nil, 493 }, 494 { 495 tip: nil, 496 get: func() (*uint64, error) { 497 return nil, errElementNotFound 498 }, 499 expect: true, 500 err: nil, 501 }, 502 { 503 tip: newUint64(0), 504 get: func() (*uint64, error) { 505 return nil, errElementNotFound 506 }, 507 expect: false, 508 err: nil, 509 }, 510 } 511 512 for _, d := range data { 513 isAtTip, err := service.isAtTip(d.tip, d.get) 514 if isAtTip != d.expect { 515 t.Fatal("expected does not match") 516 } 517 if !errors.Is(err, d.err) { 518 t.Fatal("error no match") 519 } 520 } 521 } 522 523 func TestSyncQueue(t *testing.T) { 524 service, txCh, _, err := newTestSyncService(true, nil) 525 if err != nil { 526 t.Fatal(err) 527 } 528 529 setupMockClient(service, map[string]interface{}{ 530 "GetEnqueue": []*types.Transaction{ 531 setMockQueueIndex(mockTx(), 0), 532 setMockQueueIndex(mockTx(), 1), 533 setMockQueueIndex(mockTx(), 2), 534 setMockQueueIndex(mockTx(), 3), 535 }, 536 }) 537 538 var tip *uint64 539 go func() { 540 tip, err = service.syncQueue() 541 }() 542 543 for i := 0; i < 4; i++ { 544 service.chainHeadCh <- core.ChainHeadEvent{} 545 event := <-txCh 546 tx := event.Txs[0] 547 if *tx.GetMeta().QueueIndex != uint64(i) { 548 t.Fatal("queue index mismatch") 549 } 550 } 551 552 wg := new(sync.WaitGroup) 553 wg.Add(1) 554 go func() { 555 for { 556 if tip != nil { 557 wg.Done() 558 return 559 } 560 time.Sleep(100 * time.Millisecond) 561 } 562 }() 563 wg.Wait() 564 if tip == nil { 565 t.Fatal("tip is nil") 566 } 567 // There were a total of 4 transactions synced and the indexing starts at 0 568 if *service.GetLatestIndex() != 3 { 569 t.Fatalf("Latest index mismatch") 570 } 571 // All of the transactions are `enqueue()`s 572 if *service.GetLatestEnqueueIndex() != 3 { 573 t.Fatal("Latest queue index mismatch") 574 } 575 if *tip != 3 { 576 t.Fatal("Tip mismatch") 577 } 578 } 579 580 func TestSyncServiceL1GasPrice(t *testing.T) { 581 service, _, _, err := newTestSyncService(true, nil) 582 setupMockClient(service, map[string]interface{}{}) 583 584 if err != nil { 585 t.Fatal(err) 586 } 587 588 gasBefore, err := service.RollupGpo.SuggestL1GasPrice(context.Background()) 589 if err != nil { 590 t.Fatal(err) 591 } 592 593 if gasBefore.Cmp(big.NewInt(0)) != 0 { 594 t.Fatal("expected 0 gas price, got", gasBefore) 595 } 596 597 state, err := service.bc.State() 598 if err != nil { 599 t.Fatal("Cannot get state db") 600 } 601 l1GasPrice := big.NewInt(100000000000) 602 state.SetState(rcfg.L2GasPriceOracleAddress, rcfg.L1GasPriceSlot, common.BigToHash(l1GasPrice)) 603 _, _ = state.Commit(false) 604 605 // Update the gas price 606 service.updateL1GasPrice(state) 607 608 gasAfter, err := service.RollupGpo.SuggestL1GasPrice(context.Background()) 609 if err != nil { 610 t.Fatal(err) 611 } 612 613 if gasAfter.Cmp(l1GasPrice) != 0 { 614 t.Fatal("expected 100 gas price, got", gasAfter) 615 } 616 } 617 618 func TestSyncServiceL2GasPrice(t *testing.T) { 619 service, _, _, err := newTestSyncService(true, nil) 620 if err != nil { 621 t.Fatal(err) 622 } 623 624 price, err := service.RollupGpo.SuggestL2GasPrice(context.Background()) 625 if err != nil { 626 t.Fatal("Cannot fetch execution price") 627 } 628 629 if price.Cmp(common.Big0) != 0 { 630 t.Fatal("Incorrect gas price") 631 } 632 633 state, err := service.bc.State() 634 if err != nil { 635 t.Fatal("Cannot get state db") 636 } 637 l2GasPrice := big.NewInt(100000000000) 638 state.SetState(rcfg.L2GasPriceOracleAddress, rcfg.L2GasPriceSlot, common.BigToHash(l2GasPrice)) 639 _, _ = state.Commit(false) 640 641 service.updateL2GasPrice(state) 642 643 post, err := service.RollupGpo.SuggestL2GasPrice(context.Background()) 644 if err != nil { 645 t.Fatal("Cannot fetch execution price") 646 } 647 648 if l2GasPrice.Cmp(post) != 0 { 649 t.Fatal("Gas price not updated") 650 } 651 } 652 653 func TestSyncServiceGasPriceOracleOwnerAddress(t *testing.T) { 654 service, _, _, err := newTestSyncService(true, nil) 655 if err != nil { 656 t.Fatal(err) 657 } 658 // newTestSyncService doesn't set the initial owner address 659 // so it initializes to the zero value 660 owner := service.GasPriceOracleOwnerAddress() 661 if *owner != (common.Address{}) { 662 t.Fatal("address not initialized to 0") 663 } 664 665 state, err := service.bc.State() 666 if err != nil { 667 t.Fatal("cannot get state db") 668 } 669 670 // Update the owner in the state to a non zero address 671 updatedOwner := common.HexToAddress("0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8") 672 state.SetState(rcfg.L2GasPriceOracleAddress, rcfg.L2GasPriceOracleOwnerSlot, updatedOwner.Hash()) 673 hash, _ := state.Commit(false) 674 675 // Update the cache based on the latest state root 676 if err := service.updateGasPriceOracleCache(&hash); err != nil { 677 t.Fatal(err) 678 } 679 got := service.GasPriceOracleOwnerAddress() 680 if *got != updatedOwner { 681 t.Fatalf("mismatch:\ngot %s\nexpected %s", got.Hex(), updatedOwner.Hex()) 682 } 683 } 684 685 // Only the gas price oracle owner can send 0 gas price txs 686 // when fees are enforced 687 func TestFeeGasPriceOracleOwnerTransactions(t *testing.T) { 688 service, _, _, err := newTestSyncService(true, nil) 689 if err != nil { 690 t.Fatal(err) 691 } 692 signer := types.NewEIP155Signer(big.NewInt(420)) 693 694 // Fees must be enforced for this test 695 service.enforceFees = true 696 // Generate a key 697 key, _ := crypto.GenerateKey() 698 owner := crypto.PubkeyToAddress(key.PublicKey) 699 // Set as the owner on the SyncService 700 service.gasPriceOracleOwnerAddress = owner 701 if owner != *service.GasPriceOracleOwnerAddress() { 702 t.Fatal("owner mismatch") 703 } 704 // Create a mock transaction and sign using the 705 // owner's key 706 tx := mockTx() 707 // Make sure the gas price is 0 on the dummy tx 708 if tx.GasPrice().Cmp(common.Big0) != 0 { 709 t.Fatal("gas price not 0") 710 } 711 // Sign the dummy tx with the owner key 712 signedTx, err := types.SignTx(tx, signer, key) 713 if err != nil { 714 t.Fatal(err) 715 } 716 // Verify the fee of the signed tx, ensure it does not error 717 if err := service.verifyFee(signedTx); err != nil { 718 t.Fatal(err) 719 } 720 // Generate a new random key that is not the owner 721 badKey, _ := crypto.GenerateKey() 722 // Ensure that it is not the owner 723 if owner == crypto.PubkeyToAddress(badKey.PublicKey) { 724 t.Fatal("key mismatch") 725 } 726 // Sign the transaction with the bad key 727 badSignedTx, err := types.SignTx(tx, signer, badKey) 728 if err != nil { 729 t.Fatal(err) 730 } 731 // Attempt to verify the fee of the bad tx 732 // It should error and be a errZeroGasPriceTx 733 if err := service.verifyFee(badSignedTx); err != nil { 734 if !errors.Is(errZeroGasPriceTx, err) { 735 t.Fatal(err) 736 } 737 } else { 738 t.Fatal("err is nil") 739 } 740 } 741 742 // Pass true to set as a verifier 743 func TestSyncServiceSync(t *testing.T) { 744 service, txCh, sub, err := newTestSyncService(true, nil) 745 defer sub.Unsubscribe() 746 if err != nil { 747 t.Fatal(err) 748 } 749 750 timestamp := uint64(24) 751 target := common.HexToAddress("0x04668ec2f57cc15c381b461b9fedab5d451c8f7f") 752 l1TxOrigin := common.HexToAddress("0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8") 753 gasLimit := uint64(66) 754 data := []byte{0x02, 0x92} 755 l1BlockNumber := big.NewInt(100) 756 queueIndex := uint64(0) 757 index := uint64(0) 758 tx := types.NewTransaction(0, target, big.NewInt(0), gasLimit, big.NewInt(0), data) 759 txMeta := types.NewTransactionMeta( 760 l1BlockNumber, 761 timestamp, 762 &l1TxOrigin, 763 types.QueueOriginL1ToL2, 764 &index, 765 &queueIndex, 766 nil, 767 ) 768 tx.SetTransactionMeta(txMeta) 769 770 setupMockClient(service, map[string]interface{}{ 771 "GetTransaction": []*types.Transaction{ 772 tx, 773 }, 774 }) 775 776 err = nil 777 go func() { 778 err = service.syncTransactionsToTip() 779 }() 780 event := <-txCh 781 if err != nil { 782 t.Fatal("verification failed", err) 783 } 784 785 if len(event.Txs) != 1 { 786 t.Fatal("Unexpected number of transactions") 787 } 788 confirmed := event.Txs[0] 789 790 if !reflect.DeepEqual(tx, confirmed) { 791 t.Fatal("different txs") 792 } 793 } 794 795 func TestInitializeL1ContextPostGenesis(t *testing.T) { 796 service, _, _, err := newTestSyncService(true, nil) 797 if err != nil { 798 t.Fatal(err) 799 } 800 801 timestamp := uint64(24) 802 target := common.HexToAddress("0x04668ec2f57cc15c381b461b9fedab5d451c8f7f") 803 l1TxOrigin := common.HexToAddress("0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8") 804 gasLimit := uint64(66) 805 data := []byte{0x02, 0x92} 806 l1BlockNumber := big.NewInt(100) 807 queueIndex := uint64(100) 808 index := uint64(120) 809 tx := types.NewTransaction(0, target, big.NewInt(0), gasLimit, big.NewInt(0), data) 810 txMeta := types.NewTransactionMeta( 811 l1BlockNumber, 812 timestamp, 813 &l1TxOrigin, 814 types.QueueOriginL1ToL2, 815 &index, 816 &queueIndex, 817 nil, 818 ) 819 tx.SetTransactionMeta(txMeta) 820 821 setupMockClient(service, map[string]interface{}{ 822 "GetEnqueue": []*types.Transaction{ 823 tx, 824 }, 825 "GetEthContext": []*EthContext{ 826 { 827 BlockNumber: uint64(10), 828 BlockHash: common.Hash{}, 829 Timestamp: timestamp, 830 }, 831 }, 832 }) 833 834 header := types.Header{ 835 Number: big.NewInt(0), 836 Time: 11, 837 } 838 839 number := uint64(10) 840 tx.SetL1Timestamp(timestamp) 841 tx.SetL1BlockNumber(number) 842 block := types.NewBlock(&header, []*types.Transaction{tx}, []*types.Header{}, []*types.Receipt{}) 843 service.bc.SetCurrentBlock(block) 844 845 err = service.initializeLatestL1(big.NewInt(0)) 846 if err != nil { 847 t.Fatal(err) 848 } 849 850 latestL1Timestamp := service.GetLatestL1Timestamp() 851 latestL1BlockNumber := service.GetLatestL1BlockNumber() 852 if number != latestL1BlockNumber { 853 t.Fatalf("number does not match, got %d, expected %d", latestL1BlockNumber, number) 854 } 855 if latestL1Timestamp != timestamp { 856 t.Fatal("timestamp does not match") 857 } 858 } 859 860 func TestBadFeeThresholds(t *testing.T) { 861 // Create the deps for the sync service 862 cfg, txPool, chain, db, err := newTestSyncServiceDeps(false, nil) 863 if err != nil { 864 t.Fatal(err) 865 } 866 867 tests := map[string]struct { 868 thresholdUp *big.Float 869 thresholdDown *big.Float 870 err error 871 }{ 872 "nil-values": { 873 thresholdUp: nil, 874 thresholdDown: nil, 875 err: nil, 876 }, 877 "good-values": { 878 thresholdUp: new(big.Float).SetFloat64(2), 879 thresholdDown: new(big.Float).SetFloat64(0.8), 880 err: nil, 881 }, 882 "bad-value-up": { 883 thresholdUp: new(big.Float).SetFloat64(0.8), 884 thresholdDown: nil, 885 err: errBadConfig, 886 }, 887 "bad-value-down": { 888 thresholdUp: nil, 889 thresholdDown: new(big.Float).SetFloat64(1.1), 890 err: errBadConfig, 891 }, 892 } 893 894 for name, tt := range tests { 895 t.Run(name, func(t *testing.T) { 896 cfg.FeeThresholdDown = tt.thresholdDown 897 cfg.FeeThresholdUp = tt.thresholdUp 898 899 _, err := NewSyncService(context.Background(), cfg, txPool, chain, db) 900 if !errors.Is(err, tt.err) { 901 t.Fatalf("%s: %s", name, err) 902 } 903 }) 904 } 905 } 906 907 func newTestSyncServiceDeps(isVerifier bool, alloc *common.Address) (Config, *core.TxPool, *core.BlockChain, ethdb.Database, error) { 908 chainCfg := params.AllEthashProtocolChanges 909 chainID := big.NewInt(420) 910 chainCfg.ChainID = chainID 911 912 engine := ethash.NewFaker() 913 db := rawdb.NewMemoryDatabase() 914 genesis := new(core.Genesis) 915 if alloc != nil { 916 genesis.Alloc = make(core.GenesisAlloc) 917 genesis.Alloc[*alloc] = core.GenesisAccount{ 918 Balance: new(big.Int).SetUint64(100000000000000), 919 } 920 } 921 _ = genesis.MustCommit(db) 922 chain, err := core.NewBlockChain(db, nil, chainCfg, engine, vm.Config{}, nil) 923 if err != nil { 924 return Config{}, nil, nil, nil, fmt.Errorf("Cannot initialize blockchain: %w", err) 925 } 926 chaincfg := params.ChainConfig{ChainID: chainID} 927 928 txPool := core.NewTxPool(core.TxPoolConfig{PriceLimit: 0}, &chaincfg, chain) 929 cfg := Config{ 930 CanonicalTransactionChainDeployHeight: big.NewInt(0), 931 IsVerifier: isVerifier, 932 // Set as an empty string as this is a dummy value anyways. 933 // The client needs to be mocked with a mockClient 934 RollupClientHttp: "", 935 Backend: BackendL2, 936 } 937 return cfg, txPool, chain, db, nil 938 } 939 940 func newTestSyncService(isVerifier bool, alloc *common.Address) (*SyncService, chan core.NewTxsEvent, event.Subscription, error) { 941 cfg, txPool, chain, db, err := newTestSyncServiceDeps(isVerifier, alloc) 942 if err != nil { 943 return nil, nil, nil, fmt.Errorf("Cannot initialize syncservice: %w", err) 944 } 945 service, err := NewSyncService(context.Background(), cfg, txPool, chain, db) 946 if err != nil { 947 return nil, nil, nil, fmt.Errorf("Cannot initialize syncservice: %w", err) 948 } 949 950 service.RollupGpo = gasprice.NewRollupOracle() 951 txCh := make(chan core.NewTxsEvent, 1) 952 sub := service.SubscribeNewTxsEvent(txCh) 953 954 return service, txCh, sub, nil 955 } 956 957 type mockClient struct { 958 getEnqueueCallCount int 959 getEnqueue []*types.Transaction 960 getRawTransactionCallCount int 961 getRawTransaction []*TransactionResponse 962 getTransactionCallCount int 963 getTransaction []*types.Transaction 964 getEthContextCallCount int 965 getEthContext []*EthContext 966 getLatestEthContext *EthContext 967 getLatestEnqueueIndex []func() (*uint64, error) 968 getLatestEnqueueIndexCallCount int 969 } 970 971 func setupMockClient(service *SyncService, responses map[string]interface{}) { 972 client := newMockClient(responses) 973 service.client = client 974 service.RollupGpo = gasprice.NewRollupOracle() 975 } 976 977 func newMockClient(responses map[string]interface{}) *mockClient { 978 getEnqueueResponses := []*types.Transaction{} 979 getRawTransactionResponses := []*TransactionResponse{} 980 getTransactionResponses := []*types.Transaction{} 981 getEthContextResponses := []*EthContext{} 982 getLatestEthContextResponse := &EthContext{} 983 getLatestEnqueueIndexResponses := []func() (*uint64, error){} 984 985 enqueue, ok := responses["GetEnqueue"] 986 if ok { 987 getEnqueueResponses = enqueue.([]*types.Transaction) 988 } 989 getRawTx, ok := responses["GetRawTransaction"] 990 if ok { 991 getRawTransactionResponses = getRawTx.([]*TransactionResponse) 992 } 993 getTx, ok := responses["GetTransaction"] 994 if ok { 995 getTransactionResponses = getTx.([]*types.Transaction) 996 } 997 getCtx, ok := responses["GetEthContext"] 998 if ok { 999 getEthContextResponses = getCtx.([]*EthContext) 1000 } 1001 getLatestCtx, ok := responses["GetLatestEthContext"] 1002 if ok { 1003 getLatestEthContextResponse = getLatestCtx.(*EthContext) 1004 } 1005 getLatestEnqueueIdx, ok := responses["GetLatestEnqueueIndex"] 1006 if ok { 1007 getLatestEnqueueIndexResponses = getLatestEnqueueIdx.([]func() (*uint64, error)) 1008 } 1009 1010 return &mockClient{ 1011 getEnqueue: getEnqueueResponses, 1012 getRawTransaction: getRawTransactionResponses, 1013 getTransaction: getTransactionResponses, 1014 getEthContext: getEthContextResponses, 1015 getLatestEthContext: getLatestEthContextResponse, 1016 getLatestEnqueueIndex: getLatestEnqueueIndexResponses, 1017 } 1018 } 1019 1020 func (m *mockClient) GetEnqueue(index uint64) (*types.Transaction, error) { 1021 if m.getEnqueueCallCount < len(m.getEnqueue) { 1022 tx := m.getEnqueue[m.getEnqueueCallCount] 1023 m.getEnqueueCallCount++ 1024 return tx, nil 1025 } 1026 return nil, errors.New("") 1027 } 1028 1029 func (m *mockClient) GetLatestEnqueue() (*types.Transaction, error) { 1030 if len(m.getEnqueue) == 0 { 1031 return &types.Transaction{}, errors.New("enqueue not found") 1032 } 1033 return m.getEnqueue[len(m.getEnqueue)-1], nil 1034 } 1035 1036 func (m *mockClient) GetRawTransaction(index uint64, backend Backend) (*TransactionResponse, error) { 1037 if m.getRawTransactionCallCount < len(m.getRawTransaction) { 1038 tx := m.getRawTransaction[m.getRawTransactionCallCount] 1039 m.getRawTransactionCallCount++ 1040 return tx, nil 1041 } 1042 return nil, fmt.Errorf("Cannot get raw transaction: mocks (%d), call count (%d)", len(m.getRawTransaction), m.getRawTransactionCallCount) 1043 } 1044 1045 func (m *mockClient) GetTransaction(index uint64, backend Backend) (*types.Transaction, error) { 1046 if m.getTransactionCallCount < len(m.getTransaction) { 1047 tx := m.getTransaction[m.getTransactionCallCount] 1048 m.getTransactionCallCount++ 1049 return tx, nil 1050 } 1051 return nil, fmt.Errorf("Cannot get transaction: mocks (%d), call count (%d)", len(m.getTransaction), m.getTransactionCallCount) 1052 } 1053 1054 func (m *mockClient) GetLatestTransaction(backend Backend) (*types.Transaction, error) { 1055 if len(m.getTransaction) == 0 { 1056 return nil, errors.New("No transactions") 1057 } 1058 return m.getTransaction[len(m.getTransaction)-1], nil 1059 } 1060 1061 func (m *mockClient) GetEthContext(index uint64) (*EthContext, error) { 1062 if m.getEthContextCallCount < len(m.getEthContext) { 1063 ctx := m.getEthContext[m.getEthContextCallCount] 1064 m.getEthContextCallCount++ 1065 return ctx, nil 1066 } 1067 return nil, errors.New("Cannot get eth context") 1068 } 1069 1070 func (m *mockClient) GetLatestEthContext() (*EthContext, error) { 1071 return m.getLatestEthContext, nil 1072 } 1073 1074 func (m *mockClient) GetLastConfirmedEnqueue() (*types.Transaction, error) { 1075 return nil, errElementNotFound 1076 } 1077 1078 func (m *mockClient) GetLatestTransactionBatch() (*Batch, []*types.Transaction, error) { 1079 return nil, nil, nil 1080 } 1081 1082 func (m *mockClient) GetTransactionBatch(index uint64) (*Batch, []*types.Transaction, error) { 1083 return nil, nil, nil 1084 } 1085 1086 func (m *mockClient) SyncStatus(backend Backend) (*SyncStatus, error) { 1087 return &SyncStatus{ 1088 Syncing: false, 1089 }, nil 1090 } 1091 1092 func (m *mockClient) GetLatestEnqueueIndex() (*uint64, error) { 1093 enqueue, err := m.GetLatestEnqueue() 1094 if err != nil { 1095 return nil, err 1096 } 1097 if enqueue == nil { 1098 return nil, errElementNotFound 1099 } 1100 return enqueue.GetMeta().QueueIndex, nil 1101 } 1102 1103 func (m *mockClient) GetLatestTransactionBatchIndex() (*uint64, error) { 1104 return nil, nil 1105 } 1106 1107 func (m *mockClient) GetLatestTransactionIndex(backend Backend) (*uint64, error) { 1108 tx, err := m.GetLatestTransaction(backend) 1109 if err != nil { 1110 return nil, err 1111 } 1112 return tx.GetMeta().Index, nil 1113 } 1114 1115 func mockTx() *types.Transaction { 1116 address := make([]byte, 20) 1117 rand.Read(address) 1118 1119 target := common.BytesToAddress(address) 1120 timestamp := uint64(0) 1121 1122 rand.Read(address) 1123 l1TxOrigin := common.BytesToAddress(address) 1124 1125 gasLimit := uint64(0) 1126 data := []byte{0x00, 0x00} 1127 l1BlockNumber := big.NewInt(0) 1128 1129 tx := types.NewTransaction(0, target, big.NewInt(0), gasLimit, big.NewInt(0), data) 1130 meta := types.NewTransactionMeta( 1131 l1BlockNumber, 1132 timestamp, 1133 &l1TxOrigin, 1134 types.QueueOriginSequencer, 1135 nil, 1136 nil, 1137 nil, 1138 ) 1139 tx.SetTransactionMeta(meta) 1140 return tx 1141 } 1142 1143 func setMockTxL1Timestamp(tx *types.Transaction, ts uint64) *types.Transaction { 1144 meta := tx.GetMeta() 1145 meta.L1Timestamp = ts 1146 tx.SetTransactionMeta(meta) 1147 return tx 1148 } 1149 1150 func setMockTxL1BlockNumber(tx *types.Transaction, bn *big.Int) *types.Transaction { 1151 meta := tx.GetMeta() 1152 meta.L1BlockNumber = bn 1153 tx.SetTransactionMeta(meta) 1154 return tx 1155 } 1156 1157 func setMockTxIndex(tx *types.Transaction, index uint64) *types.Transaction { 1158 meta := tx.GetMeta() 1159 meta.Index = &index 1160 tx.SetTransactionMeta(meta) 1161 return tx 1162 } 1163 1164 func setMockQueueIndex(tx *types.Transaction, index uint64) *types.Transaction { 1165 meta := tx.GetMeta() 1166 meta.QueueIndex = &index 1167 tx.SetTransactionMeta(meta) 1168 return tx 1169 } 1170 1171 func setMockQueueOrigin(tx *types.Transaction, qo types.QueueOrigin) *types.Transaction { 1172 meta := tx.GetMeta() 1173 meta.QueueOrigin = qo 1174 tx.SetTransactionMeta(meta) 1175 return tx 1176 } 1177 1178 func newUint64(n uint64) *uint64 { 1179 return &n 1180 }