-
Notifications
You must be signed in to change notification settings - Fork 7
Definitions
A protoburn is a mechanism by which runes are burned and a subprotocol-only representation is transferred onto a UTXO, to be indexed accordingly by the subprotocol indexer. The RuneId identifier for the asset is the same as it occurs on the runes metaprotocol, as it relates to transferring the assets with Edict structures packed into the Protocol messages for our extended Runestone. A protoburn is targeted by a Runestone pointer or edict on the runes protocol in a way that renders those runes provably unspendable, but does not result in a cenotaph. To target a protoburn, an Edict pointer targets the OP_RETURN output that the Runestone itself lives on. Edicts that target the OP_RETURN output are handled once per rune. i.e. for two edicts for the same RuneId that declare a transfer to the OP_RETURN, the first edict targets the first protoburn in the set of Protostones, the second edict targets the second protoburn, etc. It is by this mechanism we can provide a way to order a set of operations packed into a protocol message succinctly, since Edict structures in a Runestone must appear in a sorted order.
When evaluating protoburns, a protoburn may specify the From
tag, where each value in this list is interpreted as a u32 representing the index of the edict which should be taken to be the source of value transferred into the protoburn. Protoburns which specify the From
tag are evaluated first, and edicts defined in this field are skipped as protoburns which do not specify a From
are evaluated. In processing the set of protoburns which specify a From
tag, a repeated appearance of an edict already specified in an earlier protoburn is safely ignored.
Protorunes are runes that have been protoburned and no longer are recognized as spendable by the usual Runestone edicts. To transfer protorunes, it is required to use Protostone objects packed into the Protocol field of a Runestone.
A subprotocol is a metaprotocol that runs the indexer program of its parent protocol as a dependency.
A protorunes-compatible subprotocol is a subprotocol of runes, which therefore must as a dependency run the runes indexing logic. Additionally, if a subprotocol is protorunes-compatible then it MUST correctly interpret and process the data structures described in this document, which includes the processing of Runestone and any edicts it contains, as well as the parsing of the Protocol field, which will never clash with the set of fields we will see in this version of runes or any protocol upgrades, for reasons we will describe.
A protomessage is an OP_RETURN output which can be the target of one or more edicts, the target of a protoburn, or the target of another protomessage. A protomessage output must delegate the sum of value that targets it to the pointer and refund_pointer, crediting any assets not forwarded to either pointer to the runtime itself. The sum of runes which exist on a subprotocol MUST NOT exceed the sum of runes bridged into a subprotocol. Subprotocols may define protorune assets, which exist exclusively on the subprotocol, but can be transferred/minted/burned or otherwise transacted against by the protocol runtime, provided the encoding of their RuneId can still be parsed as two u128 values. For a RuneId of a subprotocol asset, at least one bit must be set in the high 64 bits of the u128 encoding of what is traditionally the height of the block for a given etching, OR one bit is set in the high 96 bits of what is traditionally the txindex of the transaction for a given etching. This permits us to define a space of custom assets exclusive to the subprotocol which are still compatible and can be transacted with using the Runestone structure, while at the same time ensuring that we cannot clash with the space of RuneIds on the runes protocol.
A predicate is a set of clauses that define the minimum balance sheet of protorunes which MUST exist on the output a protomessage points to. If the predicate is not satisfied, a protomessage must have no side effect. The balance sheet of protorunes MUST, in this case, be transferred to the output defined by the refund_pointer. A standard predicate structure does not occur in the data structures used in protorunes, since it is not needed in every subprotocol and may need to be modeled in different ways in different contexts, but this vocabulary is provided to model a concept which should be a feature of protorune runtime messages for which there is settlement risk.
A predicate mechanism should be available to the user in any instance where a reorg of the Bitcoin blockchain could change the balance sheet held by an input being used in a way that is significant to transactions which follow it. In cases where this occurs, we ensure that all value being used as inputs to a protomessage are safely returned to the refund_pointer
.
A ProtoruneRuneId is a construct defined in Protorunes meant to encode arbitrary data as LEB128 integers in the RuneId field.
Normally, RuneIds are generated by the indexer as the block number and tx index, but Protorunes aims to support arbitrary runes and derivatives of runes, such as LP tokens, that require more data than just the block number and tx index. For example, a LP token for an AMM protocol can encode the two tokens in the AMM in the RuneId. Instead of having to etch a protorune or rune that is meant to be the LP token, the AMM indexer can designate the LP token of rune A and rune B to have a runeid of LEB128["RuneId1", "RuneId2"].
The LEB128 encoding is done as follows: the inputs (an array of u128s) that are intended to be encoded in the ProtoruneRuneId are converted to LEB128s and concatenated together. Then, the result is zero padded to 32 bytes (with the zeros padding the lower memory addresses, in other words, shifting the data to the right, or the higher memory addresses). The lower 16 bytes are used as the block number, and the higher 16 bytes are interpreted as the tx index.
Note that ProtoruneRuneId is meant to be extended or used as an API by subprotocols, and it is the responsibility of the subprotocol's engineers to ensure that the runeIds generated by ProtoruneRuneIds do not conflict with existing rune ids on Runes. This is extremely unlikely to happen, as it would require 14 bytes of pure 0s input as data, in order for txIndex to be valid, and then the data needs to be higher than 840,000 for the block. It is also the responsibility of the subprotocol engineers to ensure that the resulting RuneId would not be rendered a cenotaph by the canonical Runes indexer. For instance, one may need to add custom hardcoded bits in the block portion of the RuneId, since rune ids with block number 0 are considered cenotaphs.