Skip to content

New synchronisation mechanism #40

@ppedziwiatr

Description

@ppedziwiatr

Current implementation

Currently, the sequencer generates transactions with a sortKey set for the current network height.
https://github.com/warp-contracts/gateway/blob/main/src/gateway/router/routes/sequencerRoute.ts#L76

The new Syncer waits a specified number of blocks to synchronize L1 transactions (to ensure they are properly confirmed and not from a fork).

Problem

There is a risk with how Sequencer is generating sortKeys. For example:

  • The Sequencer starts writing transactions at block height 100.
  • At the same time, the Syncer begins synchronizing transactions from block height 90 (assuming a 10-block delay).
  • The Syncer saves transactions to the database with sortKey = 90 + 10, but after the sequencer has already saved its transactions at that block height.

Because the second part of the sortKey for sequencer transactions is always greater than those from L1, there is a risk that transactions from the sequencer at block height 100 will be processed (e.g. by DRE) before Syncer adds its transactions at that block height. This could cause the transactions from the Syncer to be effectively unused for evaluating state (because the client will have already calculated transactions for newer sortKeys - those from the sequencer).

Solution

Parameters

  • CONFIRMATION_BLOCKS - how many blocks is Syncer waiting before downloading the block, e.g. 10. After this many blocks the risk of having a fork in the arweave blockchain is minimal
  • READY_BLOCKS - how many blocks "into the future" is Syncer generating the sortKey with
  • CURRENT_HEIGHT - block height returned by the Warp's Gateway
  • SYNCER_FINISHED_HEIGHT - last block height that is saved by the Syncer
  • SEQUENCER_CURRENT_HEIGHT - block height used in Sequencer to generate sortKeys

Block height used for SortKey generation

Syncer

It saves the block height it last synchronized (SYNCER_FINISHED_HEIGHT) in the database.
Syncer saves interactions with block height = SYNCER_FINISHED_HEIGHT + READY_BLOCKS.

For example:

  • a sortKey for a transaction from block 85 (as reported by Arweave)
  • with a 10-block CONFIRMATION_BLOCKS
  • with a 15-block READY_BLOCKS

should have a block height of 100.

Sequencer

Sequencer assigns sortKeys using block height:

SEQUENCER_CURRENT_HEIGHT = SYNCER_FINISHED_HEIGHT + CONFIRMATION_BLOCKS

Sequencer doesn't know what is the current block height of Arweave network

Sequencer doesn't send interactions to Redis anymore.

Introduce Forwarder

Forwarder is a new component connected to the database and the Redis master node, it is responsible for:

  • sending interactions from the database to Redis
  • ensuring that after SEQUENCER_CURRENT_HEIGHT is updated in the database all L1 interactions are sent before any L2 interaction.

Forwarder gets interactions that are already bundled

graph TD
    A[Send L1 interactions <br/> to Redis ] -->|Success| B[Send L2 interactions <br/> as soon as they appear]
    B -->|Check| C{SEQUENCER_CURRENT_HEIGHT updated}
    C -->|Yes| A
    C -->|No| B
Loading

Implementation details:

Block height in interaciton table

  • Syncer saves the original block height of the transaction
  • Sequencer saves with the current block height as reported from the Warp's Gateway

Block height used in sortKey vs block key seen by the contract

Sort Key Block Height seen by the contract
Syncer Original block height from tx + READY_BLOCKS Original block height from tx
Sequencer SYNCER_FINISHED_HEIGHT + CONFIRMATION_BLOCKS Block height at request time

Gateway

Gateway needs to use SEQUENCER_CURRENT_HEIGHT when returning interactions. Only interactions with sortKeys generated with block height smaller than SEQUENCER_CURRENT_HEIGHT can be returned.

TODO (remove)

Additional SortKey

We should generate two sortKeys:

  • first for contracts that only use L1 transactions (which should have the original block height, not the height where we synchronize) and
  • second for contracts that use mixed or sequencer-only modes.

Data in the interaction column should reflect the block for which we are generating the sortKey (problem: what about double generation of sortKeys - do we save two interactions? that's a lot of data...).

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions