|
| 1 | +# Warp Centralized Sequencer |
| 2 | + |
| 3 | +:::caution |
| 4 | +This section describes the operation of the current centralized sequencer, which will soon be replaced by the new [decentralized solution](/docs/sequencer/decentralized). |
| 5 | +::: |
| 6 | + |
| 7 | +## How it works |
| 8 | + |
| 9 | +Instead of posting the interaction transactions directly to Arweave mainnet, Warp SDK creates a data item with interaction input and tags which is then signed with user's wallet. Data item is then sent to Warp Sequencer (`/gateway/v2/sequencer/register` endpoint) (this is the default behaviour of Warp's SDK `contract.writeInteraction` |
| 10 | +function, when `forMainnet` instance is being used). |
| 11 | + |
| 12 | +The Warp Sequencer then: |
| 13 | + |
| 14 | +#### 1. Generates a sort key |
| 15 | + |
| 16 | +A sort key is generated from: |
| 17 | + |
| 18 | +1. current mainnet network height |
| 19 | +2. current sequence value |
| 20 | +3. original transaction id |
| 21 | +4. current mainnet block hash |
| 22 | + |
| 23 | +In the original SmartWeave protocol specification, a _sort key_ is defined |
| 24 | +as a `[ block_height,sha256(transactionId + blockHash) ]`, where: |
| 25 | + |
| 26 | +1. `block_height` - current network height, l-padded with `0` to 12 chars, e.g. for block height `1015556`, the |
| 27 | + result is `000001015556` |
| 28 | +2. `sha256(transactionId + blockHash)` - a `sha256` hash of the concatenated buffers of the transaction id and block |
| 29 | + hash, |
| 30 | + e.g. for txId `UR_35HORbjjZ_NnUqinkZuWkcNB1-gBST3Rezt5JrDs` and block |
| 31 | + hash `ixWCxRN36DjVUxQRa68xIeoZLfvLDTtX78e0ae8RAAJjOPpDBuVKVaEKYOpq7bLS`, |
| 32 | + the result is `44edd70f2018924f22a878a558a8f2d5cae8bc1f718d567df43bf52b6384d260`. |
| 33 | + |
| 34 | +The complete _sort key_ for the above values would |
| 35 | +be: `000001015556,44edd70f2018924f22a878a558a8f2d5cae8bc1f718d567df43bf52b6384d260`. |
| 36 | + |
| 37 | +The generated sort keys are then used by the SmartWeave protocol to lexicographically sort the transactions. |
| 38 | + |
| 39 | +The Warp Sequencer extends this default mechanism by the current sequence value. |
| 40 | +The formula for the _sort key_ is extended to: |
| 41 | +`[ block_height,sequence_value,sha256(transactionId + blockHash) ]` |
| 42 | + |
| 43 | +This sequence value can be obtained from the Sequencer's node timestamp, database or other sources. |
| 44 | +In its current implementation - a Sequencer node timestamp value is being used. |
| 45 | +This in effect gives a fair transactions ordering - the transactions will have the sequence assigned in order in which |
| 46 | +they are processed by the Sequencer. |
| 47 | + |
| 48 | +Assuming transaction id `La_NpAFAWxGj-VIiLfg7NbBfox0RZ8uuEJSOOZykd48`, block |
| 49 | +hash `-o88tFYsMG9RXSGcNXX5sVDuSV5uHy7zuFRj6vYo91e3mXpmng6qw322Ip0-EguA`, |
| 50 | +block height `1015560` and current Sequencer value `1663069424541`, the generated _sort key_ would |
| 51 | +be `000001015560,1663069424541,a21ac8a60326ba8c2bb8caa05cff3334a22e9960ef55de0b5392caa30b484d0a` |
| 52 | + |
| 53 | +**NOTE** All the transactions sent to Arweave directly, have the sequence value assigned to `0000000000000000`. |
| 54 | +This effectively means that if transactions to a given contract are sent both directly to Arweave mainnet and Warp |
| 55 | +Sequencer - |
| 56 | +if two transactions happen to be at the same block height, the "direct" Arweave transactions take precedence. |
| 57 | +This also means that the sequencing algorithm is fully backwards compatible with the original SmartWeave protocol. |
| 58 | + |
| 59 | +#### 2. Generates tags for the Bundlr transaction |
| 60 | + |
| 61 | +| Tag Name | Tag Value | |
| 62 | +| ------------------------------------------- | -------------------------------------------------------------------- | |
| 63 | +| `Sequencer` | `Warp` | |
| 64 | +| `Sequencer-Owner` | The original owner/signar of the contract transaction | |
| 65 | +| `Sequencer-Mills` | The sequence value used by the Sequencer for this transaction | |
| 66 | +| `Sequencer-Sort-Key` | The generated sort key for this transaction | |
| 67 | +| `Sequencer-Prev-Sort-Key` | The sort key of the previous transaction | |
| 68 | +| `Sequencer-Tx-Id` | The original transaction id | |
| 69 | +| `Sequencer-Block-Height` | The block height used for generating the sort key | |
| 70 | +| `Sequencer-Block-Id` | The block hash used for generating the sort key | |
| 71 | +| `Sequencer-Block-Timestamp` | The timestamp of the block that was used for generating the sort key | |
| 72 | +| ...all the tags of the original transaction | | |
| 73 | + |
| 74 | +:::tip |
| 75 | +The `Sequencer-Prev-Sort-Key` tells what is the sort key of the 'previous' transaction in the sequencer and |
| 76 | +can be used to verify whether all transactions have been properly loaded (i.e. if one |
| 77 | +decides to load them directly from L1 nodes) and none is missing. |
| 78 | +::: |
| 79 | + |
| 80 | +Additional set of tags are added in case user requests generating a random value using VRF (Verifiable Random Function): |
| 81 | + |
| 82 | +| Tag Name | Tag Value | |
| 83 | +| ------------ | ----------------------------------------------------------------------- | |
| 84 | +| `vrf-index` | The original hash generated by the VRF (using `sort_key` as input data) | |
| 85 | +| `vrf-proof` | The original proof generated by the VRF | |
| 86 | +| `vrf-bigint` | A BigInt value evaluated from the hash generated by the VRF | |
| 87 | +| `vrf-pubkey` | The public key used by the VRF | |
| 88 | + |
| 89 | +Verifiable randomness can be used by contracts that require using random values - e.g. gaming contracts, nft/loot |
| 90 | +generating contracts, etc. |
| 91 | +Using the `sort_key`, `vrf-proof` and `vrf-pubkey`, the client can always verify the generated random value. |
| 92 | + |
| 93 | +#### 3. Wrap original data item in a bundle and uploads the bundle to Bundlr |
| 94 | + |
| 95 | +Apart from all the tags from point 2, some additional tags are added to the wrapping bundle: |
| 96 | + |
| 97 | +| Tag Name | Tag Value | |
| 98 | +| ---------------- | ----------------- | |
| 99 | +| `Bundle-Format` | `binary` | |
| 100 | +| `Bundle-Version` | `2.0.0` | |
| 101 | +| `App-Name` | `Warp` | |
| 102 | +| `Action` | `WarpInteraction` | |
| 103 | + |
| 104 | +In order to send original data item to Bundlr, we use the concept of nested bundles and set an interaction data item inside a bundle. If you're not faimiliar with this concept, here is a quick summary: |
| 105 | + |
| 106 | +:::info |
| 107 | +Bundling allows to write multiple data items into one top level transaction. A data item differs from a regular transaction by not allowing to transfer AR tokens and passing reward but it has most of the transaction's properties - such as owner, data, tags, owner and id. |
| 108 | + |
| 109 | +In a nutshell, the nested bundles concept means that a data item of a bundle can also be a bundle containg other data items. According to ANS-104 standard it can lead to theoretically unbounded levels of nesting. |
| 110 | + |
| 111 | +You can read the specification for nested bundles standard in [ANS-104](https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md#31-nested-bundle). |
| 112 | +::: |
| 113 | + |
| 114 | +:::info |
| 115 | +Obviously the data-item is signed by the Sequencer's wallet - and as such can be easily verified. |
| 116 | +The Sequencer wallet address is `jnioZFibZSCcV8o-HkBXYPYEYNib4tqfexP0kCBXX_M`. |
| 117 | +::: |
| 118 | + |
| 119 | +**NOTE** The original data item is not modified in any way - this is to preserve the original |
| 120 | +signature! |
| 121 | + |
| 122 | +After receiving proper response and receipt from Bundlr, the Warp gateway indexes the contract interaction |
| 123 | +internally - to make it instantly available. |
| 124 | + |
| 125 | +#### 4. Finally, the Warp gateway returns the response from the Bundlr to the client. |
| 126 | + |
| 127 | +## Interaction data item retrieval (generated by the Warp Sequencer) via Arweave gateway |
| 128 | + |
| 129 | +Use the GQL endpoint, with the original data item id passed in the `Contract` tag. Note that all the |
| 130 | +interactions will be part of a bundle (i.e. will have the `edges.node.bundledIn.id` value set). |
| 131 | + |
| 132 | +```qql |
| 133 | +query { |
| 134 | + transactions( |
| 135 | + ids: ["1UIhK4vL5lc2X4aMsJFmMpJqfdgrjznVzi2F17yLBlc"] |
| 136 | + ) { |
| 137 | + edges { |
| 138 | + node { |
| 139 | + id |
| 140 | + tags { |
| 141 | + name |
| 142 | + value |
| 143 | + } |
| 144 | + block { |
| 145 | + height |
| 146 | + } |
| 147 | + bundledIn { |
| 148 | + id |
| 149 | + } |
| 150 | + } |
| 151 | + } |
| 152 | + } |
| 153 | +} |
| 154 | +``` |
| 155 | + |
| 156 | +## Interaction retrieval via Warp gateway |
| 157 | + |
| 158 | +The Warp `/gateway/interactions/:id` endpoint allows to retrieve the interaction info based on its original id. |
0 commit comments