You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

603 lines
19 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package coordinator
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "math/big"
  7. "time"
  8. "github.com/ethereum/go-ethereum"
  9. "github.com/ethereum/go-ethereum/accounts"
  10. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  11. "github.com/ethereum/go-ethereum/core"
  12. "github.com/ethereum/go-ethereum/core/types"
  13. "github.com/hermeznetwork/hermez-node/common"
  14. "github.com/hermeznetwork/hermez-node/db/l2db"
  15. "github.com/hermeznetwork/hermez-node/eth"
  16. "github.com/hermeznetwork/hermez-node/log"
  17. "github.com/hermeznetwork/hermez-node/synchronizer"
  18. "github.com/hermeznetwork/tracerr"
  19. )
  20. // TxManager handles everything related to ethereum transactions: It makes the
  21. // call to forge, waits for transaction confirmation, and keeps checking them
  22. // until a number of confirmed blocks have passed.
  23. type TxManager struct {
  24. cfg Config
  25. ethClient eth.ClientInterface
  26. l2DB *l2db.L2DB // Used only to mark forged txs as forged in the L2DB
  27. coord *Coordinator // Used only to send messages to stop the pipeline
  28. batchCh chan *BatchInfo
  29. chainID *big.Int
  30. account accounts.Account
  31. consts synchronizer.SCConsts
  32. stats synchronizer.Stats
  33. vars synchronizer.SCVariables
  34. statsVarsCh chan statsVars
  35. discardPipelineCh chan int // int refers to the pipelineNum
  36. minPipelineNum int
  37. queue Queue
  38. // lastSuccessBatch stores the last BatchNum that who's forge call was confirmed
  39. lastSuccessBatch common.BatchNum
  40. // lastPendingBatch common.BatchNum
  41. // accNonce is the account nonce in the last mined block (due to mined txs)
  42. accNonce uint64
  43. // accNextNonce is the nonce that we should use to send the next tx.
  44. // In some cases this will be a reused nonce of an already pending tx.
  45. accNextNonce uint64
  46. // accPendingNonce is the pending nonce of the account due to pending txs
  47. // accPendingNonce uint64
  48. lastSentL1BatchBlockNum int64
  49. }
  50. // NewTxManager creates a new TxManager
  51. func NewTxManager(ctx context.Context, cfg *Config, ethClient eth.ClientInterface, l2DB *l2db.L2DB,
  52. coord *Coordinator, scConsts *synchronizer.SCConsts, initSCVars *synchronizer.SCVariables) (*TxManager, error) {
  53. chainID, err := ethClient.EthChainID()
  54. if err != nil {
  55. return nil, tracerr.Wrap(err)
  56. }
  57. address, err := ethClient.EthAddress()
  58. if err != nil {
  59. return nil, tracerr.Wrap(err)
  60. }
  61. accNonce, err := ethClient.EthNonceAt(ctx, *address, nil)
  62. if err != nil {
  63. return nil, err
  64. }
  65. // accPendingNonce, err := ethClient.EthPendingNonceAt(ctx, *address)
  66. // if err != nil {
  67. // return nil, err
  68. // }
  69. // if accNonce != accPendingNonce {
  70. // return nil, tracerr.Wrap(fmt.Errorf("currentNonce (%v) != accPendingNonce (%v)",
  71. // accNonce, accPendingNonce))
  72. // }
  73. log.Infow("TxManager started", "nonce", accNonce)
  74. return &TxManager{
  75. cfg: *cfg,
  76. ethClient: ethClient,
  77. l2DB: l2DB,
  78. coord: coord,
  79. batchCh: make(chan *BatchInfo, queueLen),
  80. statsVarsCh: make(chan statsVars, queueLen),
  81. discardPipelineCh: make(chan int, queueLen),
  82. account: accounts.Account{
  83. Address: *address,
  84. },
  85. chainID: chainID,
  86. consts: *scConsts,
  87. vars: *initSCVars,
  88. minPipelineNum: 0,
  89. queue: NewQueue(),
  90. accNonce: accNonce,
  91. accNextNonce: accNonce,
  92. // accPendingNonce: accPendingNonce,
  93. }, nil
  94. }
  95. // AddBatch is a thread safe method to pass a new batch TxManager to be sent to
  96. // the smart contract via the forge call
  97. func (t *TxManager) AddBatch(ctx context.Context, batchInfo *BatchInfo) {
  98. select {
  99. case t.batchCh <- batchInfo:
  100. case <-ctx.Done():
  101. }
  102. }
  103. // SetSyncStatsVars is a thread safe method to sets the synchronizer Stats
  104. func (t *TxManager) SetSyncStatsVars(ctx context.Context, stats *synchronizer.Stats, vars *synchronizer.SCVariablesPtr) {
  105. select {
  106. case t.statsVarsCh <- statsVars{Stats: *stats, Vars: *vars}:
  107. case <-ctx.Done():
  108. }
  109. }
  110. // DiscardPipeline is a thread safe method to notify about a discarded pipeline
  111. // due to a reorg
  112. func (t *TxManager) DiscardPipeline(ctx context.Context, pipelineNum int) {
  113. select {
  114. case t.discardPipelineCh <- pipelineNum:
  115. case <-ctx.Done():
  116. }
  117. }
  118. func (t *TxManager) syncSCVars(vars synchronizer.SCVariablesPtr) {
  119. updateSCVars(&t.vars, vars)
  120. }
  121. // NewAuth generates a new auth object for an ethereum transaction
  122. func (t *TxManager) NewAuth(ctx context.Context) (*bind.TransactOpts, error) {
  123. gasPrice, err := t.ethClient.EthSuggestGasPrice(ctx)
  124. if err != nil {
  125. return nil, tracerr.Wrap(err)
  126. }
  127. inc := new(big.Int).Set(gasPrice)
  128. const gasPriceDiv = 100
  129. inc.Div(inc, new(big.Int).SetUint64(gasPriceDiv))
  130. gasPrice.Add(gasPrice, inc)
  131. // log.Debugw("TxManager: transaction metadata", "gasPrice", gasPrice)
  132. auth, err := bind.NewKeyStoreTransactorWithChainID(t.ethClient.EthKeyStore(), t.account, t.chainID)
  133. if err != nil {
  134. return nil, tracerr.Wrap(err)
  135. }
  136. auth.Value = big.NewInt(0) // in wei
  137. // TODO: Calculate GasLimit based on the contents of the ForgeBatchArgs
  138. auth.GasLimit = 1000000
  139. auth.GasPrice = gasPrice
  140. auth.Nonce = nil
  141. return auth, nil
  142. }
  143. func (t *TxManager) shouldSendRollupForgeBatch(batchInfo *BatchInfo) error {
  144. nextBlock := t.stats.Eth.LastBlock.Num + 1
  145. if !t.canForgeAt(nextBlock) {
  146. return tracerr.Wrap(fmt.Errorf("can't forge in the next block: %v", nextBlock))
  147. }
  148. if t.mustL1L2Batch(nextBlock) && !batchInfo.L1Batch {
  149. return tracerr.Wrap(fmt.Errorf("can't forge non-L1Batch in the next block: %v", nextBlock))
  150. }
  151. margin := t.cfg.SendBatchBlocksMarginCheck
  152. if margin != 0 {
  153. if !t.canForgeAt(nextBlock + margin) {
  154. return tracerr.Wrap(fmt.Errorf("can't forge after %v blocks: %v",
  155. margin, nextBlock))
  156. }
  157. if t.mustL1L2Batch(nextBlock+margin) && !batchInfo.L1Batch {
  158. return tracerr.Wrap(fmt.Errorf("can't forge non-L1Batch after %v blocks: %v",
  159. margin, nextBlock))
  160. }
  161. }
  162. return nil
  163. }
  164. func addPerc(v *big.Int, p int64) *big.Int {
  165. r := new(big.Int).Set(v)
  166. r.Mul(r, big.NewInt(p))
  167. // nolint reason: to calculate percetnages we divide by 100
  168. r.Div(r, big.NewInt(100)) //nolit:gomnd
  169. return r.Add(v, r)
  170. }
  171. func (t *TxManager) sendRollupForgeBatch(ctx context.Context, batchInfo *BatchInfo, resend bool) error {
  172. var ethTx *types.Transaction
  173. var err error
  174. auth, err := t.NewAuth(ctx)
  175. if err != nil {
  176. return tracerr.Wrap(err)
  177. }
  178. auth.Nonce = big.NewInt(int64(t.accNextNonce))
  179. if resend {
  180. auth.Nonce = big.NewInt(int64(batchInfo.EthTx.Nonce()))
  181. }
  182. for attempt := 0; attempt < t.cfg.EthClientAttempts; attempt++ {
  183. if auth.GasPrice.Cmp(t.cfg.MaxGasPrice) > 0 {
  184. return tracerr.Wrap(fmt.Errorf("calculated gasPrice (%v) > maxGasPrice (%v)",
  185. auth.GasPrice, t.cfg.MaxGasPrice))
  186. }
  187. // RollupForgeBatch() calls ethclient.SendTransaction()
  188. ethTx, err = t.ethClient.RollupForgeBatch(batchInfo.ForgeBatchArgs, auth)
  189. if errors.Is(err, core.ErrNonceTooLow) {
  190. log.Warnw("TxManager ethClient.RollupForgeBatch incrementing nonce",
  191. "err", err, "nonce", auth.Nonce, "batchNum", batchInfo.BatchNum)
  192. auth.Nonce.Add(auth.Nonce, big.NewInt(1))
  193. attempt--
  194. } else if errors.Is(err, core.ErrNonceTooHigh) {
  195. log.Warnw("TxManager ethClient.RollupForgeBatch decrementing nonce",
  196. "err", err, "nonce", auth.Nonce, "batchNum", batchInfo.BatchNum)
  197. auth.Nonce.Sub(auth.Nonce, big.NewInt(1))
  198. attempt--
  199. } else if errors.Is(err, core.ErrUnderpriced) {
  200. log.Warnw("TxManager ethClient.RollupForgeBatch incrementing gasPrice",
  201. "err", err, "gasPrice", auth.GasPrice, "batchNum", batchInfo.BatchNum)
  202. auth.GasPrice = addPerc(auth.GasPrice, 10)
  203. attempt--
  204. } else if errors.Is(err, core.ErrReplaceUnderpriced) {
  205. log.Warnw("TxManager ethClient.RollupForgeBatch incrementing gasPrice",
  206. "err", err, "gasPrice", auth.GasPrice, "batchNum", batchInfo.BatchNum)
  207. auth.GasPrice = addPerc(auth.GasPrice, 10)
  208. attempt--
  209. } else if err != nil {
  210. log.Errorw("TxManager ethClient.RollupForgeBatch",
  211. "attempt", attempt, "err", err, "block", t.stats.Eth.LastBlock.Num+1,
  212. "batchNum", batchInfo.BatchNum)
  213. } else {
  214. break
  215. }
  216. select {
  217. case <-ctx.Done():
  218. return tracerr.Wrap(common.ErrDone)
  219. case <-time.After(t.cfg.EthClientAttemptsDelay):
  220. }
  221. }
  222. if err != nil {
  223. return tracerr.Wrap(fmt.Errorf("reached max attempts for ethClient.RollupForgeBatch: %w", err))
  224. }
  225. if !resend {
  226. t.accNextNonce = auth.Nonce.Uint64() + 1
  227. }
  228. batchInfo.EthTx = ethTx
  229. log.Infow("TxManager ethClient.RollupForgeBatch", "batch", batchInfo.BatchNum, "tx", ethTx.Hash())
  230. now := time.Now()
  231. batchInfo.SendTimestamp = now
  232. if resend {
  233. batchInfo.Debug.ResendNum++
  234. }
  235. batchInfo.Debug.Status = StatusSent
  236. batchInfo.Debug.SendBlockNum = t.stats.Eth.LastBlock.Num + 1
  237. batchInfo.Debug.SendTimestamp = batchInfo.SendTimestamp
  238. batchInfo.Debug.StartToSendDelay = batchInfo.Debug.SendTimestamp.Sub(
  239. batchInfo.Debug.StartTimestamp).Seconds()
  240. t.cfg.debugBatchStore(batchInfo)
  241. // t.lastPendingBatch = batchInfo.BatchNum
  242. if !resend {
  243. if batchInfo.L1Batch {
  244. t.lastSentL1BatchBlockNum = t.stats.Eth.LastBlock.Num + 1
  245. }
  246. }
  247. if err := t.l2DB.DoneForging(common.TxIDsFromL2Txs(batchInfo.L2Txs), batchInfo.BatchNum); err != nil {
  248. return tracerr.Wrap(err)
  249. }
  250. return nil
  251. }
  252. // checkEthTransactionReceipt takes the txHash from the BatchInfo and stores
  253. // the corresponding receipt if found
  254. func (t *TxManager) checkEthTransactionReceipt(ctx context.Context, batchInfo *BatchInfo) error {
  255. txHash := batchInfo.EthTx.Hash()
  256. var receipt *types.Receipt
  257. var err error
  258. for attempt := 0; attempt < t.cfg.EthClientAttempts; attempt++ {
  259. receipt, err = t.ethClient.EthTransactionReceipt(ctx, txHash)
  260. if ctx.Err() != nil {
  261. continue
  262. } else if tracerr.Unwrap(err) == ethereum.NotFound {
  263. err = nil
  264. break
  265. } else if err != nil {
  266. log.Errorw("TxManager ethClient.EthTransactionReceipt",
  267. "attempt", attempt, "err", err)
  268. } else {
  269. break
  270. }
  271. select {
  272. case <-ctx.Done():
  273. return tracerr.Wrap(common.ErrDone)
  274. case <-time.After(t.cfg.EthClientAttemptsDelay):
  275. }
  276. }
  277. if err != nil {
  278. return tracerr.Wrap(fmt.Errorf("reached max attempts for ethClient.EthTransactionReceipt: %w", err))
  279. }
  280. batchInfo.Receipt = receipt
  281. t.cfg.debugBatchStore(batchInfo)
  282. return nil
  283. }
  284. func (t *TxManager) handleReceipt(ctx context.Context, batchInfo *BatchInfo) (*int64, error) {
  285. receipt := batchInfo.Receipt
  286. if receipt != nil {
  287. if batchInfo.EthTx.Nonce()+1 > t.accNonce {
  288. t.accNonce = batchInfo.EthTx.Nonce() + 1
  289. }
  290. if receipt.Status == types.ReceiptStatusFailed {
  291. batchInfo.Debug.Status = StatusFailed
  292. t.cfg.debugBatchStore(batchInfo)
  293. _, err := t.ethClient.EthCall(ctx, batchInfo.EthTx, receipt.BlockNumber)
  294. log.Warnw("TxManager receipt status is failed", "tx", receipt.TxHash,
  295. "batch", batchInfo.BatchNum, "block", receipt.BlockNumber.Int64(),
  296. "err", err)
  297. if batchInfo.BatchNum <= t.lastSuccessBatch {
  298. t.lastSuccessBatch = batchInfo.BatchNum - 1
  299. }
  300. return nil, tracerr.Wrap(fmt.Errorf(
  301. "ethereum transaction receipt status is failed: %w", err))
  302. } else if receipt.Status == types.ReceiptStatusSuccessful {
  303. batchInfo.Debug.Status = StatusMined
  304. batchInfo.Debug.MineBlockNum = receipt.BlockNumber.Int64()
  305. batchInfo.Debug.StartToMineBlocksDelay = batchInfo.Debug.MineBlockNum -
  306. batchInfo.Debug.StartBlockNum
  307. if batchInfo.Debug.StartToMineDelay == 0 {
  308. if block, err := t.ethClient.EthBlockByNumber(ctx,
  309. receipt.BlockNumber.Int64()); err != nil {
  310. log.Warnw("TxManager: ethClient.EthBlockByNumber", "err", err)
  311. } else {
  312. batchInfo.Debug.SendToMineDelay = block.Timestamp.Sub(
  313. batchInfo.Debug.SendTimestamp).Seconds()
  314. batchInfo.Debug.StartToMineDelay = block.Timestamp.Sub(
  315. batchInfo.Debug.StartTimestamp).Seconds()
  316. }
  317. }
  318. t.cfg.debugBatchStore(batchInfo)
  319. if batchInfo.BatchNum > t.lastSuccessBatch {
  320. t.lastSuccessBatch = batchInfo.BatchNum
  321. }
  322. confirm := t.stats.Eth.LastBlock.Num - receipt.BlockNumber.Int64()
  323. return &confirm, nil
  324. }
  325. }
  326. return nil, nil
  327. }
  328. // TODO:
  329. // - After sending a message: CancelPipeline, stop all consecutive pending Batches (transactions)
  330. // Queue of BatchInfos
  331. type Queue struct {
  332. list []*BatchInfo
  333. // nonceByBatchNum map[common.BatchNum]uint64
  334. next int
  335. }
  336. // NewQueue returns a new queue
  337. func NewQueue() Queue {
  338. return Queue{
  339. list: make([]*BatchInfo, 0),
  340. // nonceByBatchNum: make(map[common.BatchNum]uint64),
  341. next: 0,
  342. }
  343. }
  344. // Len is the length of the queue
  345. func (q *Queue) Len() int {
  346. return len(q.list)
  347. }
  348. // At returns the BatchInfo at position (or nil if position is out of bounds)
  349. func (q *Queue) At(position int) *BatchInfo {
  350. if position >= len(q.list) {
  351. return nil
  352. }
  353. return q.list[position]
  354. }
  355. // Next returns the next BatchInfo (or nil if queue is empty)
  356. func (q *Queue) Next() (int, *BatchInfo) {
  357. if len(q.list) == 0 {
  358. return 0, nil
  359. }
  360. defer func() { q.next = (q.next + 1) % len(q.list) }()
  361. return q.next, q.list[q.next]
  362. }
  363. // Remove removes the BatchInfo at position
  364. func (q *Queue) Remove(position int) {
  365. // batchInfo := q.list[position]
  366. // delete(q.nonceByBatchNum, batchInfo.BatchNum)
  367. q.list = append(q.list[:position], q.list[position+1:]...)
  368. if len(q.list) == 0 {
  369. q.next = 0
  370. } else {
  371. q.next = position % len(q.list)
  372. }
  373. }
  374. // Push adds a new BatchInfo
  375. func (q *Queue) Push(batchInfo *BatchInfo) {
  376. q.list = append(q.list, batchInfo)
  377. // q.nonceByBatchNum[batchInfo.BatchNum] = batchInfo.EthTx.Nonce()
  378. }
  379. // func (q *Queue) NonceByBatchNum(batchNum common.BatchNum) (uint64, bool) {
  380. // nonce, ok := q.nonceByBatchNum[batchNum]
  381. // return nonce, ok
  382. // }
  383. // Run the TxManager
  384. func (t *TxManager) Run(ctx context.Context) {
  385. waitDuration := longWaitDuration
  386. var statsVars statsVars
  387. select {
  388. case statsVars = <-t.statsVarsCh:
  389. case <-ctx.Done():
  390. }
  391. t.stats = statsVars.Stats
  392. t.syncSCVars(statsVars.Vars)
  393. log.Infow("TxManager: received initial statsVars",
  394. "block", t.stats.Eth.LastBlock.Num, "batch", t.stats.Eth.LastBatchNum)
  395. for {
  396. select {
  397. case <-ctx.Done():
  398. log.Info("TxManager done")
  399. return
  400. case statsVars := <-t.statsVarsCh:
  401. t.stats = statsVars.Stats
  402. t.syncSCVars(statsVars.Vars)
  403. case pipelineNum := <-t.discardPipelineCh:
  404. t.minPipelineNum = pipelineNum + 1
  405. if err := t.removeBadBatchInfos(ctx); ctx.Err() != nil {
  406. continue
  407. } else if err != nil {
  408. log.Errorw("TxManager: removeBadBatchInfos", "err", err)
  409. continue
  410. }
  411. case batchInfo := <-t.batchCh:
  412. if batchInfo.PipelineNum < t.minPipelineNum {
  413. log.Warnw("TxManager: batchInfo received pipelineNum < minPipelineNum",
  414. "num", batchInfo.PipelineNum, "minNum", t.minPipelineNum)
  415. }
  416. if err := t.shouldSendRollupForgeBatch(batchInfo); err != nil {
  417. log.Warnw("TxManager: shouldSend", "err", err,
  418. "batch", batchInfo.BatchNum)
  419. t.coord.SendMsg(ctx, MsgStopPipeline{
  420. Reason: fmt.Sprintf("forgeBatch shouldSend: %v", err)})
  421. continue
  422. }
  423. if err := t.sendRollupForgeBatch(ctx, batchInfo, false); ctx.Err() != nil {
  424. continue
  425. } else if err != nil {
  426. // If we reach here it's because our ethNode has
  427. // been unable to send the transaction to
  428. // ethereum. This could be due to the ethNode
  429. // failure, or an invalid transaction (that
  430. // can't be mined)
  431. log.Warnw("TxManager: forgeBatch send failed", "err", err,
  432. "batch", batchInfo.BatchNum)
  433. t.coord.SendMsg(ctx, MsgStopPipeline{
  434. Reason: fmt.Sprintf("forgeBatch send: %v", err)})
  435. continue
  436. }
  437. t.queue.Push(batchInfo)
  438. waitDuration = t.cfg.TxManagerCheckInterval
  439. case <-time.After(waitDuration):
  440. queuePosition, batchInfo := t.queue.Next()
  441. if batchInfo == nil {
  442. waitDuration = longWaitDuration
  443. continue
  444. }
  445. if err := t.checkEthTransactionReceipt(ctx, batchInfo); ctx.Err() != nil {
  446. continue
  447. } else if err != nil { //nolint:staticcheck
  448. // Our ethNode is giving an error different
  449. // than "not found" when getting the receipt
  450. // for the transaction, so we can't figure out
  451. // if it was not mined, mined and succesfull or
  452. // mined and failed. This could be due to the
  453. // ethNode failure.
  454. t.coord.SendMsg(ctx, MsgStopPipeline{
  455. Reason: fmt.Sprintf("forgeBatch receipt: %v", err)})
  456. }
  457. confirm, err := t.handleReceipt(ctx, batchInfo)
  458. if ctx.Err() != nil {
  459. continue
  460. } else if err != nil { //nolint:staticcheck
  461. // Transaction was rejected
  462. if err := t.removeBadBatchInfos(ctx); ctx.Err() != nil {
  463. continue
  464. } else if err != nil {
  465. log.Errorw("TxManager: removeBadBatchInfos", "err", err)
  466. continue
  467. }
  468. t.coord.SendMsg(ctx, MsgStopPipeline{
  469. Reason: fmt.Sprintf("forgeBatch reject: %v", err)})
  470. continue
  471. }
  472. now := time.Now()
  473. if !t.cfg.EthNoReuseNonce && confirm == nil &&
  474. now.Sub(batchInfo.SendTimestamp) > t.cfg.EthTxResendTimeout {
  475. log.Infow("TxManager: forgeBatch tx not been mined timeout, resending",
  476. "tx", batchInfo.EthTx.Hash(), "batch", batchInfo.BatchNum)
  477. if err := t.sendRollupForgeBatch(ctx, batchInfo, true); ctx.Err() != nil {
  478. continue
  479. } else if err != nil {
  480. // If we reach here it's because our ethNode has
  481. // been unable to send the transaction to
  482. // ethereum. This could be due to the ethNode
  483. // failure, or an invalid transaction (that
  484. // can't be mined)
  485. log.Warnw("TxManager: forgeBatch resend failed", "err", err,
  486. "batch", batchInfo.BatchNum)
  487. t.coord.SendMsg(ctx, MsgStopPipeline{
  488. Reason: fmt.Sprintf("forgeBatch resend: %v", err)})
  489. continue
  490. }
  491. }
  492. if confirm != nil && *confirm >= t.cfg.ConfirmBlocks {
  493. log.Debugw("TxManager: forgeBatch tx confirmed",
  494. "tx", batchInfo.EthTx.Hash(), "batch", batchInfo.BatchNum)
  495. t.queue.Remove(queuePosition)
  496. }
  497. }
  498. }
  499. }
  500. func (t *TxManager) removeBadBatchInfos(ctx context.Context) error {
  501. next := 0
  502. // batchNum := 0
  503. for {
  504. batchInfo := t.queue.At(next)
  505. if batchInfo == nil {
  506. break
  507. }
  508. if err := t.checkEthTransactionReceipt(ctx, batchInfo); ctx.Err() != nil {
  509. return nil
  510. } else if err != nil {
  511. // Our ethNode is giving an error different
  512. // than "not found" when getting the receipt
  513. // for the transaction, so we can't figure out
  514. // if it was not mined, mined and succesfull or
  515. // mined and failed. This could be due to the
  516. // ethNode failure.
  517. next++
  518. continue
  519. }
  520. confirm, err := t.handleReceipt(ctx, batchInfo)
  521. if ctx.Err() != nil {
  522. return nil
  523. } else if err != nil {
  524. // Transaction was rejected
  525. if t.minPipelineNum <= batchInfo.PipelineNum {
  526. t.minPipelineNum = batchInfo.PipelineNum + 1
  527. }
  528. t.queue.Remove(next)
  529. continue
  530. }
  531. // If tx is pending but is from a cancelled pipeline, remove it
  532. // from the queue
  533. if confirm == nil {
  534. if batchInfo.PipelineNum < t.minPipelineNum {
  535. // batchNum++
  536. t.queue.Remove(next)
  537. continue
  538. }
  539. }
  540. next++
  541. }
  542. accNonce, err := t.ethClient.EthNonceAt(ctx, t.account.Address, nil)
  543. if err != nil {
  544. return err
  545. }
  546. if !t.cfg.EthNoReuseNonce {
  547. t.accNextNonce = accNonce
  548. }
  549. return nil
  550. }
  551. func (t *TxManager) canForgeAt(blockNum int64) bool {
  552. return canForge(&t.consts.Auction, &t.vars.Auction,
  553. &t.stats.Sync.Auction.CurrentSlot, &t.stats.Sync.Auction.NextSlot,
  554. t.cfg.ForgerAddress, blockNum)
  555. }
  556. func (t *TxManager) mustL1L2Batch(blockNum int64) bool {
  557. lastL1BatchBlockNum := t.lastSentL1BatchBlockNum
  558. if t.stats.Sync.LastL1BatchBlock > lastL1BatchBlockNum {
  559. lastL1BatchBlockNum = t.stats.Sync.LastL1BatchBlock
  560. }
  561. return blockNum-lastL1BatchBlockNum >= t.vars.Rollup.ForgeL1L2BatchTimeout-1
  562. }