diff --git a/src/RFC-0001_overview.md b/src/RFC-0001_overview.md index 7b8d7fd..950c8e9 100644 --- a/src/RFC-0001_overview.md +++ b/src/RFC-0001_overview.md @@ -4,8 +4,6 @@ ![status: stable](theme/images/status-stable.svg) -**Maintainer(s)**: [Cayle Sharrock](https://github.com/CjS77) - # Licence [ The 3-Clause BSD Licence](https://opensource.org/licenses/BSD-3-Clause). @@ -101,9 +99,9 @@ We can't have fast, cheap digital assets and also highly secure and decentralize Tari overcomes this constraint by building two layers: 1. A base layer that provides a public ledger of Tari coin transactions, secured by PoW to maximize security. -2. A DAN consisting of a highly scalable, efficient side-chain that each manages the state of all digital asset. +2. A DAN consisting of a highly scalable, efficient side-chain that each manages the state of all digital asset, called the Ootle. -The DAN layer gives up some security guarantees in exchange for performance. However, in the case of a liveness +The Ootle layer gives up some security guarantees in exchange for performance. However, in the case of a liveness failure (wherein parts of the DAN cannot make progress), the base layer intervenes to break the deadlock and allow the DAN to continue. @@ -127,7 +125,7 @@ cryptocurrencies such as Bitcoin: > "Mimblewimble is the most sound, scalable 'base layer' protocol we know" -- @fluffypony In addition to this, Tari has made some novel additions to the basic Mimblewimble protocol. Primarily, these were -invented to allow the DAN to be built on top of Tari, but have found some great applications generally: +invented to allow the Ootle to be built on top of Tari, but have found some great applications generally: * TariScript. Similar to Bitcoin script, TariScript ([RFC-201], [RFC-202]) provides limited "smart contract" functionality on the base layer protocol. @@ -142,8 +140,9 @@ invented to allow the DAN to be built on top of Tari, but have found some great #### Proof of Work -Tari is mined using a hybrid approach. On average, 50% of block rewards come from [Monero merge-mining], - while 50% come from the [Sha3x][RFC-131] algorithm. Blocks are produced every 2 minutes, on average. +Tari is mined using a hybrid approach. On average, 25% of block rewards come from [Monero merge-mining], +25& solo mined using RandomX, 25% mined using Cuckaroo 29 and 25% come from the [Sha3x][RFC-131] algorithm. +Blocks are produced every 2 minutes, on average. ### The role of the base layer @@ -156,12 +155,12 @@ The Base Layer fulfils these, and only these, major roles: code that they expect and includes functionality like version tracking. 4. Provides a global reference clock for the digital assets layer to help it resolve certain operational failure modes. -### Digital Assets Network +### Digital Assets Network, Ootle -The DAN is focused on achieving high speed and scalability while maintaining a high degree of decentralisation. +The Ootle is focused on achieving high speed and scalability while maintaining a high degree of decentralisation. -The DAN itself is made up of two conceptual levels. On the more fundamental level, the consensus layer uses -Cerberus and emergent HotStuff to reach consensus on state changes in the DAN in a highly scalable, decentralised way. +The Ootle itself is made up of two conceptual levels. On the more fundamental level, the consensus layer uses +Cerberus and emergent HotStuff to reach consensus on state changes in the Ootle in a highly scalable, decentralised way. A big, and probably the biggest, advantage of this approach is that assets in disparate smart contracts can easily interact, without the need for slow, honey pot-shaped bridges. @@ -169,7 +168,7 @@ interact, without the need for slow, honey pot-shaped bridges. Then there is the semantic layer, which is where the Tari contracts are compiled, run and verified inside sandboxed Tari virtual machines. -Together, these levels provide that smart contract enabled digital assets layer, that we've simply been calling the DAN. +Together, these levels provide that smart contract enabled digital assets layer, that we've simply been calling the Ootle. ### Interplay of the layers @@ -183,7 +182,7 @@ enormous; imagine controlling every piece of inventory and their live statistics for a massively multiplayer online role-playing game (MMORPG). The base layer is also too slow. If _any_ state relies on base layer transactions being confirmed, there is an immediate lag before that state change can be considered final, which kills the latency properties we seek for -the DAN. +the Ootle. It is better to keep the two networks almost totally decoupled from the outset, and allow each network to play to its strength. diff --git a/src/RFC-0110_BaseNodes.md b/src/RFC-0110_BaseNodes.md index 899c79b..bb94432 100644 --- a/src/RFC-0110_BaseNodes.md +++ b/src/RFC-0110_BaseNodes.md @@ -4,8 +4,6 @@ ![status: stable](theme/images/status-stable.svg) -**Maintainer(s)**: [Cayle Sharrock](https://github.com/CjS77), [S W van heerden](https://github.com/SWvheerden) and [Stanley Bondi](https://github.com/sdbondi) - # Licence [The 3-Clause BSD Licence](https://opensource.org/licenses/BSD-3-Clause). @@ -55,17 +53,12 @@ their general approach for doing so. * [RFC-0140: SyncAndSeeding](RFC-0140_Syncing_and_seeding.md) -$$ -\newcommand{\so}{\gamma} % script offset -$$ - ## Description ### Broad Requirements Tari Base Nodes form a peer-to-peer network for a proof-of-work based blockchain running the [Mimblewimble] -protocol. The proof-of-work is performed via hybrid mining, that is merge mining with Monero and stand-alone SHA 3. -Arguments for this design are presented [in the overview](RFC-0001_overview.md#proof-of-work). +protocol. The proof-of-work is performed via hybrid mining, Arguments for this design are presented [in the overview](RFC-0001_overview.md#proof-of-work). Tari Base Nodes MUST carry out the following tasks: @@ -76,7 +69,7 @@ Tari Base Nodes MUST carry out the following tasks: * connect to peer nodes to catch up (sync) with their blockchain state; * provide historical block information to peers that are syncing. -Once the Digital Assets Network (DAN) goes live, Base Nodes will also need to support the tasks described in +Once the Ootle goes live, Base Nodes will also need to support the tasks described in [RFC-0303_DAN](RFC-0303_DanOverview.md). These requirements may involve but are not limited to: * maintain an index of validator node registrations; @@ -123,7 +116,7 @@ The transaction is validated as follows: * The transaction excess is a valid public key. This proves that: $$ \Sigma \left( \mathrm{inputs} - \mathrm{outputs} - \mathrm{fees} \right) = 0 $$. * The transaction excess has a unique value across the whole chain. -* The [Tari script] of each input must execute successfully and return the public key that signs the script signature. +* The [Tari script] of each input must execute successfully and return the public key that signs a valid script signature. * The script offset \\( \so\\) is calculated and verified as per [RFC-0201_TariScript]. Rejected transactions are dropped without service interruption and noted in log files. @@ -154,10 +147,10 @@ With an `S` of 1MiB and `N` of 16, the block and transaction body weights are as | | Byte size | Natural Weight | Adjust | Final | |-------------------|-----------|------------------------|--------|------------------------| | Output | | | | | -| - Per output | 832 | 52 | 0 | 52 | +| - Per output | 832 | 52 | +1 | 53 | | - Tari Script | variable | size_of(script) / 16 | 0 | size_of(script) / 16 | | - Output Features | variable | size_of(features) / 16 | 0 | size_of(features) / 16 | -| Input | 169 | 11 | -2 | 9 | +| Input | 169 | 11 | -3 | 8 | | Kernel size | 113 | 8 | 2 | 10 | Pseudocode: diff --git a/src/RFC-0111_BaseNodeArchitecture.md b/src/RFC-0111_BaseNodeArchitecture.md index f839cbe..aeae83f 100644 --- a/src/RFC-0111_BaseNodeArchitecture.md +++ b/src/RFC-0111_BaseNodeArchitecture.md @@ -4,8 +4,6 @@ ![status: stable](theme/images/status-stable.svg) -**Maintainer(s)**: [Cayle Sharrock](https://github.com/CjS77) - # Licence [ The 3-Clause BSD Licence](https://opensource.org/licenses/BSD-3-Clause). @@ -61,7 +59,7 @@ The major components are separated into separate modules. Each module exposes a ### Base Node Service -The Base Node Service fields requests for the local nodes chain state and also accepts newly mined blocks that are +The Base Node Service fields requests for the local node's chain state and also accepts newly mined blocks that are propagating across the network. The service subscribes to NewBlock and BaseNodeRequest messages via the P2P comms interface. These messages are propagated across the P2P network and can also be received directly from other nodes. The service also provides a local interface to its functionality via an asynchronous Request-Response API. @@ -72,8 +70,8 @@ The P2P message types this service subscribes to are: node will validate it. Its action depends on the validation outcome: * _Invalid block_ - drop the block. * _Valid block appending to the longest chain_ - add the block to the local state and propagate the block to peers. - * _Valid block forking off main chain_ - add the block to the local state and propagate the block to peers. - * _Valid block building off unknown block_ - add the orphan block to the local state. + * _Valid block forking off main chain_ - add the orphan block to the local state. + * _Valid* block building off unknown block_ - add the orphan block to the local state. These blocks are only checked for PoW and other stateless checks. * **BaseNodeServiceRequest:** A collection of requests for chain data from the node. @@ -93,8 +91,8 @@ block. The mempool is ephemeral and non-consensus critical, and as such may be a a large mempool is far more important for Base Nodes serving miners than those serving wallets. The mempool structure itself is a set of hash maps as described in [RFC-0190] -When either the node reboots, or it synchronises a default number of 5 blocks, the Mempool sync service will contact peers and sync valid mempool transactions from them. After -it has synced this service runs to field such requests from other peers. +When either the node reboots or it synchronises a default number of 5 blocks, the Mempool Sync Service will contact peers and sync valid mempool transactions from them. After +it has synced, this service runs to field such requests from other peers. The Mempool service handles Mempool Service Requests which it can receive from the P2P comms stack via its subscriptions, via the Mempool RPC service and via an internal Request-Response API. All these interfaces provide the @@ -108,13 +106,13 @@ following calls: The Liveness service can be used by other modules to test the liveness of a specific peer and also periodically tests a set of its connected peers for liveness. This service subscribes to `Ping` P2P messages and responds with `Pong`s. The -service gathers data about the monitored peer's liveness such as its latency. The `Ping` and Pong` messages also contain -a copy of this nodes current Chain Metadata for use by the receiving nodes Chain Metadata Service. +service gathers data about the monitored peer's liveness such as its latency. The `Ping` and `Pong` messages also contain +a copy of this node's current Chain Metadata for use by the receiving node's Chain Metadata Service. ### Chain Metadata Service -The Chain Metadata Service maintains this nodes current Chain Metadata state to be sent out via `Ping` and `Pong` -messages by the Liveness service. This node also monitors the Chain Metadata received from other peers in the `Ping` and +The Chain Metadata Service maintains this node's current Chain Metadata state to be sent out via `Ping` and `Pong` +messages by the Liveness Service. This service also monitors the Chain Metadata received from other peers in the `Ping` and `Pong` messages received by the Liveness service. Once a full round of `Pong` messages are received this service will emit this data as an event which the Base Node State Machine monitors. @@ -147,18 +145,17 @@ be thread-safe. ### P2P communications The Tari Peer to Peer messaging protocol is defined in [RFC-0172]. It is a fire-and-forget style protocol. Messages can be sent directly to a known peer, sent indirectly to an offline or unknown peer and broadcast to a set of peers. When -a message is sent to specific peer it is propagated to the peers local neighbourhood and stored by those peers until it +a message is sent to a specific peer it is propagated to the peer's local neighbourhood and stored by those peers until it comes online to receive the message. Messages that are broadcast will be propagated around the network until the whole network has received them, they are not stored. ### RPC Services Fire-and-forget messaging is not efficient for point to point communications between online peers. For these applications the Base Node provides RPC services that present an API for clients to interact with. These RPC services provide a -Request-Response interface defined by Profobuf for clients to use. RPC also allows for streaming of data which is much +Request-Response interface defined by Protobuf for clients to use. RPC also allows for streaming of data which is much more efficient when transferring large amounts of data. -Examples of RPC services running in -Base Node are: +Examples of RPC services running in the Base Node are: - **Wallet RPC service**: An RPC interface containing methods used by wallets to submit and query transactions on a Base Node - **Base Node Sync RPC Service**: Used by the Base Node State Machine Service to synchronise blocks @@ -194,6 +191,37 @@ A non-exhaustive list of methods the base node module API will expose includes: * Block and transaction validation calls * Block synchronisation calls +### HTTP Interface + +The base node exposes an HTTP API built with [Axum](https://github.com/tokio-rs/axum). Interactive API documentation is +available via Swagger UI at `/swagger-ui`, with the OpenAPI specification served at `/openapi.json`. + +The following endpoints are available: + +| Method | Path | Description | +|:-------|:-----------------------------------|:-----------------------------------------------------| +| GET | `/get_tip_info` | Returns chain tip metadata and sync status | +| GET | `/get_header_by_height` | Retrieves a block header at a given height | +| GET | `/get_height_at_time` | Returns the block height for a given Unix timestamp | +| GET | `/get_utxos_mined_info` | Returns mining info for UTXOs identified by hash | +| GET | `/fetch_utxo` | Fetches a single UTXO by output hash | +| GET | `/get_utxos_deleted_info` | Returns deletion/spend info for a set of UTXOs | +| GET | `/transactions` | Queries a transaction by its excess signature | +| GET | `/sync_utxos_by_block` | Paginated UTXO sync starting from a header hash | +| GET | `/get_utxos_by_block` | Returns all UTXOs for a block by header hash | +| POST | `/json_rpc` | JSON-RPC 2.0 endpoint (e.g. `submit_transaction`) | +| GET | `/generate_kernel_merkle_proof` | Generates a Merkle proof for a kernel signature | +| GET | `/get_mempool_fee_per_gram_stats` | Returns fee-per-gram statistics from the mempool | + +All endpoints use JSON request and response bodies. A global request body size limit of approximately 10 MB is applied, +though several endpoints disable this limit to support larger payloads. Caching behaviour is configurable per route. + +The `/json_rpc` endpoint follows the [JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. Currently +supported methods: + +* `submit_transaction` — Submits a transaction to the mempool. The response includes whether the transaction was + accepted, any rejection reason, and whether the node is synced. + # Change Log | Date | Change | Author | diff --git a/src/RFC-0120_Consensus.md b/src/RFC-0120_Consensus.md index 8e9e6b1..33122a8 100644 --- a/src/RFC-0120_Consensus.md +++ b/src/RFC-0120_Consensus.md @@ -4,7 +4,6 @@ ![status: stable](theme/images/status-stable.svg) -**Maintainer(s)**: [Cayle Sharrock](https://github.com/CjS77), [Stanley Bondi](https://github.com/sdbondi) and [SW van heerden](https://github.com/SWvheerden) # Licence @@ -48,7 +47,7 @@ technological merits of the potential system outlined herein. ## Goals -The aim of this Request for Comment (RFC) is to describe the fields that a block should contain as well as all consensus rules that will determine the validity of a block. +The aim of this Request for Comment (RFC) is to describe the fields that a block should contain, as well as all consensus rules that determine the validity of a block. ## Related Requests for Comment @@ -58,9 +57,9 @@ The aim of this Request for Comment (RFC) is to describe the fields that a block ## Description -Blockchain consensus is a set of rules that a majority of nodes agree on that determines the state of the blockchain. +Blockchain consensus is a set of rules that a majority of nodes agree on, which determines the state of the blockchain. -This RFC details the consensus rules for the Tari network. +This RFC details the consensus rules for the Tari network. ### Blocks [Blocks]: #blocks "Block consensus" @@ -70,28 +69,28 @@ Every [block] MUST: * have _exactly one_ valid [block header], as per the [Block Headers] section * have _exactly one_ [coinbase] transaction * have a total [transaction weight] less than the consensus maximum -* be able to calculate matching Merkle roots ([kernel_mr], [output_mr], [witness_mr], and [input_mr]) +* be able to calculate matching Merkle roots ([kernel_mr], [output_mr], and [input_mr]) * each [transaction input] MUST: * be of an allowed [transaction input] version - * spend an existing valid [UTXO] with a maturity less than the current block height + * spend an existing valid [UTXO] with a maturity less than or equal to the current block height * satisfy the [covenant] attached to the [UTXO] * have a valid [script signature] * be in a canonical order (see [Transaction ordering]) * each [transaction output] MUST: * be of an allowed [transaction output] version - * have a unique domain separated hash (`version || features || commitment || script || covenant || encrypted_values`) with the domain (`transaction_output`) + * have a unique domain-separated hash (`version || features || commitment|| RangeProof Hash || Sender Offset Public Key || Metadata signature || script || covenant || encrypted_data || minimum value promise`) with the domain (`transaction_output`) * have a unique commitment in the current [UTXO] set * be in a canonical order (see [Transaction ordering]) * have a valid [range proof] * have a valid [metadata signature] * contain only allowed opcodes in the script -* each [transaction kernel] MUST +* each [transaction kernel] MUST: * have a valid kernel excess signature * have a unique excess -* have a valid total script offset, \\( \gamma \\), see [script-offset]. -* the number of `BURNED` outputs MUST equal the number of `BURNED_KERNEL` kernels exactly, -* the commitment values of each burnt output MUST match the commitment value of each corresponding `BURNED_KERNEL` exactly. -* the transaction commitments and kernels MUST balance, as follows: +* have a valid total script offset, \\( \gamma \\); see [script-offset]. +* The number of `BURNED` outputs MUST equal the number of `BURNED_KERNEL` kernels exactly. +* The commitment value of each burnt output MUST match the commitment value of each corresponding `BURNED_KERNEL` exactly. +* The transaction commitments and kernels MUST balance, as follows: $$ \begin{align} @@ -105,7 +104,7 @@ Every [block] MUST: $$ -If a [block] does not conform to the above, the block SHOULD be discarded and MAY ban the peer that sent it. +If a [block] does not conform to the above, the block SHOULD be discarded, and the node MAY ban the peer that sent it. #### Coinbase [coinbase]: #coinbase "Coinbase consensus" @@ -113,16 +112,16 @@ If a [block] does not conform to the above, the block SHOULD be discarded and MA A coinbase transaction contained in a block MUST: * be the only transaction in the block with the coinbase flag -* consist of exactly one output and one kernel (no input) +* consist of at least one output and one kernel (no inputs) * have a valid kernel signature * have a value exactly equal to the emission at the block height it was minted (see [emission schedule]) plus the total transaction fees within the block * have a lock-height as per consensus -* can not have a offset except 0 -* can not have a script offset except 0 +* MUST NOT have an offset other than 0 +* MUST NOT have a script offset other than 0 -A coinbase transaction contained in a block CAN: -* include any arbitrary 64 bytes of extra data, [coinbase-extra] +A coinbase transaction contained in a block MAY: +* include any arbitrary 64 bytes of extra data; see [coinbase-extra] ### Block Headers [block headers]: #block-headers "Block headers" @@ -133,28 +132,30 @@ Every [block header] MUST contain the following fields: * height; * prev_hash; * timestamp; -* output_mr; -* output_mmr_size; * input_mr; +* output_mr; +* block_output_mr; +* output_smt_size; * witness_mr; * kernel_mr; * kernel_mmr_size; * total_kernel_offset; * script_kernel_offset; -* nonce; -* pow. +* validator_node_mr; +* validator_size; +* pow; +* nonce. The [block header] MUST conform to the following: -* The nonce and [PoW](#pow) must be valid for the [block header]. +* The nonce and [PoW](#pow) MUST be valid for the [block header]. * The [achieved difficulty] MUST be greater than or equal to the [target difficulty]. -* The [FTL] and [MTP] rules, detailed below. -* The block hash must not appear in the bad block list. +* The timestamp MUST satisfy the [FTL] and [MTP] rules, detailed below. +* The block hash MUST NOT appear in the bad block list. The Merkle roots are validated as part of the full block validation, detailed in [Blocks]. -If the [block header] does not conform to any of the above, the [block] SHOULD be rejected and MAY ban the peer that -sent it. +If the [block header] does not conform to any of the above, the [block] SHOULD be rejected, and the node MAY ban the peer that sent it. #### Version @@ -163,8 +164,8 @@ This is the version currently running on the chain. The version MUST conform to the following: * It is represented as an unsigned 16-bit integer. -* Version numbers MUST be incremented whenever there is a change in the blockchain schema or validation rules starting from 0. -* The version must be one of the allowed versions for the consensus rules at this block's height. +* Version numbers MUST be incremented whenever there is a change in the blockchain schema or validation rules, starting from 0. +* The version MUST be one of the allowed versions for the consensus rules at this block's height. #### Height @@ -182,7 +183,7 @@ This is the hash of the previous block's header. The prev_hash MUST conform to the following: -* represented as an array of unsigned 8-bit integers (bytes) in little-endian format. +* Represented as an array of unsigned 8-bit integers (bytes) in little-endian format. * MUST be a hash of the entire contents of the previous block's header using the domain (`block_header`). #### Timestamp @@ -191,21 +192,14 @@ This is the timestamp at which the block was mined. The timestamp MUST conform to the following: -* Must be transmitted as UNIX timestamp. +* MUST be transmitted as a UNIX timestamp. * MUST be less than [FTL]. * MUST be higher than the [MTP]. #### Output_mr [output_mr]: #output_mr "Output Merkle root" -The `output_mr` MUST be calculated as follows: Hash (`TXO MMR root` || Hash(`spent TXO bitmap`)). - -The `TXO MMR root` is the MMR root that commits to every [transaction output] that has ever existed since -the genesis [block]. - -The `spent TXO bitmap` is a compact serialized [roaring bitmap] containing all the output MMR leaf indexes -of all the outputs that have ever been spent. - +The `output_mr` MUST be calculated as the sparse Merkle tree root of all UNSPENT outputs in the blockchain, after this block has been applied. The output_mr MUST conform to the following: * Represented as an array of unsigned 8-bit integers (bytes) in little-endian format. @@ -218,30 +212,25 @@ This is the total size of the leaves in the output Merkle mountain range. The Output_mmr_size MUST conform to the following: * Represented as a single unsigned 64-bit integer. + +#### Block_output_mr -#### Input_mr -[input_mr]: #input_mr "Input Merkle root" - -This is the Merkle root of all the inputs in the block, which consists of the hashed inputs. It is used to prove that -all inputs are correct and not changed after mining. This MUST be constructed by adding, in order, the hash of every -input contained in the block. +The `block_output_mr` MUST be calculated as the Merkle mountain range tree root of all non-coinbase outputs, appended with the Merkle mountain range tree root of all coinbase outputs. -The input_mr MUST conform to the following: +The block_output_mr MUST conform to the following: * Represented as an array of unsigned 8-bit integers (bytes) in little-endian format. -* The hashing function must be blake2b with a 256-bit digest. +* The hashing function used MUST be blake2b with a 256-bit digest. -#### Witness_mr -[witness_mr]: #witness_mr "Witness Merkle root" +#### Input_mr +[input_mr]: #input_mr "Input Merkle root" -This is the Merkle root of the output witness data, specifically all created outputs’ [range proof]s and -metadata signatures. This MUST be constructed by -Hash ( `RangeProof` || `metadata commitment signature`), in order, for every output contained in the block. +This is the Merkle root of all the inputs in the block, consisting of the hashed inputs. It is used to prove that all inputs are correct and have not been changed after mining. This MUST be constructed by adding, in order, the hash of every input contained in the block. -The witness_mr MUST conform to the following: +The input_mr MUST conform to the following: * Represented as an array of unsigned 8-bit integers (bytes) in little-endian format. -* The hashing function used must be blake2b with a 256-bit digest. +* The hashing function MUST be blake2b with a 256-bit digest. #### Kernel_mr [kernel_mr]: #kernel_mr "Kernel Merkle root" @@ -250,8 +239,8 @@ This is the Merkle root of the kernels. The kernel_mr MUST conform to the following: -* Must be transmitted as an array of unsigned 8-bit integers (bytes) in little-endian format. -* The hashing function used must be blake2b with a 256-bit digest. +* MUST be transmitted as an array of unsigned 8-bit integers (bytes) in little-endian format. +* The hashing function used MUST be blake2b with a 256-bit digest. #### Kernel_mmr_size @@ -267,7 +256,7 @@ This is the total summed offset of all the transactions in this block. The total_kernel_offset MUST conform to the following: -* Must be transmitted as an array of unsigned 8-bit integers (bytes) in little-endian format +* MUST be transmitted as an array of unsigned 8-bit integers (bytes) in little-endian format. #### Total_script_offset @@ -275,7 +264,7 @@ This is the total summed script offset of all the transactions in this block. The total_script_offset MUST conform to the following: -* Must be transmitted as an array of unsigned 8-bit integers (bytes) in little-endian format +* MUST be transmitted as an array of unsigned 8-bit integers (bytes) in little-endian format. #### Nonce @@ -283,27 +272,26 @@ This is the nonce used in solving the Proof of Work. The nonce MUST conform to the following: -* MUST be transmitted as an unsigned 64-bit integer; -* for RandomX blocks, thus MUST be 0 +* MUST be transmitted as an unsigned 64-bit integer. +* For RandomX blocks, this MUST be 0. #### PoW -This is the Proof of Work algorithm used to solve the Proof of Work. This is used in conjunction with the Nonce. +This is the Proof of Work algorithm used to mine the block. It is used in conjunction with the nonce. The [PoW] MUST contain the following: -* pow_algo as an enum (0 for RandomX, 1 for Sha3x). +* pow_algo as an enum (0 for RandomX-M, 1 for Sha3x, 2 for RandomX-T, and 3 for C29). * pow_data for RandomX blocks as an array of unsigned 8-bit integers (bytes) in little-endian format, containing the RandomX merge-mining Proof-of-Work data. - * the RandomX seed, stored as `randomx_key` within the RandomX block, must have not been first seen in a block with confirmations more than `max_randomx_seed_height`. + * The RandomX seed, stored as `randomx_key` within the RandomX block, MUST NOT have been first seen in a block with more than `max_randomx_seed_height` confirmations. * pow_data for Sha3x blocks MUST be empty. #### Difficulty Calculation [target difficulty]: #target-difficulty "Target Difficulty" -The target difficulty represents how difficult it is to mine a given block. This difficulty is not fixed and needs to -constantly adjust to changing network hash rates. +The target difficulty represents how difficult it is to mine a given block. This difficulty is not fixed and needs to constantly adjust to changing network hash rates. -The difficulty adjustment MUST be calculated using a linear-weighted moving average (LWMA) algorithm (2) +The difficulty adjustment MUST be calculated using a linear-weighted moving average (LWMA) algorithm (2): $$ \newcommand{\solvetime}{ \mathrm{ST_i} } \newcommand{\solvetimemax}{ \mathrm{ST_{max}} } @@ -312,9 +300,9 @@ $$ | Symbol | Value | Description | |-------------------------|-------------------------|---------------------------------------------------------------------------------------------------------------------| | N | 90 | Target difficulty block window | -| T | SHA3x: 300 RandomX: 200 | Target block time in seconds. The value used depends on the PoW algorithm being used. | -| \\( \solvetimemax \\) | SHA3x: 1800 RandomX: 1200 | Maximum solve time. This is six times the target time of the current PoW algorithm. | -| \\( \solvetime \\) | variable | The timestamp difference in seconds between block _i_ and _i - 1_ where \\( 1 \le \solvetime \le \solvetimemax \\) | +| T | 480 | Target block time in seconds. The value used depends on the PoW algorithm being used. | +| \\( \solvetimemax \\) | 2880 | Maximum solve time. This is six times the target time of the current PoW algorithm. | +| \\( \solvetime \\) | variable | The timestamp difference in seconds between block _i_ and _i - 1_ where \\( 1 \le \solvetime \le \solvetimemax \\) | | \\( \mathrm{D_{avg}} \\)| variable | The average difficulty of the last _N_ blocks | $$ @@ -326,29 +314,28 @@ $$ \tag{2} $$ -It is important to note that the two proof of work algorithms are calculated _independently_. i.e., if the current block uses _SHA3x_ proof of work, the block window and solve times only include _SHA3x_ blocks and vice versa. +It is important to note that the two proof-of-work algorithms are calculated _independently_; i.e., if the current block uses _SHA3x_ proof of work, the block window and solve times only include _SHA3x_ blocks, and vice versa. ### FTL [FTL]: #ftl "Future Time Limit" -The Future Time Limit. This is how far into the future a time is accepted as a valid time. Any time that is more than the FTL is rejected until such a time that it is not more than the FTL. -The FTL is calculated as (T*N)/20 with T and N defined as: -T: Target time - This is the ideal time that should pass between blocks that have been mined. -N: Block window - This is the number of blocks used when calculating difficulty adjustments. +The Future Time Limit (FTL) defines how far into the future a timestamp is accepted as valid. Any block with a timestamp beyond the FTL is rejected until the current time catches up. + +The FTL is calculated as (T*N)/20, with T and N defined as: +- T: Target time — the ideal time that should pass between mined blocks. +- N: Block window — the number of blocks used when calculating difficulty adjustments. ### MTP [MTP]: #mtp "Median Time Passed" -The Median Time Passed (MTP) is the lower bound calculated by taking the median average timestamp of the -last _N_ blocks. Any block with a timestamp that is less than MTP will be rejected. +The Median Time Passed (MTP) is the lower bound calculated by taking the median timestamp of the last _N_ blocks. Any block with a timestamp less than the MTP will be rejected. ### Total accumulated proof of work -This is defined as the total accumulated proof of work done on the blockchain. Tari uses two _independent_ proof of work algorithms -rated at different difficulties. To compare them, we simply multiply them together into one number: +This is defined as the total accumulated proof of work done on the blockchain. Tari uses four _independent_ proof-of-work algorithms rated at different difficulties. To compare them, they are simply multiplied together into one number: $$ \begin{align} - \textit{accumulated_randomx_difficulty} * \textit{accumulated_sha3x_difficulty} + \textit{accumulated_randomxM_difficulty} * \textit{accumulated_sha3x_difficulty} * \textit{accumulated_randomxT_difficulty} * \textit{accumulated_C29_difficulty} \end{align} \tag{3} $$ @@ -357,13 +344,11 @@ This value is used to compare chain tips to determine the strongest chain. ### Transaction Ordering [Transaction ordering]: #transaction-ordering "Canonical Transaction Ordering" -The order in which transaction inputs, outputs, and kernels are added to the Merkle mountain range completely changes the -final Merkle root. Input, output, and kernel ordering within a block is, therefore, part of the consensus. +The order in which transaction inputs, outputs, and kernels are added to the Merkle mountain range completely changes the final Merkle root. Input, output, and kernel ordering within a block is, therefore, part of consensus. -The block MUST be transmitted in canonical ordering. The advantage of this approach is that sorting does not need to be -done by the whole network, and verification of sorting is exceptionally cheap. +The block MUST be transmitted in canonical ordering. The advantage of this approach is that sorting does not need to be done by the whole network, and verification of sorting is exceptionally cheap. -- Transaction outputs are sorted lexicographically by the byte representation of their Pedersen commitment i.e. ( \\(k \cdot G + v \cdot H\\) ). +- Transaction outputs are sorted lexicographically by the byte representation of their Pedersen commitment, i.e. \\(k \cdot G + v \cdot H\\). - Transaction kernels are sorted lexicographically by the excess signature byte representation. - Transaction inputs are sorted lexicographically by the hash of the output that is spent by the input. diff --git a/src/RFC-0122_Burning.md b/src/RFC-0122_Burning.md index 6786822..b6a4b29 100644 --- a/src/RFC-0122_Burning.md +++ b/src/RFC-0122_Burning.md @@ -4,7 +4,6 @@ ![status: draft](theme/images/status-draft.svg) -**Maintainer(s)**: [Cayle Sharrock](https://github.com/CjS77), [stringhandler](https://github.com/stringhandler) and [SW van heerden](https://github.com/SWvheerden) # Licence @@ -48,7 +47,7 @@ technological merits of the potential system outlined herein. ## Goals -The aim of this Request for Comment (RFC) is to describe the process of Burning UTXOs and to track the amount burned. +The aim of this Request for Comment (RFC) is to describe the process of burning UTXOs and to track the amount burned. ## Related Requests for Comment @@ -56,23 +55,22 @@ The aim of this Request for Comment (RFC) is to describe the process of Burning ## Description -Blockchains have used the burn method to destroy coins in circulation and block their use forever. Most chains use a reclaimable address -to denote burned coins. Using [RFC-0201: TariScript](RFC-0201_TariScript.md), Tari can also use this method, but this does not explicitly +Blockchains have used the burn method to destroy coins in circulation and prevent their use forever. Most chains use a reclaimable address +to denote burned coins. Using [RFC-0201: TariScript](RFC-0201_TariScript.md), Tari can also use this method, but it does not explicitly remove the coins from circulation. This RFC details a method to remove coins from circulation permanently. -An excellent example of using burned coins is for a [Perpetual One-way Peg](https://medium.com/@RubenSomsen/21-million-bitcoins-to-rule-all-sidechains-the-perpetual-one-way-peg-96cb2f8ac302) this allows users -create utility tokens on a sidechain or in Tari's case the DAN. By not allowing funds to be moved back, the sidechain gains an auditable total utilitarian value -. Value speculation is largely removed as the sidechain will only ever be as valuable as value of coins burnet in the peg. +An excellent example of using burned coins is a [Perpetual One-way Peg](https://medium.com/@RubenSomsen/21-million-bitcoins-to-rule-all-sidechains-the-perpetual-one-way-peg-96cb2f8ac302). This allows users to +create utility tokens on a sidechain or, in Tari's case, the DAN. By not allowing funds to be moved back, the sidechain gains an auditable total utilitarian value. Value speculation is largely removed, as the sidechain will only ever be as valuable as the value of coins burned in the peg. ## Introduction To completely remove coins from circulation, we need to mark outputs as burned, and we need to change the balance equation to -allow pruned nodes and non pruned nodes to still verify the integrity and emission of Tari. +allow both pruned and non-pruned nodes to verify the integrity and emission of Tari. ### TL;DR -In order to get burns working, we flag each desired output as burned with a flag. To calculate the emission of the network, we need -to store the commitment of the burned output in a kernel. This will allow any pruned node to verify the emission of the network and all burned outputs. +In order to get burns working, we flag each desired output as burned. To calculate the emission of the network, we need +to store the commitment of the burned output in a kernel. This allows any pruned node to verify the emission of the network and all burned outputs. ### Transaction output changes @@ -81,7 +79,7 @@ Inside this field, we track every possible type of output. We need to add anothe ```rust,ignore pub enum OutputType { - /// An standard non-coinbase output. + /// A standard non-coinbase output. Standard = 0, /// Output is a coinbase output, must not be spent until maturity. Coinbase = 1, @@ -92,8 +90,8 @@ pub enum OutputType { ### Kernel changes -Currently, each transaction has to have one or more kernels, [TransactionKernel](https://github.com/tari-project/tari/blob/2ca06724f0ab7c63eb0b6caab563372f353f4348/base_layer/core/src/transactions/transaction_components/transaction_kernel.rs#L53). This tracks details such as the balance proof of each transaction as well as other information essential for the transaction consensus. Here we add an Optional field to track burned commitments. -For each burned output, we need to have a kernel where the burned output's commitment is stored. +Currently, each transaction has to have one or more kernels, [TransactionKernel](https://github.com/tari-project/tari/blob/2ca06724f0ab7c63eb0b6caab563372f353f4348/base_layer/core/src/transactions/transaction_components/transaction_kernel.rs#L53). This tracks details such as the balance proof of each transaction as well as other information essential for transaction consensus. Here we add an optional field to track burned commitments. +For each burned output, we need to have a kernel where the burned output's commitment is stored. ```rust,ignore pub struct TransactionKernel { @@ -117,7 +115,7 @@ pub struct TransactionKernel { } ``` Each kernel also has a field called [KernelFeatures](https://github.com/tari-project/tari/blob/2ca06724f0ab7c63eb0b6caab563372f353f4348/base_layer/core/src/transactions/transaction_components/kernel_features.rs#L36) that defines the properties of the kernel. The feature set needs to be expanded to include a burn type. -Inside this field, we track every possible type of output. We need to add another type here called `BURNED_KERNEL`. +Inside this field, we track every possible type of kernel. We need to add another type here called `BURNED_KERNEL`. ```rust,ignore pub struct KernelFeatures: u8 { @@ -128,18 +126,18 @@ pub struct KernelFeatures: u8 { } ``` -For each burned output in a transaction, there needs to be a kernel. This means that if a transaction has two burned outputs, it needs at least two kernels. -This stops a node from publishing an aggregated inflated commitment in the kernel. +For each burned output in a transaction, there needs to be a kernel. This means that if a transaction has two burned outputs, it needs at least two kernels. +This prevents a node from publishing an aggregated inflated commitment in the kernel. ### Consensus rules changes -When a block or transaction is received with a burned output, there: +When a block or transaction is received with a burned output: * the number of `BURNED` outputs MUST equal the number of `BURNED_KERNEL` kernels exactly, -* the commitment values of each burnt output MUST match the commitment value of each corresponding `BURNED_KERNEL` exactly. +* the commitment values of each burned output MUST match the commitment value of each corresponding `BURNED_KERNEL` exactly. -### Chain balance equation changes +### Chain balance equation changes Currently, when checking the total chain emission, the following equation must hold: $$ diff --git a/src/about.md b/src/about.md index 6144874..dfc127b 100644 --- a/src/about.md +++ b/src/about.md @@ -3,24 +3,46 @@ Tari is a community-driven project. The documents presented in this RFC collection have typically gone through several iterations before reaching this point: -* Ideas and questions are posted in #tari-dev on [#FreeNode IRC](https://freenode.net/). This is typically short-form +* Ideas and questions are posted in the [Tari Discord](https://discord.gg/hPABK5WV). This is typically short-form content with rapid feedback. Often, these conversations will lead to someone posting an [issue] or RFC [pull request]. * RFCs are "Requests for Comment", so although the proposals in these documents are usually well-thought out, they are - not cast in stone. RFCs can, and should, undergo further evaluation and discussion by the community. RFC comments are - best made using Github [issue]s. + not set in stone. RFCs can, and should, undergo further evaluation and discussion by the community. RFC comments are + best made using GitHub [issue]s. +* These RFCs are for new proposals and ideas. Ideas can be discussed and commented on. +* Some issues might be converted into RFCs or vice versa. + +## Issues vs RFCs +Most minor bug fixes or feature requests might not require an RFC, and an issue on the relevant repository will be enough. When a new feature or request changes critical consensus or changes how the network operates, it will require an RFC. Sometimes this will be only after an issue existed and a pull request is opened, but typically an RFC would be opened up first. + + +## RFC Naming +New RFCs should follow the format given in the [RFC template](RFC_template.md). + +RFCs are given a numbering scheme `RFC-{X}-{Y}` where `{Y}` is a number and `{X}` is one of the following: +* `MT` - MinoTari, all RFCs for the base layer +* `O` - Ootle, all RFCs for the second layer +* `TU` - Tari Universe, all RFCs relating specifically to Tari Universe + +### Prefixes + +All stable and in-use RFCs will just be named `RFC-{X}-{Y}`; proposals, accepted, deprecated, and rejected RFCs will use prefixes: + +* `p-RFC-{X}-XXXX` is a proposal RFC. It does not have a number yet; `{X}` still needs to be one of the correct tags. +* `a-RFC-{X}-{Y}` is an accepted RFC. It is an accepted idea, but not yet implemented. +* `d-RFC-{X}-{Y}` is a deprecated RFC. +* `r-RFC-{X}-{Y}` is a rejected RFC; these are assigned a number. -New RFC's should follow the format given in the [RFC template](RFC_template.md). ## Lifecycle RFCs go through the following lifecycle, which roughly corresponds to the [COSS](https://github.com/unprotocols/rfc/blob/master/2/README.md): | Status | | Description | |:------------|:--------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Draft | ![draft](theme/images/status-draft.svg) | Changes, additions and revisions can be expected. | -| Stable | ![stable](theme/images/status-stable.svg) | Typographical and cosmetic changes aside, no further changes should be made. Changes to the Tari code base w.r.t. a stable RFC will lead to the RFC becoming out of date, deprecated, or retired. | -| Out of date | ![out of date](theme/images/status-outofdate.svg) | This RFC has become stale due to changes in the code base. Contributions will be accepted to make it stable again if the changes are relatively minor, otherwise it should eventually become deprecated or retired. | -| Deprecated | ![deprecated](theme/images/status-deprecated.svg) | This RFC has been replaced by a newer RFC document, but is still is use in some places and/or versions of Tari. | -| Retired | ![retired](theme/images/status-retired.svg) | The RFC is no longer in use on the Tari network. | +| Draft | ![draft](theme/images/status-draft.svg) | New ideas and proposals. These are not yet accepted; changes, additions, and revisions can be expected. | +| Stable | ![stable](theme/images/status-stable.svg) | Typographical and cosmetic changes aside, no further changes should be made. Changes to the Tari codebase will lead to the RFC becoming out of date, deprecated, or retired. | +| Out of date | ![out of date](theme/images/status-outofdate.svg) | This RFC has become stale due to changes in the codebase. Contributions will be accepted to make it stable again if the changes are relatively minor; otherwise it should eventually become deprecated or retired. | +| Deprecated | ![deprecated](theme/images/status-deprecated.svg) | This RFC has been replaced by a newer RFC document, but is still in use in some places and/or versions of Tari. | +| Retired | ![retired](theme/images/status-retired.svg) | This RFC is no longer in use by the Tari network. | [pull request]: https://github.com/tari-project/tari/pulls?q=is%3Aopen+is%3Apr+label%3ARFC 'Tari RFC pull requests'