RGB

Francisco CalderónFrancisco Calderón
Sep 1, 2024
Sep 1, 2024

introduction

On January 3, 2009 Satoshi Nakamoto launched the first Bitcoin node, from that moment new nodes joined and Bitcoin begin to behave as if it were a new form of life, a form of life that has not stopped evolving, little by little it has become the safest network in the world as a result of its unique design, very well thought out by Satoshi since, through economic incentives, it attracts users commonly called miners to invest in energy and computing power which contributes to network security.
As Bitcoin continues its growth and adoption it faces scalability issues, the Bitcoin network allows a new block with transactions to be mined in an approximate time of 10 minutes, assuming we have 144 blocks in a day with maximum values ​​of 2700 transactions per block, Bitcoin would have allowed only 4.5 transactions per second, Satoshi was aware of this limitation, we can see it in an email1 sent to Mike Hearn in March 2011 where he explains how what we know today as a payment channel works. micropayments quickly and safely without waiting for confirmations. This is where off-chain protocols come in.
According to Christian Decker2 Off-chain protocols are usually systems in which users use data from a blockchain and manage it without touching the blockchain itself until the last minute. Based on this concept, the Lightning Network was born, a network that uses off-chain protocols to allow Bitcoin payments to be made almost instantaneously and since not all these operations are written on the block chain, it allows thousands of transactions per second and scale Bitcoin.
Research and development in the area of ​​off-chain protocols on Bitcoin has opened a pandora's box, today we know that we can achieve much more than value transfer in a decentralized way, the non-profit LNP/BP Standards Association focuses on development of layer 2 and 3 protocols on Bitcoin and the Lightning Network, among these projects RGB stands out.

What is RGB?

RGB has appeared from the research by Peter Todd3 on single-use-seals and client-side-validation, which was coined in 2016-2019 by Giacomo Zucco and community into a better asset protocol for Bitcoin and Lightning network. Further evolution of these ideas led to a development of RGB into a fully-fledged smart contract system by Maxim Orlovsky, who is leading its implementation since 2019 with community participation.
We can define RGB as a set of open source protocols that allows us to execute complex smart contracts in a scalable and confidential way. It is not a particular network (like Bitcoin or Lightning); each smart contract is just a set of contract participants which can interact using different communication channels (defaulting to Lightning network). RGB uses Bitcoin blockchain as a layer of state commitment and maintains the code of the smart contract and the data off-chain, which makes it scalable, leveraging Bitcoin transactions (and Script) as a ownership control system for smart contracts; while the evolution of the smart contract is defined by an off-chain scheme, finally it is important to note that everything is validated on the client side.
In simple terms, RGB is a system that allows the user to audit a smart contract, execute it and verify it individually at any time without having an additional cost since for this it does not use a blockchain as "traditional" systems do, complex smart contracts systems were pioneered by Ethereum but due to it requires the user to spend significant amounts of gas for each operation, they never achieved the scalability they promised by consequence it never was an option to bank the users excluded from the current financial system.
Currently, the blockchain industry promotes that both the code of smart contracts and the data must be stored in the blockchain and executed by each node of the network, regardless of the excessive increase in size or the misuse of computational resources. The scheme proposed by RGB is much more intelligent and efficient since it cuts with the blockchain paradigm by having smart contracts and data separated from the blockchain and thus avoids the saturation of the network seen in other platforms, in turn it does not force each node to execute each contract but rather the parties involved which adds confidentiality to a level never seen before.

Smart contracts in RGB

In RGB smart contract developer defines a scheme specifying rules how the contract evolves over time. The scheme is the standard for the construction of smart contracts in RGB, and both an issuer when defining a contract for issuance and a wallet or exchange must adhere to a particular scheme against which they must validate the contract. Only if the validation is correct can each party accept requests and work with the asset.
A smart contract in RGB is a directed acyclic graph (DAG) of state changes, where only a portion of the graph is always known and there is no access to the rest. The RGB scheme is a core set of rules for the evolution of this graph the smart contract starts with. Each contract participant may add to those rules (if this is allowed by the schema) and the resulting graph is built from the iterative application of those rules.

Fungible assets

The fungible assets in RGB follow the LNPBP RGB-20 specification4, when an RGB-20 is defined, the asset data known as "genesis data'' is distributed through the Lightning network, which contains what is required to use the asset. The most basic form of assets do not allow secondary issuance, token burning, renomination or replacement.
Sometimes the issuer will need to issue more tokens in the future, i.e. stablecoins such as USDT, which keeps the value of each token tied to the value of an inflationary currency such as the USD. To achieve this more complex RGB-20 schemata exists, and in addition to the genesis data they require the issuer to produce consignments, which will be also circulating in the lightning network; with this information we can know the total circulating supply of the asset. The same applies for burning assets, or changing its name.
The information related to the asset can be public or private: if the issuer requires confidentiality, he/she can choose not to share information about the token and perform operations in absolute privacy, but we also have the opposite case in which the issuer and the holders need the whole process to be transparent. This is achieved by sharing the token data.

RGB-20 procedures

The burning procedure disables tokens, burned tokens can’t be used anymore.
Replacement procedure occurs when tokens are burned and a new amount of the same token is created. This helps reduce the size of the asset's historical data, which is important to maintain asset speed.
To support the use case where it is possible to burn assets without having to replace them, a sub-scheme of RGB-20 is used that only allows burning assets.

