rholang - a programming language for distributed systems
- From the sandbox
- Tutorial
RChain is a distributed computing blockchain platform. Like ethereum, only an order of magnitude faster. In theory, it can be scaled to infinity, the first implementations in practice allow you to process up to 40 thousand transactions per second. Technical details are in the architecture document .

Contracts on the RChain platform are written in the rholang language , with which I would like to introduce the audience of the Habr. You can try to write and execute programs in this language either by downloading and running the Rchain node through the docker, or using the interpreter on the site .
Full tutorial
Rolang (or simply ro ) is a process-oriented language. All calculations on it are performed by sending messages between the " channels ". On the channels are stored a plurality of messages. Po is a completely asynchronous language, so the order in which messages are received on the channels does not play any role. For example, you can read a message from a channel and then perform some operation on that message. However, you cannot send a message and then do something after the message is received. At least not separately specifying the expectation of a delivery confirmation message. It is worth noting that in this tutorial we will use the terms name andchannel as synonyms. INIn the algebra on which rholang is based, the term name is used , but since we can send and receive data with their help, they are semantically similar to channels .
Contracts and Data Submission
1 contract @"HelloWorld"(return) = {
2 return!("Hello, World!")
3 } |
4 new myChannel in {
5 @"HelloWorld"!(*myChannel)
6 }- A ro program is a single process consisting of several parts that are executed synchronously. This process is started by creating a contract named @ "HelloWorld". Creating a contract starts a process that invokes a copy of its "body" every time it receives a message. It is worth noting that in the roll all processes can be "quoted" using the @ operator and turn into a channel . Lines are just special processes, and we can quote any process and thus create a channel . Over on RChain platform meets the storage library rspace , written in Scala.
- On the channel,
returnwe send the string "Hello, World!" - The design
new ... inallows you to create a new private channel. No other process can send or receive messages from this channel. Each exception must be specified separately, sending channel_name to another process. - We send channel myChannel contract at @ "HelloWorld". The operator
*means "unquoting" the channel and returns the original process. In ro you can only send processes on channels, you can not directly send channels to channels . In this way, we turn a private channel into a process before sending it.
Data retrieval
1 contract @"HelloAgain"(_) = {
2 new chan in {
3 chan!("Hello again, world!") |
4 for (@text <- chan) { Nil }
5 }
6 } | @"HelloAgain"!(Nil)- Contracts have at least one parameter, but we can get around this by specifying a wildcard
_. - We are creating a new channel
chan. - We are sending the line process "Hello again, world!" on the new channel .
- We are listening to the new channel and are waiting for the only message. The operation
forremains blocked untilchanthere is a message on the channel . In ro, you can only receive names through channels , but you can send quoted processes as well. The assignment to the left of the expression is a name pattern. In this example , this means that the resulting name is a quoted process and we want to associate this process with a free text variable. The operation behaves similarly: it can read only one message and then becomes the body, and does not call a copy of itself in each message. In this case, we do nothing in and turn it into a stopped process<-@textforforNil, in principle, we can performchanother operations with the text on the channel .
State change
1 new MakeCell in {
2 // Makes a single cell in which you can store values
3 contract MakeCell(@init, get, set) = {
4 new valueStore in {
5 valueStore!(init) |
6 contract get(ack) = {
7 for(@value <- valueStore) {
8 valueStore!(value) | ack!(value)
9 }
10 } |
11 contract set(@newValue, ack) = {
12 for(_ <- valueStore) {
13 valueStore!(newValue) | ack!(true)
14 }
15 }
16 }
17 } |
18 // Cell usage.
19 new myGet, mySet in {
20 MakeCell!(123, *myGet, *mySet) |
21 new ack in {
22 myGet!(*ack) |
23 for (@result <- ack) {
24 //result now contains the value 123
25 mySet!(456, *ack) |
26 for (_ <- ack) {
27 myGet!(*ack) |
28 for (@result <- ack) {
29 //result now contains the value 456
30 Nil
31 }
32 }
33 }
34 }
35 }
36 }- We create a new channel
MakeCelland then use it on line 3 as the name of the internal contract. No other process than code in this lexical environment can cause it. - The contract
MakeCellneeds three arguments. The first argument is the value that this cell will contain. The second and third are the channels through which the cell will receive read and write requests. Note that the first argument must be a process, and the second and third should be names. Since names are always sent through channels, the first argument will be a pattern starting with@, which indicates that the name obtained is a quoted process and we want to associate this process with a variable. - To save the value, we create a new channel. This channel will contain a maximum of one value, the current value of the cell.
- There
valueStoreare no messages on the channel to this line . After we set the initial value, this value will become the only one on this channel. - We are launching a contract that listens on the reading channel. Each time a message is received, the body of the contract is executed.
- We block the contract until you receive a message on the channel
valueStore. Since the channelvalueStorecan expect no more than one message, reading the message is a kind of lock. - We again transmit the current value of the channel
valueStore, opening the processing of other messages and removing the block. Now we pass the current value back to the client on the channelack. - In parallel with the get contract, we run a contract that listens on set.
- We block it until a message appears on
valueStore, and then read it. We throw away the message that we read. - We send the new value to the storage on the channel
valueStoreand give a signal that the operation has completed.
- 18-36) A code that shows the creation of a cell, setting the initial value
123, reading this value, setting the value456, getting this value.
Note the depth of the layers to which the call extends. Po was specifically designed to describe synchronous computing, and therefore it is necessary to explicitly indicate the order of actions where in other languages this goes without saying.
Conclusion
Po is a language that was created for use on blockchains, but we have not yet reached the device of nodes, namespaces, wallets, Rev and phlogiston, network structure or Casper consensus algorithm.
Full tutorial .