I-TIP-RFC-MT-0122: Burning
| TIP | I-TIP-RFC-MT-0122 |
|---|---|
| Title | Consensus-level Burn Transactions |
| Last Modified | 2026-07-16 |
| Authors | Tari Labs |
| Status | Implemented |
| Type | RFC |
| Created | 2022-09-26 |
| References |
Consensus-level burn transactions
Licence
Copyright 2019 The Tari Development Community
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of this document must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS DOCUMENT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”, AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Language
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY” and “OPTIONAL” in this document are to be interpreted as described in BCP 14 (covering RFC2119 and RFC8174) when, and only when, they appear in all capitals, as shown here.
Disclaimer
This document and its content are intended for information purposes only and may be subject to change or update without notice.
This document may include preliminary concepts that may or may not be in the process of being developed by the Tari community. The release of this document is intended solely for review and discussion by the community of the 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.
Related Requests for Comment
Description
Blockchains have used the burn method to destroy coins in circulation and prevent their spend forever. Most chains use a reclaimable address to denote burned coins. Using RFC-0201: TariScript, 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 a Perpetual One-way Peg. This allows users to create utility tokens on a sidechain or, in Tari’s case, the Ootle. 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 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. 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
Each transaction output has a field called OutputFeatures that tracks the unique properties of each output. Inside this field, we track every possible type of output. We need to add another type here called burned.
pub enum OutputType {
/// A standard non-coinbase output.
Standard = 0,
/// Output is a coinbase output, must not be spent until maturity.
Coinbase = 1,
/// This output is burned and may never be used as a transaction input.
Burned = 2,
}
Kernel changes
Currently, each transaction has to have one or more kernels, TransactionKernel. 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.
pub struct TransactionKernel {
pub version: TransactionKernelVersion,
/// Options for a kernel's structure or use
pub features: KernelFeatures,
/// Fee originally included in the transaction this proof is for.
pub fee: MicroTari,
/// This kernel is not valid earlier than lock_height blocks
/// The max lock_height of all *inputs* to this transaction
pub lock_height: u64,
/// Remainder of the sum of all transaction commitments (minus an offset). If the transaction is well-formed,
/// amounts plus fee will sum to zero, and the excess is hence a valid public key.
pub excess: Commitment,
/// An aggregated signature of the metadata in this kernel, signed by the individual excess values and the offset
/// excess of the sender.
pub excess_sig: Signature,
/// This is an optional field that must be set if the transaction contains a burned output.
pub burn_commitment: Option<Commitment>,
}
Each kernel also has a field called KernelFeatures 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 kernel. We need to add another type here called BURNED_KERNEL.
pub struct KernelFeatures: u8 {
/// Coinbase transaction
const COINBASE_KERNEL = 1u8;
/// Burned output
const BURNED_KERNEL = 2u8;
}
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:
- the number of
BURNEDoutputs MUST equal the number ofBURNED_KERNELkernels exactly, - the commitment values of each burned output MUST match the commitment value of each corresponding
BURNED_KERNELexactly.
Chain balance equation changes
Currently, when checking the total chain emission, the following equation must hold: $$ \begin{align} &\sum_i\mathrm{C_{i}} \stackrel{?}{=} E_l \cdot H + \sum_k\mathrm{K_k} + \text{offset}\\ & \text{for each unspent output}, i, \\ & \text{for each kernel excess}, k \\ & \textit{offset }\text{is the total kernel offset} \\ & \text{and }E_l\text{ is total emission up to block } l\\ \end{align} \tag{1} $$
To include burnt outputs in the balance, we can immediately mark burnt outputs as spent (and thus allow them to be pruned), and introduce the additional requirement of tracking the total sum of all burnt output commitments.
This sum is easily verified by summing all BURNED_KERNEL commitments in the blockchain history. These are available to all nodes since the kernels are never pruned.
The balance equation then becomes $$ \begin{align} &\sum_i\mathrm{C_{i}} \stackrel{?}{=} E \cdot H + \sum_k\mathrm{K_k} + \text{offset} - \sum_m\mathrm{Cburn_{m}}\\ & \text{for each unspent output}, i, \\ & \text{for each burned output}, m, \\ & \text{for each kernel excess}, k \\ & \textit{offset }\text{is the total kernel offset} \\ & \text{and }E_l\text{ is total emission up to block } l\\ \end{align} \tag{2} $$
When verifying total chain emission, equation (2) MUST hold.