Non fungible assets

The non-fungible assets in RGB follow the LNPBP RGB-21 specification5, when we work with NFTs we also have a main scheme and a sub-scheme. These schemes have an engraving procedure, which allows us to attach custom data by part of the token owner, the most common example we see in NFTs today is digital art linked to the token. The token issuer can prohibit this data engraving by using the RGB-21 sub-scheme. Unlike other NFT blockchain systems, RGB allows to distribute large-size media token data in a complete decentralized and censorship-resistant manner, utilizing extension to the Lightning P2P network called Bifrost, which is also used for building many other forms of RGB-specific smart contract functionalities.
Additionally to fungible assets and NFTs, RGB and Bifrost can be used to produce other forms of smart contracts, including DEXes, liquidity pools, algorithmic stable coins etc, which we will cover in future articles.

NFT from RGB vs NFT from other platforms

  • No need for expensive blockchain storage
  • Not need for IPFS, a Lightning network extension (called Bifrost) is used instead (and it’s fully end-to-end encrypted)
  • No need for a special data management solution – again, Bifrost takes that role
  • No need to trust websites to maintain data for NFT tokens or about issues assets / contract ABIs
  • Built-in DRM encryption and ownership management
  • Infrastructure for backups using the Lightning Network (Bifrost)
  • Ways to monetize content (not only selling the NFT itself, but access to the content, several times)

Conclusions

Since the launch of Bitcoin, almost 13 years ago there has been a lot of research and experimentation in the area, both the successes and the mistakes have allowed us to understand a little more how decentralized systems behave in practice, what makes them really decentralized and what actions tend to lead them to centralization, all this has led us to conclude that real decentralization is a rare and difficult phenomenon to achieve, real decentralization has only been achieved by Bitcoin and it is for this reason that we focus our efforts to build on top of it.
RGB has its own rabbit hole within the Bitcoin rabbit hole, while I am falling down through them I will post what I have learned, in the next article we will have an introduction to the LNP and RGB nodes and how to use them.

RGB-node Tutorial

Introduction

In this tutorial we explain how to use RGB-node to create a fungible token and how to transfer it, this document is based on RGB-node demo and differs in that this tutorial uses real testnet data and for that, we must build our own Partially Signed Bitcoin Transaction, psbt from now on.

Requirements

The use of a Linux distribution is recommended, this tutorial was written using Pop!OS, which is based on Ubuntu and you will need:
  • cargo
  • Bitcoin core
  • git
Note: This tutorial shows the execution of commands in a Linux terminal, to differentiate what the user writes and the response he gets in the terminal, we include the $ symbolizing the bash prompt.
You will need to install some dependencies:
$ sudo apt install -y build-essential pkg-config libzmq3-dev libssl-dev libpq-dev libsqlite3-dev cmake
Build & Run
RGB-node is work in progress (WIP), that is why we must locate ourselves in a specific commit (3f3c520c19d84c66d430e76f0fc68c5a66d79c84) to be able to compile and use it correctly, for this we execute the following commands.
$ git clone https://github.com/rgb-org/rgb-node.git $ cd rgb-node $ git checkout 3f3c520c19d84c66d430e76f0fc68c5a66d79c84
Now we compile it, don't forget to use --locked flag because there is a breaking change introduced on a version of clap.
$ cargo install --path . --all-features --locked .... .... Finished release [optimized] target(s) in 2m 14s Installing /home/user/.cargo/bin/fungibled Installing /home/user/.cargo/bin/rgb-cli Installing /home/user/.cargo/bin/rgbd Installing /home/user/.cargo/bin/stashd Installed package `rgb_node v0.4.2 (/home/user/dev/rgb-node)` (executables `fungibled`, `rgb-cli`, `rgbd`, `stashd`)
As the rust compiler tells us, the binaries were copied to the $HOME/.cargo/bin directory, if your compiler copied them to a different place you must make sure that directory must be included in $PATH.
Among the installed binaries we can see three daemons or services (the files that end in d) and a cli (command line interface), the cli allows us to interact with the main rgbd daemon. As in this tutorial we are going to run two nodes, we will also need two clients, each one must connect to its own node, for that we create two aliases.
alias rgb0-cli="$HOME/.cargo/bin/rgb-cli -d $HOME/rgbdata/data0 -n testnet" alias rgb1-cli="$HOME/.cargo/bin/rgb-cli -d $HOME/rgbdata/data1 -n testnet"
We can just run the aliases or add them to the end of the $HOME/.bashrc file and run source $HOME/.bashrc. Premise
RGB-node does not handle any kind of wallet-related functionality, it just performs RGB-specific tasks on the data that will be provided by an external wallet like bitcoin core. In particular, to demonstrate a basic workflow with issuance and transfer, we will need:
  • An issuance_utxo to which rgb-node-0 will bind the newly issued asset
  • A receive_utxo where rgb-node-1 receives the asset
  • A change_utxo where rgb-node-0 receives the asset change
  • A partially signed bitcoin transaction (tx.psbt), whose output public key will be tweaked to include a commitment to the transfer.
