Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the SyncService to more closely implement the specification #552

Merged
merged 32 commits into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
656cbe3
l2geth: add Backend enums and config parsing
tynes Apr 21, 2021
97fd394
l2geth: move OVMContext to types file
tynes Apr 21, 2021
60f3a2e
l2geth: implement syncservice spec
tynes Apr 22, 2021
d8359ce
l2geth: fix error handling for get tx batch
tynes Apr 22, 2021
87742d9
l2geth: update tests to compile and pass
tynes Apr 22, 2021
82aea42
l2geth: add sync range functions
tynes Apr 22, 2021
c0c3561
l2geth: add batch index indexing
tynes Apr 22, 2021
6aba901
l2geth: update syncservice hot path logging
tynes Apr 22, 2021
c902766
l2geth: use indexed batch index
tynes Apr 22, 2021
570b79a
chore: add changeset
tynes Apr 22, 2021
964e05e
l2geth: sync spec refactor (#822)
tynes May 12, 2021
6d9e632
Merge branch 'develop' into l2geth/sync-spec
tynes May 12, 2021
c3bedee
sync-service: better logline
tynes May 12, 2021
e8a350d
l2geth: better logline
tynes May 12, 2021
db1f547
l2geth: test apply indexed transaction
tynes May 12, 2021
0849703
l2geth: better logline
tynes May 12, 2021
059d793
linting: fix
tynes May 12, 2021
913a14d
syncservice: fix logline
tynes May 12, 2021
51ef245
l2geth: add error and fix logline
tynes May 13, 2021
8b5ead5
l2geth: sync service tests
tynes May 13, 2021
cac3daf
fix: get last confirmed enqueue (#846)
tynes May 12, 2021
53b12c5
batch-submitter: updated config (#847)
tynes May 13, 2021
9d91c2c
l2geth: update rawdb logline
tynes May 13, 2021
1b83b4b
l2geth: more robust testing
tynes May 13, 2021
9ada2d0
l2geth: add sanity check for L1ToL2 timestamps
tynes May 13, 2021
4c9ceb7
l2geth: handle error in single place
tynes May 13, 2021
1f86620
Merge branch 'develop' into l2geth/sync-spec
tynes May 13, 2021
435e25d
l2geth: fix test tx queue origin
tynes May 14, 2021
f7d18c1
l2geth: add new arg to start.sh
tynes May 14, 2021
c38ec87
l2geth: return error in the SyncService.Start()
tynes May 14, 2021
ae02108
Merge branch 'develop' into l2geth/sync-spec
gakonst May 26, 2021
112f0e8
chore: go fmt
gakonst May 26, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/big-moose-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/l2geth': patch
---

Fixes a bug in L2geth that causes it to skip the first deposit if there have been no deposits batch-submitted yet
7 changes: 7 additions & 0 deletions .changeset/lovely-plants-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@eth-optimism/core-utils': patch
'@eth-optimism/data-transport-layer': patch
'@eth-optimism/message-relayer': patch
---

Migrate bcfg interface to core-utils
5 changes: 5 additions & 0 deletions .changeset/nervous-bobcats-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@eth-optimism/l2geth": patch
---

Refactor the SyncService to more closely implement the specification. This includes using query params to select the backend from the DTL, trailing syncing of batches for the sequencer, syncing by batches as the verifier as well as unified code paths for transaction ingestion to prevent double ingestion or missed ingestion
5 changes: 5 additions & 0 deletions .changeset/soft-squids-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/batch-submitter': patch
---

Updates the configuration to use bcfg in a backwards compatible way
2 changes: 1 addition & 1 deletion l2geth/cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ var (
utils.Eth1ETHGatewayAddressFlag,
utils.Eth1ChainIdFlag,
utils.RollupClientHttpFlag,
// Enable verifier mode
utils.RollupEnableVerifierFlag,
utils.RollupAddressManagerOwnerAddressFlag,
utils.RollupTimstampRefreshFlag,
Expand All @@ -166,6 +165,7 @@ var (
utils.RollupMaxCalldataSizeFlag,
utils.RollupDataPriceFlag,
utils.RollupExecutionPriceFlag,
utils.RollupBackendFlag,
}

rpcFlags = []cli.Flag{
Expand Down
1 change: 1 addition & 0 deletions l2geth/cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.RollupMaxCalldataSizeFlag,
utils.RollupDataPriceFlag,
utils.RollupExecutionPriceFlag,
utils.RollupBackendFlag,
},
},
{
Expand Down
15 changes: 15 additions & 0 deletions l2geth/cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,12 @@ var (
Value: time.Minute * 3,
EnvVar: "ROLLUP_TIMESTAMP_REFRESH",
}
RollupBackendFlag = cli.StringFlag{
Name: "rollup.backend",
Usage: "Sync backend for verifiers (\"l1\" or \"l2\"), defaults to l1",
Value: "l1",
EnvVar: "ROLLUP_BACKEND",
}
// Flag to enable verifier mode
RollupEnableVerifierFlag = cli.BoolFlag{
Name: "rollup.verifier",
Expand Down Expand Up @@ -1170,6 +1176,15 @@ func setRollup(ctx *cli.Context, cfg *rollup.Config) {
if ctx.GlobalIsSet(RollupExecutionPriceFlag.Name) {
cfg.ExecutionPrice = GlobalBig(ctx, RollupExecutionPriceFlag.Name)
}
if ctx.GlobalIsSet(RollupBackendFlag.Name) {
val := ctx.GlobalString(RollupBackendFlag.Name)
backend, err := rollup.NewBackend(val)
if err != nil {
log.Error("Configured with unknown sync backend, defaulting to l1", "backend", val)
backend, _ = rollup.NewBackend("l1")
}
cfg.Backend = backend
}
}

// setLes configures the les server and ultra light client settings from the command line flags.
Expand Down
21 changes: 21 additions & 0 deletions l2geth/core/rawdb/rollup_indexes.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,24 @@ func WriteHeadVerifiedIndex(db ethdb.KeyValueWriter, index uint64) {
log.Crit("Failed to store verifier index", "err", err)
}
}

// ReadHeadBatchIndex will read the known tip of the processed batches
func ReadHeadBatchIndex(db ethdb.KeyValueReader) *uint64 {
Copy link
Contributor

Choose a reason for hiding this comment

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

The name (Read/Write)HeadBatchIndex is a bit confusing, might consider updating it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

{Read/Write}HeadTransactionBatchIndex ?
Open to a suggestion

data, _ := db.Get(headBatchKey)
if len(data) == 0 {
return nil
}
ret := new(big.Int).SetBytes(data).Uint64()
return &ret
}

// WriteHeadBatchIndex will write the known tip of the processed batches
func WriteHeadBatchIndex(db ethdb.KeyValueWriter, index uint64) {
value := new(big.Int).SetUint64(index).Bytes()
if index == 0 {
value = []byte{0}
}
if err := db.Put(headBatchKey, value); err != nil {
log.Crit("Failed to store head batch index", "err", err)
}
}
2 changes: 2 additions & 0 deletions l2geth/core/rawdb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ var (
headQueueIndexKey = []byte("LastQueueIndex")
// headVerifiedIndexKey tracks the latest verified index
headVerifiedIndexKey = []byte("LastVerifiedIndex")
// headBatchKey tracks the latest processed batch
headBatchKey = []byte("LastBatch")

preimagePrefix = []byte("secure-key-") // preimagePrefix + hash -> preimage
configPrefix = []byte("ethereum-config-") // config prefix for the db
Expand Down
2 changes: 1 addition & 1 deletion l2geth/eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
}
}
}
return b.eth.syncService.ApplyTransaction(signedTx)
return b.eth.syncService.ValidateAndApplySequencerTransaction(signedTx)
}
// OVM Disabled
return b.eth.txPool.AddLocal(signedTx)
Expand Down
74 changes: 63 additions & 11 deletions l2geth/rollup/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,17 @@ type decoded struct {
type RollupClient interface {
GetEnqueue(index uint64) (*types.Transaction, error)
GetLatestEnqueue() (*types.Transaction, error)
GetTransaction(uint64) (*types.Transaction, error)
GetLatestTransaction() (*types.Transaction, error)
GetLatestEnqueueIndex() (*uint64, error)
GetTransaction(uint64, Backend) (*types.Transaction, error)
GetLatestTransaction(Backend) (*types.Transaction, error)
GetLatestTransactionIndex(Backend) (*uint64, error)
GetEthContext(uint64) (*EthContext, error)
GetLatestEthContext() (*EthContext, error)
GetLastConfirmedEnqueue() (*types.Transaction, error)
GetLatestTransactionBatch() (*Batch, []*types.Transaction, error)
GetLatestTransactionBatchIndex() (*uint64, error)
GetTransactionBatch(uint64) (*Batch, []*types.Transaction, error)
SyncStatus() (*SyncStatus, error)
SyncStatus(Backend) (*SyncStatus, error)
GetL1GasPrice() (*big.Int, error)
}

Expand Down Expand Up @@ -272,6 +275,43 @@ func (c *Client) GetLatestEnqueue() (*types.Transaction, error) {
return tx, nil
}

// GetLatestEnqueueIndex returns the latest `enqueue()` index
func (c *Client) GetLatestEnqueueIndex() (*uint64, error) {
tx, err := c.GetLatestEnqueue()
if err != nil {
return nil, err
}
index := tx.GetMeta().QueueIndex
if index == nil {
return nil, errors.New("Latest queue index is nil")
}
return index, nil
}

// GetLatestTransactionIndex returns the latest CTC index that has been batch
// submitted or not, depending on the backend
func (c *Client) GetLatestTransactionIndex(backend Backend) (*uint64, error) {
tx, err := c.GetLatestTransaction(backend)
if err != nil {
return nil, err
}
index := tx.GetMeta().Index
if index == nil {
return nil, errors.New("Latest index is nil")
}
return index, nil
}

// GetLatestTransactionBatchIndex returns the latest transaction batch index
func (c *Client) GetLatestTransactionBatchIndex() (*uint64, error) {
batch, _, err := c.GetLatestTransactionBatch()
if err != nil {
return nil, err
}
index := batch.Index
return &index, nil
}

// batchedTransactionToTransaction converts a transaction into a
// types.Transaction that can be consumed by the SyncService
func batchedTransactionToTransaction(res *transaction, signer *types.EIP155Signer) (*types.Transaction, error) {
Expand Down Expand Up @@ -366,12 +406,15 @@ func batchedTransactionToTransaction(res *transaction, signer *types.EIP155Signe
}

// GetTransaction will get a transaction by Canonical Transaction Chain index
func (c *Client) GetTransaction(index uint64) (*types.Transaction, error) {
func (c *Client) GetTransaction(index uint64, backend Backend) (*types.Transaction, error) {
str := strconv.FormatUint(index, 10)
response, err := c.client.R().
SetPathParams(map[string]string{
"index": str,
}).
SetQueryParams(map[string]string{
"backend": backend.String(),
}).
SetResult(&TransactionResponse{}).
Get("/transaction/index/{index}")

Expand All @@ -387,9 +430,12 @@ func (c *Client) GetTransaction(index uint64) (*types.Transaction, error) {

// GetLatestTransaction will get the latest transaction, meaning the transaction
// with the greatest Canonical Transaction Chain index
func (c *Client) GetLatestTransaction() (*types.Transaction, error) {
func (c *Client) GetLatestTransaction(backend Backend) (*types.Transaction, error) {
response, err := c.client.R().
SetResult(&TransactionResponse{}).
SetQueryParams(map[string]string{
"backend": backend.String(),
}).
Get("/transaction/latest")

if err != nil {
Expand Down Expand Up @@ -449,23 +495,26 @@ func (c *Client) GetLastConfirmedEnqueue() (*types.Transaction, error) {
if err != nil {
return nil, fmt.Errorf("Cannot get latest enqueue: %w", err)
}
// This should only happen if the database is empty
// This should only happen if there are no L1 to L2 transactions yet
if enqueue == nil {
return nil, nil
return nil, errElementNotFound
}
// Work backwards looking for the first enqueue
// to have an index, which means it has been included
// in the canonical transaction chain.
for {
meta := enqueue.GetMeta()
// The enqueue has an index so it has been confirmed
if meta.Index != nil {
return enqueue, nil
}
// There is no queue index so this is a bug
if meta.QueueIndex == nil {
return nil, fmt.Errorf("queue index is nil")
}
// No enqueue transactions have been confirmed yet
if *meta.QueueIndex == uint64(0) {
return enqueue, nil
return nil, errElementNotFound
}
next, err := c.GetEnqueue(*meta.QueueIndex - 1)
if err != nil {
Expand All @@ -476,9 +525,12 @@ func (c *Client) GetLastConfirmedEnqueue() (*types.Transaction, error) {
}

// SyncStatus will query the remote server to determine if it is still syncing
func (c *Client) SyncStatus() (*SyncStatus, error) {
func (c *Client) SyncStatus(backend Backend) (*SyncStatus, error) {
response, err := c.client.R().
SetResult(&SyncStatus{}).
SetQueryParams(map[string]string{
"backend": backend.String(),
}).
Get("/eth/syncing")

if err != nil {
Expand Down Expand Up @@ -532,8 +584,8 @@ func (c *Client) GetTransactionBatch(index uint64) (*Batch, []*types.Transaction
// parseTransactionBatchResponse will turn a TransactionBatchResponse into a
// Batch and its corresponding types.Transactions
func parseTransactionBatchResponse(txBatch *TransactionBatchResponse, signer *types.EIP155Signer) (*Batch, []*types.Transaction, error) {
if txBatch == nil {
return nil, nil, nil
if txBatch == nil || txBatch.Batch == nil {
return nil, nil, errElementNotFound
}
batch := txBatch.Batch
txs := make([]*types.Transaction, len(txBatch.Transactions))
Expand Down
2 changes: 2 additions & 0 deletions l2geth/rollup/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ type Config struct {
DataPrice *big.Int
// The gas price to use for L2 congestion costs
ExecutionPrice *big.Int
// Represents the source of the transactions that is being synced
Backend Backend
}
Loading