An open API service indexing awesome lists of open source software.

https://github.com/0xpolygon/zkevm-data-streamer

Go implementation of a generic fast data streamer library.
https://github.com/0xpolygon/zkevm-data-streamer

Last synced: about 1 year ago
JSON representation

Go implementation of a generic fast data streamer library.

Awesome Lists containing this project

README

          

# zkEVM DataStreamer

Go implementation of a generic fast data streamer library.

**Use case for the zkEVM Node**: Sequencer data stream service to stream L2 blocks and L2 txs.

![zkEVM DataSreamer diagram](doc/data-streamer.png)

## GENERAL DIAGRAM
Description of the diagram elements:

- **Sequencer**: uses the data streamer library through the API to send L2 blocks and L2 transactions to the stream. It's an use case of the datastreamer component.

- **Data Streamer**: creates the stream server, it manages the stream file and allows stream clients to connect using a TCP socket. For such stream clients, it offers a series of commands via the TCP port.

- **Stream File**: stores all the streaming data. It is a custom binary file organized into data pages with a preceding header page.

- **Bookmarks DB**: stores an index for the bookmarks that are available in the streaming file. It uses a LevelDB using the library [goleveldb](https://github.com/syndtr/goleveldb).

- **Streamer Client**: creates a stream client, it manages the data streamer connection and allows to execute the TCP commands available in the server.

## STREAM FILE
The binary file format is described below.

### Header page
- The first page is the header.
- Header page size = 4096 bytes

#### Magic numbers
At the beginning of the file there are the following magic bytes (file signature): `polygonDATSTREAM`

#### HEADER ENTRY format (HeaderEntry)
>u8 packetType = 1 // 1:Header
>u32 headerLength = 38 // Total length of header entry
>u8 Version // Stream file version (starting from 1)
>u64 SystemID // E.g.: ChainID
>u64 streamType // 1:Sequencer
>u64 TotalLength // Total bytes used in the file
>u64 TotalEntries // Total number of data entries

### Data page
- From the second page starts the data pages.
- Page size = 1 MB

#### DATA ENTRY format (FileEntry)
>u8 packetType // 2:Data entry, 0:Padding
>u32 Length // Total length of data entry (17 bytes + length(data))
>u32 Type // 0xb0:Bookmark, 1:Event1, 2:Event2,...
>u64 Number // Entry number (sequential starting with 0)
>u8[] data

NOTE: If an entry does not fit in the remaining page space, the entry will be stored in the next page.

### File diagram
![Alt](doc/data-streamer-bin-file.drawio.png)

## STREAM TCP COMMANDS
- All the commands available for the stream clients return first a response, a `Result` entry defined in a later section.
- Some commands like `Start` or `Header` may return more data.

Below is the detail of the available commands:

### Start
Syncs from the entry number (`fromEntryNumber`) and starts receiving data streaming from that entry.

Command format sent by the client:
>u64 command = 1
>u64 streamType // e.g. 1:Sequencer
>u64 fromEntryNumber

If already started terminates the connection.

### StartBookmark
Syncs from the bookmark (`fromBookmark`) and starts receiving data streaming from the entry pointed by that bookmark.

Command format sent by the client:
>u64 command = 4
>u64 streamType // e.g. 1:Sequencer
>u32 bookmarkLength // Length of fromBookmark (Max bookmark length value is 16)
>u8[] fromBookmark

If already started or `bookmarkLength` exceeds the maximum length, terminates the connection.

### Stop
Stops the reception of the streaming transmission.

Command format sent by the client:
>u64 command = 2
>u64 streamType // e.g. 1:Sequencer

If not started terminates the connection.

### GetHeader
Gets the current stream file header (`HeaderEntry` format defined in the [STREAM FILE](#stream-file) section), so stream clients can know the total number of entries and the size of the stream file.

Command format sent by the client:
>u64 command = 3
>u64 streamType // e.g. 1:Sequencer

If streaming already started terminates the connection.

### GetEntry
Gets the data from the entry (`entryNumber`) in the format `FileEntry` defined in the [STREAM FILE](#stream-file) section).

Command format sent by the client:
>u64 command = 4
>u64 streamType // e.g. 1:Sequencer
>u64 entryNumber

If streaming already started terminates the connection.

### GetBookmark
Gets the data from the entry pointed by the bookmark (`bookmark`) in the format `FileEntry` defined in the [STREAM FILE](#stream-file) section).

Command format sent by the client:
>u64 command = 5
>u64 streamType // e.g. 1:Sequencer
>u32 bookmarkLength // Length of bookmark (Max bookmark length value is 16)
>u8[] bookmark

If streaming already started or `bookmarkLength` exceeds the maximum length, terminates the connection.

### RESULT FORMAT (ResultEntry)
Remember that all these TCP commands firstly return a response in the following detailed format:
>u8 packetType // 0xff:Result
>u32 length // Total length of the entry
>u32 errorNum // Error code (0:OK)
>u8[] errorStr

## BOOKMARKS
Bookmarks make possible to the clients to sync the streaming from a business logic point.
- No need to store the latest `stream entry number` received.
- Using the API, bookmarks to business logic data are added in the send data to stream implementation.
- e.g. zkEVM Sequencer streaming: each L2 block number has its own bookmark. Clients can request to start the stream from a L2 block number.

## STREAM RELAY
Stream relay server included in the datastream library allows scaling the number of stream connected clients.

![Datastream relay diagram](doc/data-streamer-relay.png)

- **Data Streamer Relay** acts as a `stream client` towards the main data stream server, and also acts as a `stream server` towards the stream clients connected to it.

## DATA STREAMER INTERFACE (API)
### SERVER API
- Create and start a datastream server (`StreamServer`) using the `NewServer` function followed by the `Start` function.
- Send data to stream by starting an atomic operation through `StartAtomicOp`, adding entry events (`AddStreamEntry`) and bookmarks (`AddStreamBookmark`), and commit the operation `CommitAtomicOp`.

#### Send data API
- StartAtomicOp()
- AddStreamBookmark(u8[] bookmark) -> returns u64 entryNumber
- AddStreamEntry(u32 entryType, u8[] data) -> returns u64 entryNumber
- CommitAtomicOp()
- RollbackAtomicOp()

#### Query data API
- GetHeader() -> returns struct HeaderEntry
- GetEntry(u64 entryNumber) -> returns struct FileEntry
- GetBookmark(u8[] bookmark) -> returns u64 entryNumber
- GetFirstEventAfterBookmark(u8[] bookmark) -> returns struct FileEntry
- GetDataBetweenBookmarks(bookmarkFrom []byte, bookmarkTo []byte) ([]byte, error) -> returns the array of data, ignoring bookmarks, between the given ones

#### Update data API
- UpdateEntryData(u64 entryNumber, u32 entryType, u8[] newData)

### CLIENT API
- Create and start a datastream client (`StreamClient`) using the `NewClient` function followed by the `Start` function.
- Executes server commands by calling `ExecCommandStart`, `ExecCommandStartBookmark`, `ExecCommandGetHeader`, `ExecCommandGetEntry`, `ExecCommandGetBookmark`, or `ExecCommandStop`.

#### Streaming API
- ExecCommandStart(fromEntry): Initiates the stream starting from the entry number specified in the parameter.
- ExecCommandStartBookmark(fromBookmark): Initiates the stream starting from the entry pointed by the bookmark specified in the parameter.
- ExecCommandStop(): Stops receiving stream.
- SetProcessEntryFunc(f `ProcessEntryFunc`): Sets the callback function for each entry received. Overrides default function that just prints the entry fields.

#### Query data API
- ExecCommandGetHeader() -> returns struct HeaderEntry: Fetches stream file header info and returns it.
- ExecCommandGetEntry(fromEntry) -> returns struct FileEntry: Fetches entry data from the specified entry number and returns it.
- ExecCommandGetBookmark(fromBookmark) -> returns struct FileEntry: Fetches entry data pointed by the specified bookmark and returns it.

## DATASTREAM CLI DEMO APP
Build the binary datastream demo app (`dsapp`):
```
make build-dsapp
```
Run the app without parameters to see the available commands:
```
./dsapp
```
```
NAME:
dsapp - Run a datastream server/client/relay demo cli app

USAGE:
dsapp [global options] command [command options] [arguments...]

COMMANDS:
server Run datastream server
client Run datastream client
relay Run datastream relay
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--help, -h show help
```
### SERVER
Use the help option to check available parameters for the server command:
```
./dsapp help server
```
```
NAME:
dsapp server - Run datastream server

USAGE:
dsapp server [command options] [arguments...]

OPTIONS:
--port value exposed port for clients to connect (default: 6900)
--file value datastream data file name (*.bin) (default: datastream.bin)
--log value log level (debug|info|warn|error) (default: info)
--sleep value initial sleep and sleep between atomic operations in ms (default: 0)
--opers value number of atomic operations (server will terminate after them) (default: 1000000)
--help, -h show help
```
Run a datastream server with default parameters (port: `6900`, file: `datastream.bin`, log: `info`):
```
./dsapp server
```
Or run a datastream server with custom parameters:
```
./dsapp server --port 6969 --file seqstream.bin --log warn
```
### CLIENT
Use the help option to check available parameters for the client command:
```
./dsapp help client
```
```
NAME:
dsapp client - Run datastream client

USAGE:
dsapp client [command options] [arguments...]

OPTIONS:
--server value datastream server address to connect (IP:port) (default: 127.0.0.1:6900)
--from value entry number to start the sync/streaming from (latest|0..N) (default: latest)
--frombookmark value bookmark to start the sync/streaming from (0..N) (has preference over --from parameter)
--header query file header information (default: false)
--entry value entry number to query data (0..N)
--bookmark value entry bookmark to query entry data pointed by it (0..N)
--log value log level (debug|info|warn|error) (default: info)
--help, -h show help
```
Run a datastream client with default parameters (server: `127.0.0.1:6900`, from: `latest`, log: `info`)
```
./dsapp client
```
Or run a datastream client with custom parameters:
```
./dsapp client --server 127.0.0.1:6969 --from 0 --log debug
```
Or just get the current stream header file information:
```
./dsapp client --server 127.0.0.1:6969 --header
```
### RELAY
Use the help option to check available parameters for the relay command:
```
./dsapp help relay
```
```
NAME:
dsapp relay - Run datastream relay

USAGE:
dsapp relay [command options] [arguments...]

OPTIONS:
--server value datastream server address to connect (IP:port) (default: 127.0.0.1:6900)
--port value exposed port for clients to connect (default: 7900)
--file value relay data file name (*.bin) (default: datarelay.bin)
--log value log level (debug|info|warn|error) (default: info)
--help, -h show help
```
Run a datastream relay with default parameters (server: `127.0.0.1:6900`, port: `7900`, file: `datarelay.bin`, log: `info`)
```
./dsapp relay
```

## USE CASE: zkEVM SEQUENCER ENTRIES
Sequencer data stream service to stream L2 blocks and L2 txs

List of events (entry types):

### BatchStart:
uint64 number
BatchType type
uint64 fork_id
uint64 chain_id
Debug debug

### BatchEnd:
uint64 number
bytes local_exit_root
bytes state_root
Debug debug

### L2Block:
uint64 number
uint64 batch_number
uint64 timestamp
uint32 delta_timestamp
uint64 min_timestamp
bytes l1_blockhash
uint32 l1_infotree_index
bytes hash
bytes state_root
bytes global_exit_root
bytes coinbase
uint64 block_gas_limit
bytes block_info_root
Debug debug

### L2BlockEnd:
uint64 number

### Transaction:
uint64 l2block_number
uint64 index
bool is_valid
bytes encoded
uint32 effective_gas_price_percentage
bytes im_state_root
Debug debug

### UpdateGER:
uint64 batch_number
uint64 timestamp
bytes global_exit_root
bytes coinbase
uint64 fork_id
uint64 chain_id
bytes state_root
Debug debug

### BookMark:
BookmarkType type
uint64 value

### Debug:
string message

### BookmarkType:
BOOKMARK_TYPE_UNSPECIFIED = 0;
BOOKMARK_TYPE_BATCH = 1;
BOOKMARK_TYPE_L2_BLOCK = 2;

### EntryType:
ENTRY_TYPE_UNSPECIFIED = 0;
ENTRY_TYPE_BATCH_START = 1;
ENTRY_TYPE_L2_BLOCK = 2;
ENTRY_TYPE_TRANSACTION = 3;
ENTRY_TYPE_BATCH_END = 4;
ENTRY_TYPE_UPDATE_GER = 5;
ENTRY_TYPE_L2_BLOCK_END = 6;

### BatchType:
BATCH_TYPE_UNSPECIFIED = 0;
BATCH_TYPE_REGULAR = 1;
BATCH_TYPE_FORCED = 2;
BATCH_TYPE_INJECTED = 3;
BATCH_TYPE_INVALID = 4;