Skip to content

Commit 3d596dc

Browse files
committed
add commitment annex and adjust links to it
1 parent 7feec49 commit 3d596dc

10 files changed

Lines changed: 271 additions & 20 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ For general information and education visit [rgb.info](https://rgb.info).
5252
* [Glossary](annexes/glossary.md)
5353
* [Contract Transfers](annexes/contract-transfers.md)
5454
* [Invoices](annexes/invoices.md)
55+
* [Commitments](annexes/commitments.md)
5556
* [RGB Library Map](annexes/rgb-library-map.md)
5657
* [Bitcoin Single-use Seals](annexes/single-use-seals-bitcoin.md)
5758

‎SUMMARY.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@
3939
* [Glossary](annexes/glossary.md)
4040
* [Contract Transfers](annexes/contract-transfers.md)
4141
* [Invoices](annexes/invoices.md)
42+
* [Commitments](annexes/commitments.md)
4243
* [RGB Library Map](annexes/rgb-library-map.md)
4344
* [Bitcoin Single-use Seals](annexes/single-use-seals-bitcoin.md)

‎annexes/commitments.md‎

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# RGB consensus commitments
2+
3+
RGB commits to client-side validated data using dedicated serialization
4+
mechanism, implemented via `CommitEncode` trait. Depending on the specific data,
5+
the mechanism can be partially or completely different from strict
6+
serialization, used for data storage. For instance, all data which may be
7+
confidential must be concealed, such that parties having no access to the
8+
original non-confidential values are still able to generate the same
9+
deterministic commitment value and verify single-use seals.
10+
11+
Any final consensus commitment is a SHA256 tagged hash. The tagging is performed
12+
according to BIP-340, where a commitment-specific fixed ASCII string value is
13+
first hashed with a single SHA256 hash, and the resulting 32 bytes are fed into
14+
a new SHA256 hasher twice before any actual data.
15+
16+
17+
## Generating commitment id
18+
19+
The commitment mechanism uses traits from [`commit_verify`] module in
20+
`rgb-consensus`, specifically its `id.rs`and `merkle.rs` submodules.
21+
22+
### `CommitEncode` trait
23+
24+
It is the main trait which must be implemented for each type requiring a
25+
dedicated commitment id.
26+
27+
The trait requires to define:
28+
- `CommitmentId` specifies a commitment id type, i.e. a type wrapping 32-byte
29+
tagged SHA256 hash, implementing `CommitmentId` trait (see details below).
30+
For instance `Operation` defines `OpId` as its commitment type.
31+
- `commit_encode` specifies an encoding for the bytestream that will be
32+
the input of the tagged hasher. Typical strategies are:
33+
* strict: the data is strict-serialized
34+
* conceal: the data is concealed and then strict-serialized
35+
* merkle: the data is organized in a merkle tree structure to obtain the merkle root
36+
37+
NB: It should never be necessary to call methods of `CommitEncode` trait directly,
38+
since `CommitId` trait automatically extends it with user-facing methods.
39+
40+
### `CommitmentId` trait
41+
42+
Each consensus commitment must have a dedicated Rust type, which wraps over
43+
inner `Bytes32` - a 32-byte resulting tagged hash value. The type is marked as
44+
a consensus commitment by implementing `CommitmentId` trait for it, which
45+
requires to provide a tag string value for the tagged hash.
46+
47+
The hash tags are defined using URN strings in form of
48+
`urn:<org>:<protocol>:<data>#<date>`, where `<org>` stands for the organization,
49+
`<protocol>` is the name of the protocol, `<data>` is the data type name
50+
producing the commitment, and `<date>` is a `YYYY-MM-DD` string for the latest
51+
revision of the commitment layout.
52+
53+
Any type implementing `CommitmentId` must also implement `From<Sha256>`, which allows for
54+
automated construction of commitments from the hasher.
55+
56+
### `CommitId` trait
57+
58+
This trait is automatically implemented for all types that implement `CommitEncode` and
59+
it can't be implemented manually.
60+
It exposes a `CommitId::commit_id()` method to produce the final commitment (i.e. the result
61+
of the hashing procedure, wrapped in the the corresponding type implementing `CommitmentId`).
62+
63+
The trait also provides `CommitId::commitment_layout()` method, which can be
64+
used for automatically generating the documentation on the commitment workflow.
65+
66+
## Merklization procedure
67+
68+
Merlization is the procedure of computing the root of a
69+
[Merkle Tree](glossary.md#merkle-tree) to be used as a commitment.
70+
It uses traits and data types from `merkle.rs` module of `commit_verify` crate and it
71+
commits to the tree parameters, such as number of elements, depth of the tree and
72+
depth of each node.
73+
74+
The main data type, related to the merklization, is `MerkleHash`: it is a tagged
75+
hash (using `urn:ubideco:merkle:node#2024-01-31` tag) representing node at any
76+
position of the tree: leaves, branch nodes and merkle tree root. `MerkleHash`
77+
can be produced in the following ways:
78+
- as a result of merklziation procedure, when it represents Merkle tree root;
79+
- as a root of empty Merkle tree (i.e. collection having 0 elements), by calling
80+
`MerkleHash::void(0u8, 0u32)`,
81+
- as a Merkle leaf, by implementing `CommitEncode` on some type and setting
82+
commitment id to be `MerkleHash`.
83+
84+
In all of the above cases the hash commits to the tree parameters, which makes
85+
it safe to use the same type for leaves, branches and root nodes. Specifically,
86+
it uses an intermediate structure `MerkleNode`, which is filled with information
87+
on:
88+
- type of node branching (no branches, one branch or two branches),
89+
- depth of the node, as 8-bit unsigned integer,
90+
- width of the tree at its base, as a 256-bit LE unsigned integer,
91+
- node hashes of the branches; if one or both branches are absent, they are
92+
replaced with 32 bytes of repeated 0xFF value.
93+
94+
A collection in form of a list (Rust `Vec`) or an ordered set of unique
95+
non-repeating items (Rust `BTreeSet`), if wrapped into a confinement (i.e. has
96+
type-defined bounds on the minimum or maximum number of items) can be
97+
automatically merklized when passed as an argument to `MerkleHash::merklize()`
98+
call. The API puts the following requirements on the collection: either
99+
- maximum number of elements must be either 0xFF or 0xFFFF **and** each
100+
collection element must implement `CommitEncode` trait with target id set to
101+
`MerkleHash`,
102+
- or there is a manual implementation of `MerkleLeaves` trait.
103+
104+
```mermaid
105+
flowchart BT
106+
subgraph Merklization
107+
direction LR
108+
subgraph MerkleNode
109+
branching
110+
depth
111+
width
112+
node1
113+
node2
114+
end
115+
MerkleNode -- encode to\ntagged hasher --> MerkleHash
116+
end
117+
MerkleHash ---> MerkleNode
118+
MerkleHash === Root
119+
Leaf -- commit_id ----> MerkleHash
120+
```
121+
122+
123+
## Specific RGB consensus commitments
124+
125+
Currently, RGB has three consensus commitments: schema, operation and bundle.
126+
Operation commitment for genesis has a second representation, named contract id,
127+
which uses reversed-byte encoding and a special string serialization, but is
128+
generated with the same procedure as the operation commitment.
129+
130+
The commitment ids can be generated with either type-specific methods
131+
(`schema_id()` for schema, `bundle_id()` for state transition bundle and
132+
`id()` for any operation) or the `CommitId::commit_id()` method, which must provide
133+
the same result.
134+
135+
Here are more details on each commitment type:
136+
137+
| Commitment ID | Produced by | Procedure | Tag URN suffix(1) |
138+
|----------------------|--------------------------------------|------------------------------------------------------------------------------------------------|-------------------------------|
139+
| `SchemaID` | `Schema` | strict serialization | `rgb:schema#2024-02-03` |
140+
| `OpId`, `ContractId` | `Transition`, `Genesis` | nested commitments with concealing, merklization etc via intermediate `OpCommitment` structure | `rgb:operation#2024-02-03` |
141+
| `BundleId` | `TransitionBundle` | conceal and partial strict serialization | `rgb:bundle#2024-02-03` |
142+
| `SecretSeal` | `BlindSeal` | conceal and strict serialization | `seals:secret#2024-02-03` |
143+
144+
(1): "URN suffix" is the part that follows the "urn:lnp-bp:" prefix.
145+
146+
Additionally to these types there are three other commitment ids used internally
147+
by merklization and strict encoding procedures:
148+
149+
| Commitment ID | Tag URN suffix |
150+
|-------------------|--------------------------------------------------|
151+
| `MerkleHash` | `urn:ubideco:merkle:node#2024-01-31` |
152+
| `StrictHash` | `urn:ubideco:strict-types:value-hash#2024-02-10` |
153+
| `mpc::Commitment` | `urn:ubideco:mpc:commitment#2024-01-31` |
154+
155+
`StrictHash` can be produced as a result of serialization of any
156+
strict-encodable data; for instance, it is used in compactifying collections
157+
into a single hash field in the process of computing operation ids (described
158+
below).
159+
160+
Finally, in `commit_verify::mpc`, multi-protocol commitment
161+
implementation, we have a type named `mpc::Commitment`, which is a commitment
162+
to a root of the MPC tree (i.e. the tree's root `MerkleHash` is tag-hashed once
163+
again to produce the final commitment value).
164+
165+
166+
### Schema ID
167+
168+
Schema id, represented by `SchemaId` data type, is produced from `Schema` type
169+
via strict serialization of all the schema data. No conceal or merklization
170+
procedures are applied; i.e. the commitment id is the same as hashing serialized
171+
schema with the given tag.
172+
173+
### Operation ID and Contract ID
174+
175+
Operation id is represented by a `OpId` type and produced for `Genesis` and
176+
`Transition` types through a dedicated `OpCommitment` structure that is then
177+
strict-serialized and hashed.
178+
179+
`OpCommitment` consists of a set of commitments to blocks of the operation data, each
180+
generated with a specific procedure.
181+
182+
For instance, global state, inputs and assignments are merklized, such that compact
183+
proofs of inclusion can be produced and used in smart contracts.
184+
Additionally to that, assignments are concealed before the merklization, such that an
185+
entity that does not know the blinding factor can still reproduce the same operation ID.
186+
Other collections such as metadata are simply strict-serialized, producing a `StrictHash` as sub-commitment.
187+
188+
```mermaid
189+
flowchart LR
190+
subgraph "Common data"
191+
Ffv --> OpCommitment
192+
TypeCommitment --> OpCommitment
193+
Metadata -- StrictHash --> OpCommitment
194+
Globals -- Merklize --> OpCommitment
195+
Inputs -- Merklize --> OpCommitment
196+
Assignments -- "Conceal\n + Merklize" --> OpCommitment
197+
end
198+
199+
subgraph "Genesis"
200+
schemaId --> BaseCommitment
201+
chainNet --> BaseCommitment
202+
end
203+
204+
subgraph "Transition"
205+
tcid[contractId] --> TypeCommitment
206+
transitionType --> TypeCommitment
207+
end
208+
209+
BaseCommitment --> TypeCommitment
210+
211+
OpCommitment -- hash --> OpId
212+
OpId -- "reverse bytes\n(genesis only)" --> ContractId
213+
```
214+
215+
Additionally to `OpId`, genesis produces `ContractId`, which is made out of the
216+
genesis `OpId` by reversing byte order and using Base58 encoding.
217+
218+
### Bundle ID
219+
220+
Bundle id is a unique identifier of state transition bundle, directly used in
221+
constructing multi-protocol commitment tree. Bundle id commits to the mapping between
222+
assignments spent within the bundle and the id of the operation spending them.
223+
`TransitionBundle::known_transitions` may contain a subset of the transitions in the
224+
bundle and thus it desn't contribute to the `BundleId`.
225+
226+
The procedure is explained in detail in a [dedicated chapter](../rgb-state-and-operations/state-transitions.md#transition-bundle)
227+
228+
```mermaid
229+
flowchart TD
230+
subgraph Discarded
231+
id((" "))
232+
end
233+
234+
subgraph TransitionBundle
235+
inputMap
236+
knownTransitions
237+
end
238+
239+
inputMap -- encode \n hash --> BundleId
240+
knownTransitions --x Discarded
241+
```

‎annexes/contract-transfers.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Contract Transfers
22

3-
In this section we will be guided through a step-by-step RGB Contract Transfer operation, again with the cooperation of our cryptographic couple: Alice and Bob. We will also provide some coding sections of both our characters, which use the `rgb` Command Line Interface Tool which can be installed from the dedicated [RGB library](rgb-library-map.md#rgb-cli).
3+
In this section we will be guided through a step-by-step RGB Contract Transfer operation, again with the cooperation of our cryptographic couple: Alice and Bob. We will also provide some coding sections of both our characters, which use the `rgb` Command Line Interface Tool which can be installed from the dedicated [RGB library](rgb-library-map.md#rgb-api-and-cli).
44

55
Let's start with Bob, who owns a Bitcoin wallet but has not yet started using RGB technology.
66

7-
**1)** To begin operating with RGB protocol, **Bob must install an RGB wallet**. This startup process involves installing the RGB wallet software, which usually, by default, contains no contracts. The RGB wallet software, in addition, requires the ability to interact with Bitcoin UTXO through a Bitcoin wallet and a Bitcoin Blockchain node tool (a full node or an [Electrum Server](https://thebitcoinmanual.com/articles/btc-electrum-server/)). These tools are a mandatory requirement because, as we learned [previously](../rgb-state-and-operations/state-transitions.md#state-transitions-and-their-mechanics), [owned states ](glossary.md#owned-state)are defined over Bitcoin UTXO and represent a necessary item for [state transitions](glossary.md#state-transition) implementing transfers of contract in RGB.
7+
**1)** To begin operating with RGB protocol, **Bob must install an RGB wallet**. This startup process involves installing the RGB wallet software, which usually, by default, contains no contracts. The RGB wallet software, in addition, requires the ability to interact with Bitcoin UTXO through a Bitcoin wallet and a Bitcoin Blockchain node tool (a full node or an [Electrum Server](https://thebitcoinmanual.com/articles/btc-electrum-server/)). These tools are a mandatory requirement because, as we learned [previously](../rgb-state-and-operations/state-transitions.md#state-transitions-and-their-mechanics), [owned states](glossary.md#owned-state) are defined over Bitcoin UTXO and represent a necessary item for [state transitions](glossary.md#state-transition) implementing transfers of contract in RGB.
88

99
**2)** Then, Bob has the task of acquiring the **necessary information about the contracts.** These data, in the RGB ecosystem, can be sourced through various channels, such as specific websites, e-mails, or Telegram messages, etc, following the [contract issuer](glossary.md#contract-participant)'s choice. These data are distributed using a [contract consignment ](glossary.md#consignment)which is a data package containing [Genesis](glossary.md#genesis) and [Schema](glossary.md#schema).
1010

‎annexes/glossary.md‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,19 @@ A decentralized network of bidirectional payment (state) channels constituted by
128128

129129
[Link](https://lightning.network/)
130130

131+
### Merkle Tree
132+
133+
A cryptographic data structure that allows small (logarithmic) inclusion proofs. It's
134+
composed of a binary tree in which leaves are the set elements, each intermediate node
135+
contains the hash of its children and the root commits to the whole set of elements.
136+
To prove a leaf is part of the tree it's enough to provide sibling hashes throughout the
137+
path from the leaf to the root, whose size grows logarithmically with the number of leaves.
138+
139+
[More details](https://developer.bitcoin.org/reference/block_chain.html#merkle-trees)
140+
131141
### Multi Protocol Commitment - MPC
132142

133-
The Merkle Tree structure used in RGB to include in a single Bitcoin Blockchain commitment the multiple [Transition Bundles](glossary.md#transition-bundle) of different contracts.
143+
The [Merkle Tree](glossary.md#merkle-tree) structure used in RGB to include in a single Bitcoin Blockchain commitment the multiple [Transition Bundles](glossary.md#transition-bundle) of different contracts.
134144

135145
[Link](commitment-layer/multi-protocol-commitments-mpc.md)
136146

‎commitment-layer/multi-protocol-commitments-mpc.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ The commitment of the MPC tree - which goes either into [Opret](deterministic-bi
1717

1818
Where:
1919

20-
* `mpc_tag = urn:ubideco:mpc:commitment#2024-01-31` follows[ RGB tagging conventions](https://github.com/RGB-WG/rgb-core/blob/master/doc/Commitments.md).
20+
* `mpc_tag = urn:ubideco:mpc:commitment#2024-01-31` follows [RGB tagging conventions](../annexes/commitments.md#merklization-procedure).
2121
* `depth` is the depth of the tree as a single byte
2222
* `cofactor` is the value used to obtain distinct positions for the contracts in the tree as a 16-bit Little Endian unsigned integer (see [MPC Tree Construction](#mpc-tree-construction))
2323
* `mpc::Root` is the root of the MPC tree whose construction is explained in the following paragraphs.
@@ -51,7 +51,7 @@ Once `C` distinct positions `pos(c_i)` with `i = 0,...,C-1` are found, the corre
5151

5252
Where:
5353

54-
* `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/master/doc/Commitments.md#merklization-procedure).
54+
* `merkle_tag = urn:ubideco:merkle:node#2024-01-31` is chosen according to [RGB conventions on Merkle Tree tagging commitments](../annexes/commitments.md#merklization-procedure).
5555
* `0x10` is the integer identifier of contract leaves.
5656
* `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.
5757
* `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`.
@@ -64,21 +64,21 @@ For the remaining `w - C` uninhabited leaves, a dummy value must be committed. T
6464

6565
Where:
6666

67-
* `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/master/doc/Commitments.md#merklization-procedure).
67+
* `merkle_tag = urn:ubideco:merkle:node#2024-01-31` is chosen according to [RGB conventions on Merkle Tree tagging commitments](../annexes/commitments.md#merklization-procedure).
6868
* `0x11` is the integer identifier of entropy leaves.
6969
* `entropy` is a 64-byte random value chosen by the user constructing the tree.
7070
* `j` is the position of the current leaf as a 32-bit Little Endian unsigned integer.
7171

7272
### MPC nodes
7373

74-
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).
74+
After generating the base of the MPC tree having `w` leaves, merkelization is performed following the rule of `commit_verify` crate detailed [here](../annexes/commitments.md#merklization-procedure).
7575

7676
The hash for non-leaf nodes in the tree is computed as:
7777

7878
`tH_MPC_BRANCH(tH1 || tH2) = SHA-256(SHA-256(merkle_tag) || SHA-256(merkle_tag) || b || d || w || tH1 || tH2)`
7979

8080
Where:
81-
* `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/master/doc/Commitments.md#merklization-procedure).
81+
* `merkle_tag = urn:ubideco:merkle:node#2024-01-31` is chosen according to [RGB conventions on Merkle Tree tagging commitments](../annexes/commitments.md#merklization-procedure).
8282
* `b` is the branching of the tree merkelization scheme, i.e. the number of children the current node has, encoded as a 8-bit unsigned integer. If the tree is complete, this is always `0x02`.
8383
* `d` is the node depth within the tree (i.e. the length of the path to the root), encoded as an 8-bit unsigned integer.
8484
* `w` is the tree width, encoded as a 256-bit Little Endian unsigned integer.

0 commit comments

Comments
 (0)