We will use the bitcoin core cli, we need to have the bitcoind daemon running on testnet, this will give us interoperability and at the end we will be able to send our own assets to other RGB user who followed this tutorial.
For the sake of simplicity we will add this alias at the end of our ~/.bashrc file.
alias bcli="bitcoin-cli -testnet"
Let's list our unspent output transactions and select two, one will be the issuance_utxo and the other one change_utxo, it doesn't matter which is which, the important thing is that the issuer has control of these two UTXO.
$ bcli listunspent [ { "txid": "4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893", "vout": 1, "address": "tb1qn4w9u5x0hxgm30hx6q2rhdwz58xr4ekqdq0vgm", "label": "", "scriptPubKey": "00149d5c5e50cfb991b8bee6d0143bb5c2a1cc3ae6c0", "amount": 0.01703963, "confirmations": 62432, "spendable": true, "solvable": true, "desc": "wpkh([ec924f82/0'/0'/5']031e0fc9a03e69326c3deeabfd749a7f7b094e3151ada90cd13019efac663c5663)#dj7rhpdt", "safe": true }, { "txid": "cd66d3b77dfc1c2ecf958847c16a8a1311bba84ee7bf9dd55592a7b97b13028f", "vout": 1, "address": "tb1qyd537gf0xmm9ehmhaf3nv0a230crg56mhp9ap3", "scriptPubKey": "001423691f212f36f65cdf77ea63363faa8bf034535b", "amount": 0.02877504, "confirmations": 189184, "spendable": true, "solvable": true, "desc": "wpkh([ec924f82/0'/1'/0']03ae333417e86840145e95ab2852c8f7ca8b8f82cd910883f7ce0c69649403cef2)#jlcj23vw", "safe": true } ]
Before go further we need to talk about outpoints, a single transaction can include multiple outputs, the outpoint includes both a 32-byte TXID and a 4-byte output index number (vout) to refer to specific output separated with a colon :. In our listunspent output we can found two UTXOs, on each we can see txid and vout, those are out issuance_utxo and change_utxo outpoints.
receive_utxo is an UTXO controlled by the receiver, in this case we will use e40d9037e31d3f440552b30af16e764cf25ffda3899b4851cc4e38fd64718b09:0 which is an outpoint from another wallet.
  • issuance_utxo: 4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893:1
  • change_utxo: cd66d3b77dfc1c2ecf958847c16a8a1311bba84ee7bf9dd55592a7b97b13028f:1
  • receive_utxo: e40d9037e31d3f440552b30af16e764cf25ffda3899b4851cc4e38fd64718b09:0
We are now going to create a partially signed transaction (tx.psbt) whose output will be tweaked to include a commit to transfer, remember to replace the txid and vout with your own, the destination address doesn't really matters, it can be yours or it can be from another person, it doesn't matter where those sats goes, what it matters is that we use issuance_utxo.
$ bcli walletcreatefundedpsbt "[{/"txid/":/"4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893/",/"vout/":1}]" "[{/"tb1q9crtjp0y6rt00c4fcrmuamrylzkcalcxls80j9/":/"0.00050000/"}]" { "psbt": "cHNidP8BAHECAAAAAZM4E58uD9auiZ7esJkFbmD5p/7PcgBTn5UwiQ0hhRdMAQAAAAD/////ArM7GQAAAAAAFgAU4xQr/g1lgG2P9+gZudpFD8mOGGRQwwAAAAAAABYAFC4GuQXk0Nb34qnA987sZPitjv8GAAAAAAABAHECAAAAAYiK0TdTiaEs4oDovRokqspfLZr5EHYH8Pnj/Tv5GFB5AQAAAAD+////Av8Bh80AAAAAFgAUsLjOd30aRkUna41LAT5c3CnAz5obABoAAAAAABYAFJ1cXlDPuZG4vubQFDu1wqHMOubAyw8gAAEBHxsAGgAAAAAAFgAUnVxeUM+5kbi+5tAUO7XCocw65sAiBgMeD8mgPmkybD3uq/10mn97CU4xUa2pDNEwGe+sZjxWYxDskk+CAAAAgAAAAIAFAACAACICA2J21wOqW6bj7/ePTVI7QGvU6e4Sk8DhN5pmd9hrwSd7EOyST4IAAACAAQAAgAcAAIAAAA==", "fee": 0.00000280, "changepos": 0 }
The output gave us a psbt in base64 encoding which we will use to create tx.psbt.
$ echo "cHNidP8BAHECAAAAAZM4E58uD9auiZ7esJkFbmD5p/7PcgBTn5UwiQ0hhRdMAQAAAAD/////ArM7GQAAAAAAFgAU4xQr/g1lgG2P9+gZudpFD8mOGGRQwwAAAAAAABYAFC4GuQXk0Nb34qnA987sZPitjv8GAAAAAAABAHECAAAAAYiK0TdTiaEs4oDovRokqspfLZr5EHYH8Pnj/Tv5GFB5AQAAAAD+////Av8Bh80AAAAAFgAUsLjOd30aRkUna41LAT5c3CnAz5obABoAAAAAABYAFJ1cXlDPuZG4vubQFDu1wqHMOubAyw8gAAEBHxsAGgAAAAAAFgAUnVxeUM+5kbi+5tAUO7XCocw65sAiBgMeD8mgPmkybD3uq/10mn97CU4xUa2pDNEwGe+sZjxWYxDskk+CAAAAgAAAAIAFAACAACICA2J21wOqW6bj7/ePTVI7QGvU6e4Sk8DhN5pmd9hrwSd7EOyST4IAAACAAQAAgAcAAIAAAA==" | base64 -d > tx.psbt
Let's create a new directory called rgbdata in which the data directory of each node are stored.
$ mkdir $HOME/rgbdata $ cd $HOME/rgbdata
Already located in $HOME/rgbdata we start each node in different terminals, where ~/.cargo/bin is the directory where cargo copied all binaries after rgb-node installation.
$ rgbd -vvvv -b ~/.cargo/bin -d ./data0 -n testnet $ rgbd -vvvv -b ~/.cargo/bin -d ./data1 -n testnet

Issuance

To issue an asset we run rgb0-cli with the fungible issue subcommands, then the arguments, the ticker USDT, the name "USD Tether" and in the allocation we will use the issuing amount and the issuance_utxo like we see below:
$ rgb0-cli fungible issue USDT "USD Tether" 1000@4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893:1
Asset successfully issued. Use this information for sharing: Asset information:
genesis: genesis1qyfe883hey6jrgj2xvk5g3dfmfqfzm7a4wez4pd2krf7ltsxffd6u6nrvjvvnc8vt9llmp7663pgututl9heuwaudet72ay9j6thc6cetuvhxvsqqya5xjt2w9y4u6sfkuszwwctnrpug5yjxnthmr3mydg05rdrpspcxysnqvvqpfvag2w8jxzzsz9pf8pjfwf0xvln5z7w93yjln3gcnyxsa04jsf2p8vu4sxgppfv0j9qerppqxhvztpqscnjsxvq5gdfy5v6j3wvpjxxqzcerxuglngnfvpxjkgqusct7cyx8zzezcfpqv3nxjxm2kjj4d0zu0ta6fjmpr8a0calk6h88h4ap5e4nucj0ch07aa73qsh3lj5sd89a32kwy0eq7tsa5zqqjpdqvqq5s46r0 id: rgb1tadqzve7vwfh39sl6gvqenp8wegsrzreekhhu0dhthx08ppzj9wq8p0je6 ticker: USDT name: USD Tether description: ~ knownCirculating: 1000 isIssuedKnown: ~ issueLimit: 0 chain: testnet decimalPrecision: 0 date: "2022-02-23T20:53:26" knownIssues: - id: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f amount: 1000 origin: ~ knownInflation: {} knownAllocations: - nodeId: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f index: 0 outpoint: "4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893:1" revealedAmount: value: 1000 blinding: "0000000000000000000000000000000000000000000000000000000000000001" genesis1qyfe883hey6jrgj2xvk5g3dfmfqfzm7a4wez4pd2krf7ltsxffd6u6nrvjvvnc8vt9llmp7663pgututl9heuwaudet72ay9j6thc6cetuvhxvsqqya5xjt2w9y4u6sfkuszwwctnrpug5yjxnthmr3mydg05rdrpspcxysnqvvqpfvag2w8jxzzsz9pf8pjfwf0xvln5z7w93yjln3gcnyxsa04jsf2p8vu4sxgppfv0j9qerppqxhvztpqscnjsxvq5gdfy5v6j3wvpjxxqzcerxuglngnfvpxjkgqusct7cyx8zzezcfpqv3nxjxm2kjj4d0zu0ta6fjmpr8a0calk6h88h4ap5e4nucj0ch07aa73qsh3lj5sd89a32kwy0eq7tsa5zqqjpdqvqq5s46r0
We get the assetId, we need it to transfer the asset.
$ rgb0-cli fungible list - name: USD Tether id: rgb1tadqzve7vwfh39sl6gvqenp8wegsrzreekhhu0dhthx08ppzj9wq8p0je6 ticker: USDT

Generate blinded UTXO

In order to receive the new USDT, rgb-node-1 needs to generate a blinded UTXO corresponding to receive_utxo to hold the asset.
$ rgb1-cli fungible blind e40d9037e31d3f440552b30af16e764cf25ffda3899b4851cc4e38fd64718b09:0 Blinded outpoint: utxob16az597vp5nkr66nfzsykf8ngdnvzep5050rm00l7vv8wm7vew4jqj7jhhf Outpoint blinding secret: 1679197189805229975
To be able to accept transfers related to this UTXO, we will need the original receive_utxo and the blinding_factor.

Transfer

