syntax = "proto3"; import "google/protobuf/empty.proto"; import "types/types.proto"; package remote; option go_package = "./remote;remote"; //Variables Naming: // ts - TimeStamp // tx - Database Transaction // txn - Ethereum Transaction (and TxNum - is also number of Etherum Transaction) // RoTx - Read-Only Database Transaction // RwTx - Read-Write Database Transaction // k - key // v - value //Methods Naming: // Get: exact match of criterias // Range: [from, to) // Each: [from, INF) // Prefix: Has(k, prefix) // Amount: [from, INF) AND maximum N records //Entity Naming: // State: simple table in db // InvertedIndex: supports range-scans // History: can return value of key K as of given TimeStamp. Doesn't know about latest/current value of key K. Returns NIL if K not changed after TimeStamp. // Domain: as History but also aware about latest/current value of key K. // Provides methods to access key-value data service KV { // Version returns the service version number rpc Version(google.protobuf.Empty) returns (types.VersionReply); // Tx exposes read-only transactions for the key-value store // // When tx open, client must receive 1 message from server with txID // When cursor open, client must receive 1 message from server with cursorID // Then only client can initiate messages from server rpc Tx(stream Cursor) returns (stream Pair); rpc StateChanges(StateChangeRequest) returns (stream StateChangeBatch); // Snapshots returns list of current snapshot files. Then client can just open all of them. rpc Snapshots(SnapshotsRequest) returns (SnapshotsReply); //Temporal methods rpc DomainGet(DomainGetReq) returns (DomainGetReply); rpc HistoryGet(HistoryGetReq) returns (HistoryGetReply); rpc IndexRange(IndexRangeReq) returns (IndexRangeReply); // rpc IndexStream(IndexRangeReq) returns (stream IndexRangeReply); // Range [from, to) // Range(from, nil) means [from, EndOfTable) // Range(nil, to) means [StartOfTable, to) // If orderAscend=false server expecting `from`<`to`. Example: Range("B", "A") rpc Range(RangeReq) returns (Pairs); // rpc Stream(RangeReq) returns (stream Pairs); } enum Op { FIRST = 0; FIRST_DUP = 1; SEEK = 2; SEEK_BOTH = 3; CURRENT = 4; LAST = 6; LAST_DUP = 7; NEXT = 8; NEXT_DUP = 9; NEXT_NO_DUP = 11; PREV = 12; PREV_DUP = 13; PREV_NO_DUP = 14; SEEK_EXACT = 15; SEEK_BOTH_EXACT = 16; OPEN = 30; CLOSE = 31; OPEN_DUP_SORT = 32; COUNT = 33; } message Cursor { Op op = 1; string bucketName = 2; uint32 cursor = 3; bytes k = 4; bytes v = 5; } message Pair { bytes k = 1; bytes v = 2; uint32 cursorID = 3; // send once after new cursor open uint64 viewID = 4; // return once after tx open. mdbx's tx.ViewID() - id of write transaction in db uint64 txID = 5; // return once after tx open. internal identifier - use it in other methods - to achieve consistant DB view (to read data from same DB tx on server). } enum Action { STORAGE = 0; // Change only in the storage UPSERT = 1; // Change of balance or nonce (and optionally storage) CODE = 2; // Change of code (and optionally storage) UPSERT_CODE = 3; // Change in (balance or nonce) and code (and optinally storage) REMOVE = 4; // Account is deleted } message StorageChange { types.H256 location = 1; bytes data = 2; } message AccountChange { types.H160 address = 1; uint64 incarnation = 2; Action action = 3; bytes data = 4; // nil if there is no UPSERT in action bytes code = 5; // nil if there is no CODE in action repeated StorageChange storageChanges = 6; } enum Direction { FORWARD = 0; UNWIND = 1; } // StateChangeBatch - list of StateDiff done in one DB transaction message StateChangeBatch { uint64 stateVersionID = 1; // mdbx's tx.ID() - id of write transaction in db - where this changes happened repeated StateChange changeBatch = 2; uint64 pendingBlockBaseFee = 3; // BaseFee of the next block to be produced uint64 blockGasLimit = 4; // GasLimit of the latest block - proxy for the gas limit of the next block to be produced } // StateChange - changes done by 1 block or by 1 unwind message StateChange { Direction direction = 1; uint64 blockHeight = 2; types.H256 blockHash = 3; repeated AccountChange changes = 4; repeated bytes txs = 5; // enable by withTransactions=true } message StateChangeRequest { bool withStorage = 1; bool withTransactions = 2; } message SnapshotsRequest { } message SnapshotsReply { repeated string blocks_files = 1; repeated string history_files = 2; } message RangeReq { uint64 tx_id = 1; // returned by .Tx() // It's ok to query wide/unlilmited range of data, server will use `pagination params` // reply by limited batches/pages and client can decide: request next page or not // query params string table = 2; bytes from_prefix = 3; bytes to_prefix = 4; bool order_ascend = 5; sint64 limit = 6; // <= 0 means no limit // pagination params int32 page_size = 7; // <= 0 means server will choose string page_token = 8; } //Temporal methods message DomainGetReq { uint64 tx_id = 1; // returned by .Tx() // query params string table = 2; bytes k = 3; uint64 ts = 4; bytes k2 = 5; } message DomainGetReply{ bytes v = 1; bool ok = 2; } message HistoryGetReq { uint64 tx_id = 1; // returned by .Tx() string table = 2; bytes k = 3; uint64 ts = 4; } message HistoryGetReply{ bytes v = 1; bool ok = 2; } message IndexRangeReq { uint64 tx_id = 1; // returned by .Tx() // query params string table = 2; bytes k = 3; sint64 from_ts = 4; // -1 means Inf sint64 to_ts = 5; // -1 means Inf bool order_ascend = 6; sint64 limit = 7; // <= 0 means no limit // pagination params int32 page_size = 8; // <= 0 means server will choose string page_token = 9; } message IndexRangeReply { repeated uint64 timestamps = 1; //TODO: it can be a bitmap string next_page_token = 2; } message Pairs { repeated bytes keys = 1; // TODO: replace by lengtsh+arena? Anyway on server we need copy (serialization happening outside tx) repeated bytes values = 2; string next_page_token = 3; // uint32 estimateTotal = 3; // send once after stream creation // repeated sint64 lengths = 1; //A length of -1 means that the field is NULL // bytes keys = 2; // bytes values = 3; } message ParisPagination { bytes next_key = 1; sint64 limit = 2; } message IndexPagination { sint64 next_time_stamp = 1; sint64 limit = 2; }