Create a UTXO-based token system
This example dapp may be deprecated. Thus, it may not function correctly with the latest versions of postchain, rell, and postchain-client.
As an exercise, we can also implement a Bitcoin-style token system.
We first define an unspent transaction output structure:
entity utxo {
pubkey;
amount: integer;
}
Then define the transfer operation that roughly follows Bitcoin transaction structure -- it has a list of inputs and outputs:
operation transfer (inputs: list<utxo>, output_pubkeys: list<pubkey>, output_amounts: list<integer>) {
var input_sum = 0;
for (an_utxo in inputs) {
require(op_context.is_signer(an_utxo.pubkey));
input_sum += an_utxo.amount;
delete utxo@{utxo == an_utxo};
}
var output_sum = 0;
require(output_pubkeys.size() == output_amounts.size());
for (out_index in range(output_pubkeys.size())) {
output_sum += output_amounts[out_index];
create utxo (output_pubkeys[out_index],
output_amounts[out_index]);
}
require(output_sum <= input_sum);
}
There are quite a lot of new constructs used in this example:
list<...>
is, obviously, a collection. Besides lists, Rell also supportsset
andmap
- in
list<utxo>
utxo object references are physically implemented using integer identifiers which are used internally an_utxo.pubkey
accesses an attribute of an object, which is a database query identical toutxo@{utxo==an_utxo} (pubkey)
- variable type is automatically inferred from expression used for
initialization. One can also write it like
var output_sum : integer = 0;
delete
operation accepts a relational expression which identifies objects.size()
method can be used get the size of a collectionfor (... in ...)
works both for collections and for ranges of integer values[]
is used to refer to an element of a collection
A front-end client together with a similar UTXO implementation to the preceding example can be found here.
Note that we perform checks as we go. This is OK because Rell is transactional: if a requirement fails or an error is generated, the whole operation (in fact, the entire transaction) is rolled back. Rell is typically used with a GTX transaction format that supports multiple signers and operations per transaction. Thus it can easily support Bitcoin-style multi-input transactions, atomic token swaps, multi-sig, etc.
Now a bit about the delete
operator. Isn't it strange to enable the deletion
of data from a blockchain?!
Here we aren't deleting data "from a blockchain", we're removing entries from the current blockchain state. This is precisely how it works in a Bitcoin node -- once entries in an unspent transaction output set are spent, they're deleted. A typical Bitcoin node doesn't keep track of spent transaction outputs.
A system based on Rell (Postchain or Chromia) works in exactly the same way: raw information about transactions and operations is preserved in a blockchain. The database contains both raw blockchain transactions and processed current state. The current state is what a Rell programmer can work with: he is allowed to do destructive updates and delete entries. These operations don't affect the raw blockchain.