To transfer some amount of the asset to rgb-node-1 we need to send it to the blinded UTXO, rgb-node-0 needs to create a consignment and a disclosure, and commit it into a bitcoin transaction. Then we will need a psbt which we will modify to include the commit. In addition, the -i and -a options allow us to provide an input outpoint that would be the origin of the asset and an allocation where we will receive the change, we must indicate it in the following way @<change_utxo>.
$ rgb0-cli fungible transfer utxob16az597vp5nkr66nfzsykf8ngdnvzep5050rm00l7vv8wm7vew4jqj7jhhf 100 rgb1tadqzve7vwfh39sl6gvqenp8wegsrzreekhhu0dhthx08ppzj9wq8p0je6 tx.psbt consignment.rgb disclosure.rgb witness.psbt -i 4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893:1 -a 900@cd66d3b77dfc1c2ecf958847c16a8a1311bba84ee7bf9dd55592a7b97b13028f:1 Transfer succeeded, consignments and disclosure are written to "consignment.rgb" and "disclosure.rgb", partially signed witness transaction to "witness.psbt" Consignment data to share:consignment1qxz4g7ec6da33llaxe97u9hx8p9wcgp2yv46ycudwy7ytjf4gdh88x6upcdmjfy3mp4y0n669j5ar5y6e04zfr7255kynff6eymx9tdfc7jux5jk6tgn4xm6lttlh3lh08070ltuh60l07mamlns2qyy984mg4m5dz0x6s5sy5edls2zjlmnvw708sh7fy2vuph745jcpgp92qrw27s73vm4ghrx57vammyf8wautwu5euujd8w3dupdtgp4px36gz8z0ywnuty45uqdwk672qqzjp3j77yl7urft6gewqksqgppczezn5c7gyux6gzgpye0wgyjp85ufdqlzy5cd8zwfg3q9550xq2hyf24qqz92wqskpgq8qsr8kp5p9dt49evmqlze9ylrx2sqpwpvpqp45lpvgjkgk542pks9850w5jquq3qqsj4xsqn9nu6w30lgpmrhdqs6jj0ez3myhj74kp223f0wg2y7vupczdq5pa23mzhzc6l647nl6ftrru0mjrh739yhgztsdhl2cdmhf0qm7du9n20up4rnnsp0tlp8665xldkq9z9u85tgh6nxmkfg3pc6wzk2t90pekj2d6l0km09vyt4vut24vhzg9qhrdsgr7dws828p6ejk7ddy0zkz3a2fq5648664w3se2egwvh904lzmpnc7a7wy4fayznunt6j4ndmm68y24tjje4qxnxs70w4lr9vz9q9qca903edtjd6c5f37jagafsqnhnlsuwvnqwc7uly4dw2rnlyxp4zcfqrfpkpez54c0lc3tmvppmv06ge97heevgt0acrq0ezgjr6ck9waqpanypl8dzrqdzjd05h735tdgv2wjjjucheur40h4wjw4pcdpc8pqlh7ef95rj2al8v3eexkgty8j2ne7kk2zxpe0wypq8ra0x76rt6cu00cw4w05v0u3ng6zhfrttz2c3m5nx64s8w98wa26dx79jwhne44gp9lmg6vkhxq98meslyr4zqtxjsg27xzj80m0csd77lr047vwycvdw0z8mwudm3uvlry9p9da4su72k9q84pphw4n0fyeet0ujzrdgacm6p777jun0y0v397mp4drafr6q7994kdl96m388xp6ggf5arn4d4ed53rv9tlkerckqvkng92uhdvngwcl3m6yqhxdjjnkca62tckxfnrae4cx4e6wx6ww5649v4hvuwkkajanllc38wavqy83xhn555l708354nt2quscchexsxjgezdxfnmxgue0cn4ktghd6xd2le76k5cw3t0p0nurs4h5rjz0j7twj9ulwkp7cmhhgl23r7g677gk36r5jw8panh2sq5966m08sa5632egd5ms6h0e504dtwskct3x6a93uutaumtc8aam8yyt66lrmrhcssw9ga2yg0496s6sdmaexa49064g3syc888egnwa8racrwwwwemknqamarpqlmqa5mg8zgt0dts8ehuwmgz4j3cjltr8gv78e7p84zm8pylann7dmss5suf4htqc04qx5trnk59m305ah2qp4mvkxwy6ts84sa30d80jzk9s6n40e4j8dcvq79ncg5e3z5g4esxyawmxk7lvm5efc30vtw8qqhe9xx3773djez6hjjx0x962z2radnvdmazkrmlqw7guxz29qvahcx79h33ncqhzhvekwaqqnrz3wxnp2qy3u83zdgdcgq27n5n22h7jjedrh28m8c6mn42xhfjasm5njsxtufqjxefnhc2n5zr0um0xlqk62cu25cjwuwwrcv3e4vhh2tdzn8rnlaefj98fvslg7sun95wpt2a4vcg4ua62v97aeqstvjegmlem5crnsamrhm3a2pcma2s22atr43lgx9vh7kn9lzymfe83a4vhe9rc6xl5pmy5hjw4t88k0fwh6lzmjtjvqtczq47ny7hv8ytdqdy2c7ce3gegnufkzwphkwtz6xqzklyw7e7f76fwfewfuyqal7dl8r9476jerrl40mav38sun2u8jvftw33x3r20dmeka34znmkgaz29ppk5hz3ldttw8zyz4k6q0gts8utqh53tuc7vtajl26rq2fnxr0vxcwlx9rfvn6v8ar8c73qkc3zca4mlgl7qu36sk7e
This will write three new files, consignment, disclosure and the psbt including the tweak, this psbt is called witness transaction, the consignment is sent to rgb-node-1.

Witness

