Skip to content

l2geth: Sync from Backend Queue#2296

Merged
Inphi merged 14 commits intoethereum-optimism:developfrom
Inphi:feat/publish-tx
Mar 18, 2022
Merged

l2geth: Sync from Backend Queue#2296
Inphi merged 14 commits intoethereum-optimism:developfrom
Inphi:feat/publish-tx

Conversation

@Inphi
Copy link
Contributor

@Inphi Inphi commented Mar 9, 2022

Description

  • Introducing a new Backend verifiers can use to synchronize transactions from an external message queue.
  • To facilitate failover recovery without causing a chainsplit. The sequencer can be configured to log transactions externally prior to being added to the next block.

Inphi added 2 commits March 7, 2022 11:15
To facilitate failover recovery without causing a chainsplit.
@changeset-bot
Copy link

changeset-bot bot commented Mar 9, 2022

🦋 Changeset detected

Latest commit: f061820

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@eth-optimism/batch-submitter-service Patch
@eth-optimism/l2geth Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov-commenter
Copy link

codecov-commenter commented Mar 9, 2022

Codecov Report

Merging #2296 (f061820) into develop (4bfddfb) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff            @@
##           develop    #2296   +/-   ##
========================================
  Coverage    80.14%   80.14%           
========================================
  Files           77       77           
  Lines         2458     2458           
  Branches       450      450           
========================================
  Hits          1970     1970           
  Misses         488      488           
Flag Coverage Δ
contracts 99.29% <ø> (ø)
core-utils 86.77% <ø> (ø)
data-transport-layer 49.72% <ø> (ø)
sdk 55.90% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4bfddfb...f061820. Read the comment docs.

if err := s.txLogger.Publish(s.ctx, encodedTx.Bytes()); err != nil {
pubTxDropCounter.Inc(1)
log.Error("Failed to publish transaction to log", "msg", err)
return fmt.Errorf("internal error: transaction logging failed")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love the idea of returning an error here because that means we tightly couple googles uptime with our ability to accept transactions. Not really sure of a good solution

Copy link
Contributor Author

@Inphi Inphi Mar 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't like quite like it either but it's the best option. With the way infra is setup right now, I don't think this will worsen failure rate of transaction submissions. i.e. the sequencer is more likely to fail than google pubsub. And going by actual historical incidents, even less likely to fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My biggest concern with this approach is the additional latency overhead used per tx for logging. The median time to publish a transaction is about 35ms. Not bad right now, but it's something to watch out if tx rate increases via gas fee reductions or by having more users.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use this logic in two places as per my other comment, we should wrap this in a helper method in rcfg/pub.

@mslipper
Copy link
Contributor

mslipper commented Mar 9, 2022

I think you'll need to add similar TX logging functionality to the RPC handler for eth_sendRawTransaction.

Comment on lines +55 to +56
p.topic.ResumePublish(messageOrderingKey)
result := p.topic.Publish(ctx, &pmsg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this thread safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. Publish by itself is but not with the ResumePublish prior call.

if err := s.txLogger.Publish(s.ctx, encodedTx.Bytes()); err != nil {
pubTxDropCounter.Inc(1)
log.Error("Failed to publish transaction to log", "msg", err)
return fmt.Errorf("internal error: transaction logging failed")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use this logic in two places as per my other comment, we should wrap this in a helper method in rcfg/pub.

@Inphi
Copy link
Contributor Author

Inphi commented Mar 9, 2022

I think you'll need to add similar TX logging functionality to the RPC handler for eth_sendRawTransaction.

@mslipper eth_sendRawTransaction goes through the same code path. So we only need to log txs in one location.

@Inphi Inphi marked this pull request as ready for review March 17, 2022 02:33
The BackendQueue can be used by verifiers to sync transactions from
Google PubSub
@Inphi Inphi changed the title l2geth: Publish transactions to external msg queue l2geth: Sync from Backend Queue Mar 17, 2022
return s.applyTransaction(tx)
}

type QueuedTransactionMeta struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed a bunch of required fields from types.Transaction. The subscriber will assert that the necessary fields are set.

func (q QueueOrigin) MarshalJSON() ([]byte, error) {
switch q {
case QueueOriginSequencer:
return []byte("\"sequencer\""), nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you get rid of the need to the escapes by using a backtick string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

certainly. thanks for pointing that out.

return
}

if err := s.applyTransactionToTip(&tx); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have an ordering guarantee? And what about a delivery guarantee?

Copy link
Contributor Author

@Inphi Inphi Mar 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. An ordering is enforced by PubSub via external configuration. The transaction ordering relates to the block that contains it. Transactions publishing itself by a Sequencer is ordered - since a SendTx fails if we're unable to log it in PubSub.

Delivery guarantees are also handled by PubSub via external configuration. On infra, published messages will be available for at least several days. Which is enough time for a failover. Messages may be delivered more than once, so we check the db to see if we've already applied the transaction. If so, we acknowledge the message (advance the subscription queue offset) and move on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can assert that infra is setup correctly in code and the PubSub subscription has message ordering enabled. But this requires extra GCP permissions than needed to subscribe to messages.

Inphi added 2 commits March 17, 2022 23:33
and use l1 block params during tx apply
// requirement of the remote server being up.
if service.enable {
// If we're syncing from the Queue, then we can skip all this and rely on L2 published transactions
if service.enable && service.backend != BackendQueue {
Copy link
Contributor Author

@Inphi Inphi Mar 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay or nay? Side effect of this is that IsSyncing always returns false when we're syncing from the Queue. IsSyncing is only used to prevent transactions from being submitted to the node. But only verifiers will use the BackendQueue, so I don't think this would be an issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is OK - I don't expect any replica operators to use BackendQueue.

@mslipper
Copy link
Contributor

Approval is conditioned on fixing the go.sum - I believe that's what's causing the test errors.

@Inphi Inphi merged commit 32d6919 into ethereum-optimism:develop Mar 18, 2022
tx := mockTx()
tx.GetMeta().RawTransaction = nil
tests := map[string][]byte{
//"good txmeta": []byte("{\"l1BlockNumber\":0,\"l1Timestamp\":1647549225,\"l1MessageSender\":\"0x1487ef4dd5b0ca7610b85964371c1d8ab7c468eb\",\"queueOrigin\":\"sequencer\",\"index\":0,\"queueIndex\":0,\"rawTransaction\":\"34CAgJQrz3UmBr9M0373farCJhgNfaGiVICCAACAgIA=\"}"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test fail?

Copy link
Contributor Author

@Inphi Inphi Mar 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's uncommented then the test case fails. It's not meant to be tested. The comment is only a reference transaction log I used to construct the other failure scenarios.

theochap pushed a commit that referenced this pull request Dec 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cannon Area: cannon

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants