diff --git a/commitment-layer/multi-protocol-commitments-mpc.md b/commitment-layer/multi-protocol-commitments-mpc.md index 225eec9..b2b049c 100644 --- a/commitment-layer/multi-protocol-commitments-mpc.md +++ b/commitment-layer/multi-protocol-commitments-mpc.md @@ -1,91 +1,4 @@ -# Multi Protocol Commitments - MPC - -Multi Protocol Commitments address the following important requirements: - -1. How the tagged `mpc::Commitment` hash, committed in Bitcoin Blockchain according to `Opret` or `Tapret` schemes, is constructed. -2. How state changes associated with more than one contract can be stored in a single commitment. - -The preceding points are addressed through an **ordered merkelization** of the multiple contracts (actually their [transition bundles](../annexes/glossary.md#transition-bundle) IDs) in an [MPC](../annexes/glossary.md#multi-protocol-commitment-mpc) Tree whose properties will be addressed in depth in this section. Eventually, the root of the tree (`mpc::Root)` is hashed once more to get the `mpc:Commitment` which is finally committed in an output of the [witness transaction](../annexes/glossary.md#witness-transaction) using the appropriate [Deterministic Bitcoin Commitment](../annexes/glossary.md#deterministic-bitcoin-commitment-dbc) construction. - -

Each RGB contract has a unique position in the MPC Tree determined by a modular division applied to its ContractId according to the width of the tree. In this example, the MPC tree has a width of 8.

- -## MPC Root Hash - -The commitment of the MPC tree - which goes either into [Opret](deterministic-bitcoin-commitments-dbc/opret.md) or into [Tapret](deterministic-bitcoin-commitments-dbc/tapret.md) commitments - is the `mpc::Commitment` constructed in BIP-341 fashion as follows: - -`mpc::Commitment = SHA-256(SHA-256(mpc_tag) || SHA-256(mpc_tag) || mpc::Root )` - -Where: - -* `mpc::Root` is the root of the MPC tree whose construction is explained in the following paragraphs. -* `mpc_tag = urn:ubideco:mpc:commitment#2024-01-31` follows[ RGB tagging conventions](https://github.com/RGB-WG/rgb-core/blob/vesper/doc/Commitments.md). - -## MPC Tree Construction - -In order to construct the MPC tree we must **deterministically find a unique leaf position for each contract**, thus: - -By setting `C` the number of contracts and `i = {0,1,..,C-1}` and by having a `ContractId(i) = c_i` to be included in the MPC, we can construct a tree with `w` leaves with `w > C` (corresponding to a depth `d` such that `2^d = w`), so that each contract identifier `c_i` representing a different contract is placed in a unique position `pos(c_i)` determined as a modulus operation detailed below. - -In essence, the construction of a suitable tree of width `w` that hosts each contract `c_i` in a unique position represents a kind of mining process. The greater the number of contract `C`, the greater should be the number of leaves `w`. Assuming a random distribution of `pos(c_i)`, as per [Birthday Paradox](https://en.wikipedia.org/wiki/Birthday\_problem), we have \~50% probability of a collision occurring in a tree with $$\mathtt{w \sim C^2}$$. - -In order to avoid too large MPC trees and assuming that the occurrence of collisions is a random process, an additional optimization has been introduced. - -The actual formula for determining the **leaf position of the contract** is: - -`pos(c_i) = c_i + cofactor mod w` pred - -Where `cofactor` is a random number of 16 bytes that can be chosen as a "nonce" to obtain distinct values of `pos(c_i)` with `w` fixed. The tree construction process starts from the smallest tree such that `w > C`, then tries a certain number of `cofactor` attempts. If none of them can produce `C` distinct positions, `w` is increased and a new series of `cofactor` trials is attempted. - -### **Contract Leaves (Inhabited)** - -Once `C` distinct positions `pos(c_i)` with `i = 0,...,C-1` are found, the corresponding leaves are populated through a tagged hash constructed in the following way: - -`tH_MPC_LEAF(c_i) = SHA-256(SHA-256(merkle_tag) || SHA-256(merkle_tag) || b || d || w || 0x10 || c_i || BundleId(c_i))` - -Where: - -* `merkle_tag = urn:ubideco:merkle:node#2024-01-31` is chosen according to [RGB conventions on Merkle Tree tagging commitments](https://github.com/RGB-WG/rgb-core/blob/vesper/doc/Commitments.md#merklization-procedure). -* `b = 1` refers to the branching of the leaf which refers to a single leaf node. -* `d` is the depth of the MPC tree at the base layer. -* `w` is the width of the MPC tree. -* `0x10` is the integer identifier of contract leaves. -* `c_i` is the 32-byte contract\_id which is derived from the hash of the [Genesis](../rgb-state-and-operations/state-transitions.md#genesis) of the contract itself. -* `BundleId(c_i)` is the 32-byte hash that is calculated from the data of the [Transition Bundle](../rgb-state-and-operations/state-transitions.md#transition-bundle) which groups all the [State Transitions](../annexes/glossary.md#state-transition) of the contract `c_i`. - -### **Entropy leaves (Uninhabited)** - -For the remaining `w - C` uninhabited leaves, a dummy value must be committed. To do that, each leaf in position `j != pos(c_i)` is populated in the following way: - -`tH_MPC_LEAF(j) = SHA-256(SHA-256(merkle_tag) || SHA-256(merkle_tag) || b || d || w || 0x11 || entropy || j )` - -Where: - -* `merkle_tag = urn:ubideco:merkle:node#2024-01-31` is chosen according to [RGB conventions on Merkle Tree tagging commitments](https://github.com/RGB-WG/rgb-core/blob/vesper/doc/Commitments.md#merklization-procedure). -* `b = 1` refers to the branching of the leaf which refers to a single leaf node. -* `d` is the depth of the MPC tree at the base layer. -* `w` is the width of the MPC tree. -* `0x11` is the integer identifier of entropy leaves. -* `entropy` is a 64-byte random value chosen by the user constructing the tree. - -### MPC nodes - -After generating the base of the MPC tree having `w` leaves, merkelization is performed following the rule of `commit_verify` crate detailed [here](https://github.com/RGB-WG/rgb-core/blob/vesper/doc/Commitments.md#merklization-procedure). - -The following diagram shows the construction of an example MPC tree where: - -* `C = 3` number of contracts to place. -* As an example: `pos(c_0) = 7, pos(c_1) = 4, pos(c_2) = 2`. -* `BUNDLE_i = BundleId(c_i)`. -* `tH_MPC_BRANCH(tH1 || tH2) = SHA-256(SHA-256(merkle_tag) || SHA-256(merkle_tag) || b || d || w || tH1 || tH2)`. -* `merkle_tag = urn:ubideco:merkle:node#2024-01-31` is chosen according to [RGB conventions on Merkle Tree tagging commitments](https://github.com/RGB-WG/rgb-core/blob/vesper/doc/Commitments.md#merklization-procedure). -* `b` is the branching of the tree merkelization scheme. In this case it is `b = 2` meaning that the merkelization happens with 2 input nodes: `tH1` and `tH2`, both having a 32-byte length. -* `d` is the tree depth which is updated at each level of the tree encoded a an 8-bit Little Endian unsigned integer. The depth at the base of the MPC tree in the example is `d = 3` -* `w` is a 256-bit Little Endian unsigned integer representing the width of the tree which remains fixed in each merkelization. In the example we have: `w=8`. - -{% code fullWidth="true" %} -``` - +--------------------------+ - mpc:Root | th_MPC(tHABCD || tHEFGH) | + mpc:Root | th_MPC(tHABCD || tHEFGH) | +-----------^---------^----+ | | +------------------------------------------------+ +--------------------------------------------+ @@ -139,13 +52,12 @@ From a verifier's perspective, in order to prove the presence of client-side val +-------+--------+ +---------+------+ | tH_MPC_LEAF(C) | | tH_MPC_LEAF(D) | +-------------^--+ +-------------^--+ - | | - +-------------------------+ +------+----+---------+ - | 0x10 || c_3 || BUNDLE_2 | | 0x11 | entropy || 3 | - +-------------------------+ +------+--------------+ + | + +-------------------------+ + | 0x10 || c_2 || BUNDLE_2 | + +-------------------------+ ``` {% endcode %} -So the Merkle Proof provided to verify the existence and uniqueness of contract commitment in the tree is: `0x11 | entropy || 3`, `tH_MPC_BRANCH(tHA || tHB)` and `tH_MPC_BRANCH(tHEF || tHGH)`. - +So the Merkle Proof provided to verify the existence and uniqueness of contract commitment in the tree is: `tH_MPC_LEAF(D)`, `tH_MPC_BRANCH(tHA || tHB)` and `tH_MPC_BRANCH(tHEF || tHGH)`. These are enough to recompute the tree root and, together with `pos(c_2)` and `cofacor`, reproduce the MPC commitment to be compared with the one included in the anchor. ***