The witness transaction should be signed and broadcasted, for this we need to base64 encode it back.
$ base64 -w0 witness.psbt cHNidP8BAHECAAAAAe2pydT0BqfK5nBCdBSbm3W/vNKE/QxTr4eJcjwjDLDjAQAAAAD/////AiWbAAAAAAAAFgAUO1Bi4v2VHUJPmq5iyYhDv1tyTCcQJwAAAAAAABYAFPwfm3skdSeMnOfcDqBpgVjwuwESAAAAAAABAHECAAAAAeSwUiZ+p3/NM7yt3BAoDkm/afi//lplsffwwpTqjd+CAQAAAAD/////AlDDAAAAAAAAFgAULga5BeTQ1vfiqcD3zuxk+K2O/wbDwgAAAAAAABYAFLsvLLowx0NR5NyFKj9wl3IFvNcPAAAAAAEBH8PCAAAAAAAAFgAUuy8sujDHQ1Hk3IUqP3CXcgW81w8iBgKIYFEbYKvRj25inaA0/c0PMIZD/BFAgFbjrBJe8cZ+cxDskk+CAAAAgAEAAIADAACAACICAsnwAXsMVlPXi/2ExgqtLoIN4TncWVW0EImSo9YwyhNmEOyST4IAAACAAQAAgAUAAIAG/ANSR0IBIQLJ8AF7DFZT14v9hMYKrS6CDeE53FlVtBCJkqPWMMoTZgb8A1JHQgIgMD8j8bQGB8NgEobv3NUJr7aERA/FkGgQ5w2KwF+daDgAAA==
Sign it with walletprocesspsbt subcommand.
$ bcli walletprocesspsbt "cHNidP8BAHECAAAAAe2pydT0BqfK5nBCdBSbm3W/vNKE/QxTr4eJcjwjDLDjAQAAAAD/////AiWbAAAAAAAAFgAUO1Bi4v2VHUJPmq5iyYhDv1tyTCcQJwAAAAAAABYAFPwfm3skdSeMnOfcDqBpgVjwuwESAAAAAAABAHECAAAAAeSwUiZ+p3/NM7yt3BAoDkm/afi//lplsffwwpTqjd+CAQAAAAD/////AlDDAAAAAAAAFgAULga5BeTQ1vfiqcD3zuxk+K2O/wbDwgAAAAAAABYAFLsvLLowx0NR5NyFKj9wl3IFvNcPAAAAAAEBH8PCAAAAAAAAFgAUuy8sujDHQ1Hk3IUqP3CXcgW81w8iBgKIYFEbYKvRj25inaA0/c0PMIZD/BFAgFbjrBJe8cZ+cxDskk+CAAAAgAEAAIADAACAACICAsnwAXsMVlPXi/2ExgqtLoIN4TncWVW0EImSo9YwyhNmEOyST4IAAACAAQAAgAUAAIAG/ANSR0IBIQLJ8AF7DFZT14v9hMYKrS6CDeE53FlVtBCJkqPWMMoTZgb8A1JHQgIgMD8j8bQGB8NgEobv3NUJr7aERA/FkGgQ5w2KwF+daDgAAA==" { "psbt": "cHNidP8BAHECAAAAAe2pydT0BqfK5nBCdBSbm3W/vNKE/QxTr4eJcjwjDLDjAQAAAAD/////AiWbAAAAAAAAFgAUO1Bi4v2VHUJPmq5iyYhDv1tyTCcQJwAAAAAAABYAFPwfm3skdSeMnOfcDqBpgVjwuwESAAAAAAABAHECAAAAAeSwUiZ+p3/NM7yt3BAoDkm/afi//lplsffwwpTqjd+CAQAAAAD/////AlDDAAAAAAAAFgAULga5BeTQ1vfiqcD3zuxk+K2O/wbDwgAAAAAAABYAFLsvLLowx0NR5NyFKj9wl3IFvNcPAAAAAAEBH8PCAAAAAAAAFgAUuy8sujDHQ1Hk3IUqP3CXcgW81w8BCGsCRzBEAiAZud+YVf1FyZq0IDQ+/oAE34TKypedrJGUcYx0QIpaygIgZJO7xvN0dOQXbXTRYE0QxGIWsfo85Dhwne0/whoO06kBIQKIYFEbYKvRj25inaA0/c0PMIZD/BFAgFbjrBJe8cZ+cwAiAgLJ8AF7DFZT14v9hMYKrS6CDeE53FlVtBCJkqPWMMoTZhDskk+CAAAAgAEAAIAFAACABvwDUkdCASECyfABewxWU9eL/YTGCq0ugg3hOdxZVbQQiZKj1jDKE2YG/ANSR0ICIDA/I/G0BgfDYBKG79zVCa+2hEQPxZBoEOcNisBfnWg4AAA=", "complete": true }
Now finalize it and get the hex.
$ bcli finalizepsbt "cHNidP8BAHECAAAAAe2pydT0BqfK5nBCdBSbm3W/vNKE/QxTr4eJcjwjDLDjAQAAAAD/////AiWbAAAAAAAAFgAUO1Bi4v2VHUJPmq5iyYhDv1tyTCcQJwAAAAAAABYAFPwfm3skdSeMnOfcDqBpgVjwuwESAAAAAAABAHECAAAAAeSwUiZ+p3/NM7yt3BAoDkm/afi//lplsffwwpTqjd+CAQAAAAD/////AlDDAAAAAAAAFgAULga5BeTQ1vfiqcD3zuxk+K2O/wbDwgAAAAAAABYAFLsvLLowx0NR5NyFKj9wl3IFvNcPAAAAAAEBH8PCAAAAAAAAFgAUuy8sujDHQ1Hk3IUqP3CXcgW81w8BCGsCRzBEAiAZud+YVf1FyZq0IDQ+/oAE34TKypedrJGUcYx0QIpaygIgZJO7xvN0dOQXbXTRYE0QxGIWsfo85Dhwne0/whoO06kBIQKIYFEbYKvRj25inaA0/c0PMIZD/BFAgFbjrBJe8cZ+cwAiAgLJ8AF7DFZT14v9hMYKrS6CDeE53FlVtBCJkqPWMMoTZhDskk+CAAAAgAEAAIAFAACABvwDUkdCASECyfABewxWU9eL/YTGCq0ugg3hOdxZVbQQiZKj1jDKE2YG/ANSR0ICIDA/I/G0BgfDYBKG79zVCa+2hEQPxZBoEOcNisBfnWg4AAA=" { "hex": "02000000000101eda9c9d4f406a7cae6704274149b9b75bfbcd284fd0c53af8789723c230cb0e30100000000ffffffff02259b0000000000001600143b5062e2fd951d424f9aae62c98843bf5b724c271027000000000000160014fc1f9b7b2475278c9ce7dc0ea0698158f0bb011202473044022019b9df9855fd45c99ab420343efe8004df84caca979dac9194718c74408a5aca02206493bbc6f37474e4176d74d1604d10c46216b1fa3ce438709ded3fc21a0ed3a90121028860511b60abd18f6e629da034fdcd0f308643fc11408056e3ac125ef1c67e7300000000", "complete": true }

Broadcast

Broadcast it using sendrawtransaction subcommand to get it confirmed into the blockchain.
$ bcli sendrawtransaction "02000000000101eda9c9d4f406a7cae6704274149b9b75bfbcd284fd0c53af8789723c230cb0e30100000000ffffffff02259b0000000000001600143b5062e2fd951d424f9aae62c98843bf5b724c271027000000000000160014fc1f9b7b2475278c9ce7dc0ea0698158f0bb011202473044022019b9df9855fd45c99ab420343efe8004df84caca979dac9194718c74408a5aca02206493bbc6f37474e4176d74d1604d10c46216b1fa3ce438709ded3fc21a0ed3a90121028860511b60abd18f6e629da034fdcd0f308643fc11408056e3ac125ef1c67e7300000000" 8e3787fe40b5feb3044f892e739bdb4043e10de384255a915a37725811abc3fe

Accept

To accept an incoming transfer rgb-node-1 should have received the consignment file from rgb-node-0, have the receive_utxo and the corresponding blinding_factor generated during blinding UTXO generation.
$ rgb1-cli fungible accept consignment.rgb e40d9037e31d3f440552b30af16e764cf25ffda3899b4851cc4e38fd64718b09:0 1679197189805229975 Asset transfer successfully accepted.
We can now see (in the knownAllocations field) the new allocation of 100 asset units in <receive_utxo> by running:
$ rgb1-cli fungible list -l - genesis: genesis1qyfe883hey6jrgj2xvk5g3dfmfqfzm7a4wez4pd2krf7ltsxffd6u6nrvjvvnc8vt9llmp7663pgututl9heuwaudet72ay9j6thc6cetuvhxvsqqya5xjt2w9y4u6sfkuszwwctnrpug5yjxnthmr3mydg05rdrpspcxysnqvvqpfvag2w8jxzzsz9pf8pjfwf0xvln5z7w93yjln3gcnyxsa04jsf2p8vu4sxgppfv0j9qerppqxhvztpqscnjsxvq5gdfy5v6j3wvpjxxqzcerxuglngnfvpxjkgqusct7cyx8zzezcfpqv3nxjxm2kjj4d0zu0ta6fjmpr8a0calk6h88h4ap5e4nucj0ch07aa73qsh3lj5sd89a32kwy0eq7tsa5zqqjpdqvqq5s46r0 id: rgb1tadqzve7vwfh39sl6gvqenp8wegsrzreekhhu0dhthx08ppzj9wq8p0je6 ticker: USDT name: USD Tether description: ~ knownCirculating: 1000 isIssuedKnown: ~ issueLimit: 0 chain: testnet decimalPrecision: 0 date: "2022-02-23T20:53:26" knownIssues: - id: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f amount: 1000 origin: ~ knownInflation: {} knownAllocations: - nodeId: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f index: 0 outpoint: "4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893:1" revealedAmount: value: 1000 blinding: "0000000000000000000000000000000000000000000000000000000000000001" - nodeId: 28f82e2dcfa91282c28a8805ff0c7fde4bd4e0bdbd40c6ba55e191666e45327b index: 1 outpoint: "e40d9037e31d3f440552b30af16e764cf25ffda3899b4851cc4e38fd64718b09:0" revealedAmount: value: 100 blinding: 224561f10229eb9ebbdf05f497132d2b8344d70971c80510eddc607d615ee2a0
Since receive_utxo was blinded when the transfer was made, the payer rgb-node-0 has no information about where the 100 USDT was sent, so the location is not shown in knownAllocations .
$ rgb0-cli fungible list -l - genesis: genesis1qyfe883hey6jrgj2xvk5g3dfmfqfzm7a4wez4pd2krf7ltsxffd6u6nrvjvvnc8vt9llmp7663pgututl9heuwaudet72ay9j6thc6cetuvhxvsqqya5xjt2w9y4u6sfkuszwwctnrpug5yjxnthmr3mydg05rdrpspcxysnqvvqpfvag2w8jxzzsz9pf8pjfwf0xvln5z7w93yjln3gcnyxsa04jsf2p8vu4sxgppfv0j9qerppqxhvztpqscnjsxvq5gdfy5v6j3wvpjxxqzcerxuglngnfvpxjkgqusct7cyx8zzezcfpqv3nxjxm2kjj4d0zu0ta6fjmpr8a0calk6h88h4ap5e4nucj0ch07aa73qsh3lj5sd89a32kwy0eq7tsa5zqqjpdqvqq5s46r0 id: rgb1tadqzve7vwfh39sl6gvqenp8wegsrzreekhhu0dhthx08ppzj9wq8p0je6 ticker: USDT name: USD Tether description: ~ knownCirculating: 1000 isIssuedKnown: ~ issueLimit: 0 chain: testnet decimalPrecision: 0 date: "2022-02-23T20:53:26" knownIssues: - id: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f amount: 1000 origin: ~ knownInflation: {} knownAllocations: - nodeId: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f index: 0 outpoint: "4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893:1" revealedAmount: value: 1000 blinding: "0000000000000000000000000000000000000000000000000000000000000001"
But as you can see rgb-node-0 can't see the 900 asset change that we supplied to the transfer command with the -a argument. To register the change rgb-node-0 needs to accept the disclosure.
$ rgb0-cli fungible enclose disclosure.rgb Disclosure data successfully enclosed.
If rgb-node-0 was successful you can see the change by listing the asset.
$ rgb0-cli fungible list -l - genesis: genesis1qyfe883hey6jrgj2xvk5g3dfmfqfzm7a4wez4pd2krf7ltsxffd6u6nrvjvvnc8vt9llmp7663pgututl9heuwaudet72ay9j6thc6cetuvhxvsqqya5xjt2w9y4u6sfkuszwwctnrpug5yjxnthmr3mydg05rdrpspcxysnqvvqpfvag2w8jxzzsz9pf8pjfwf0xvln5z7w93yjln3gcnyxsa04jsf2p8vu4sxgppfv0j9qerppqxhvztpqscnjsxvq5gdfy5v6j3wvpjxxqzcerxuglngnfvpxjkgqusct7cyx8zzezcfpqv3nxjxm2kjj4d0zu0ta6fjmpr8a0calk6h88h4ap5e4nucj0ch07aa73qsh3lj5sd89a32kwy0eq7tsa5zqqjpdqvqq5s46r0 id: rgb1tadqzve7vwfh39sl6gvqenp8wegsrzreekhhu0dhthx08ppzj9wq8p0je6 ticker: USDT name: USD Tether description: ~ knownCirculating: 1000 isIssuedKnown: ~ issueLimit: 0 chain: testnet decimalPrecision: 0 date: "2022-02-23T20:53:26" knownIssues: - id: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f amount: 1000 origin: ~ knownInflation: {} knownAllocations: - nodeId: 5c912284f3cc5db73d7eafcd798801517627cc0c18d21f967893633e33015a5f index: 0 outpoint: "4c1785210d8930959f530072cffea7f9606e0599b0de9e89aed60f2e9f133893:1" revealedAmount: value: 1000 blinding: "0000000000000000000000000000000000000000000000000000000000000001" - nodeId: 28f82e2dcfa91282c28a8805ff0c7fde4bd4e0bdbd40c6ba55e191666e45327b index: 0 outpoint: "cd66d3b77dfc1c2ecf958847c16a8a1311bba84ee7bf9dd55592a7b97b13028f:1" revealedAmount: value: 900 blinding: ddba9e0efdd614614420fa0b68ecd2d3376a05dd3d809b2ad1f5fe0f6ed75ea2

Conclusions

We have been able to create a fungible asset and move it from one transaction to another in a private way, if we check the confirmed transaction in a block explorer we would not find anything different from regular transaction, this is thanks to the fact that RGB uses single-use seals to tweak the transactions, In this post, I do an intro to how RGB works.
This post may have bugs, if you find something please let me know to improve this guide, suggestions, and criticisms are also welcome, happy hacking! 🖖
Did this work well for you?
2
0
Original source:https://grunch.dev/blog/

Author

This tutorial has been written by Francisco Calderón

You can say thanks by tipping the professor.

Francisco CalderónFrancisco Calderón
3Tutorials

I'm a software engineer, Open source & Bitcoin supporter. I spend my time contributing to open source Bitcoin and Ligthning Network related projects, I want to help make Bitcoin better money and be easy to use for non technical people. I've been working on Lightning Network projects since Q1 2018, currently I'm an independent consultant on Bitcoin/Lightning Network related projects, if you want to talk just DM me.

developmentlightninguser-friendly

Credits

This tutorial has been proofread by Asi0Flammeus

1/3Proofreading status

Even if this content is in its original language, human review is necessary to ensure its accuracy.

Progress: 1/3Asi0Flammeus2 211 sats1 106 sats
*Rewards may vary based on the $ exchange rate

Every content on the platform is the result of a collaborative effort: each lesson, translation, and revision is made possible by the work of contributors. For this reason, we are always looking for proofreaders who can review our content in many languages. If you want to participate in the proofreading process, please reach out in our Telegram group and read our tutorial. We remind you that this content is open-source - licensed under CC BY-SA - so it can be freely shared and used, as long as the original source is credited.