RSK: Bitcoin smart contracts (EN)

Bitcoin allows smart contracts. Some cases of smart contracts are multisig wallet and HTLC (both used by Lightning Network).
The Bitcoin’s killer app is digital money. Because of that its language (Script) is limited (turing incomplete) and safer, since it allows less probability of programming bugs on their contracts.

For believing that a blockchain that focused on serving as a platform for the construction of decentralized applications (besides being used only for financial transactions) was needed, Vitalik Buterin created the Ethereum platform.

Rootstock is a project to execute smart contracts (turing complete) to the ecosystem of Bitcoin. It is a Sidechain that uses as currency the SBTC (Smart-BTC) which is convertible 1: 1 with Bitcoin (2-way peg). This conversion between currencies is done through the RSK Federation, composed mostly by respected members of the community (Ex: Xapo, Bitpay, Jaxx, BitGo, OKCoin, Zeppelin and etc).

Whenever there is a transfer of BTCs destined for the RSK network, those BTCs get stuck in the federation wallet and the same amount of SBTCs are transferred to your RSK wallet (and vice versa).

An interesting feature of the solution is that it is compatible with the Ethereum Virtual Machine (EVM) and its contracts are also written in Solidity.

The RSK mainnet is already running but for the time being it’s closed to pre-approved participants (whitelisted).
In this post we will run a RSK testnet node, perform smart contract deploy and make some transactions.

Observation: I’ve used a fresh new Ubuntu 16.04 (Xenial) instalation.

$ sudo add-apt-repository ppa:rsksmart/rskj
$ sudo apt-get update
$ sudo apt-get install rskj

Make sure your node is configured for the testnet network. The link /etc/rsk/node.conf should point to the /etc/rsk/testnet.conf file.

$ ls /etc/rsk/node.conf -l
lrwxrwxrwx 1 root root 21 Jul 3 17:57 /etc/rsk/node.conf -> /etc/rsk/testnet.conf

To run RSK node, use:

$ sudo service rsk start

The node is synchronizing, now install the rsk-utilities project. It’ll allow access to node throw console. If you don’t have them, install NPM and NodeJs because both will be necessary.

$ sudo apt-get install npm
$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt-get install -y nodejs
$ mkdir ~/rsk-utils
$ cd ~/srk-utils
$ wget https://github.com/rsksmart/utilities/archive/master.zip
$ unzip master.zip
$ cd utilities-master/console
$ npm install

Now access node using console:

$ node ~/rsk-utils/utilities-master/console/console.js
RSK > web3.eth.syncing
{ startingBlock: 0, currentBlock: 48527, highestBlock: 52416 }

Console.js is a wrapper that uses ethereum web3.js. So the RSK console is very similar to that of an Ethereum client (e.g., geth).

Now you should wait node syncronization. To check last block, use the rsk testnet explorer.

When the blockchain is updated, the command web3.eth.syncing will return false and the web3.eth.blockNumber command will return the same block as the latest in explorer.

With your node up-to-date, create two accounts to make a transaction between them.

$ java -cp /usr/share/rsk/rsk.jar co.rsk.GenNodeKeyId
{
"privateKey": "1ec575c11c227059b6c438f22773261f5876cdea60e83b607467e68ee1f2e6ff",
"publicKey": "0490894e27b5663954aa5f595417ac6ea447a577f7ec58534c789fefb1d2920e995ca366912887a6fcfdd9694d94743d6eb7d6355c14aa5f70c534ef31628e2737",
"publicKeyCompressed": "0390894e27b5663954aa5f595417ac6ea447a577f7ec58534c789fefb1d2920e99",
"address": "54aaa49f761dc048df63e81378054bcad2604230",
"nodeId": "90894e27b5663954aa5f595417ac6ea447a577f7ec58534c789fefb1d2920e995ca366912887a6fcfdd9694d94743d6eb7d6355c14aa5f70c534ef31628e2737"
}
$ java -cp /usr/share/rsk/rsk.jar co.rsk.GenNodeKeyId
{
"privateKey": "3489806ce2af94a6c227fe35de457242fc92f71a211b0b966970fab8d191d9cc",
"publicKey": "0412e7a4d0420f636ff114414395a77c157a6116fab9887488b6e40ee6cd5551df4d48fb7ae44e705c13a3bb7d102039a79427dcd31ec77a0553e3d712ba7d396b",
"publicKeyCompressed": "0312e7a4d0420f636ff114414395a77c157a6116fab9887488b6e40ee6cd5551df",
"address": "9c46863dda60dd78aa628330347167caf0ba0dfc",
"nodeId": "12e7a4d0420f636ff114414395a77c157a6116fab9887488b6e40ee6cd5551df4d48fb7ae44e705c13a3bb7d102039a79427dcd31ec77a0553e3d712ba7d396b"
}

Now you need to add the accounts in the RSK configuration file and also enable the wallet function of the node, which by default is disabled. Look for the wallet section in the configuration file (/etc/rsk/node.conf) and add the lines below:

$ sudo vi /etc/rsk/node.conf
wallet {
enabled = true
accounts = [
{
privateKey = "1ec575c11c227059b6c438f22773261f5876cdea60e83b607467e68ee1f2e6ff",
publicKey = "0490894e27b5663954aa5f595417ac6ea447a577f7ec58534c789fefb1d2920e995ca366912887a6fcfdd9694d94743d6eb7d6355c14aa5f70c534ef31628e2737",
address = "54aaa49f761dc048df63e81378054bcad2604230"
},
{
privateKey = "3489806ce2af94a6c227fe35de457242fc92f71a211b0b966970fab8d191d9cc",
publicKey = "0412e7a4d0420f636ff114414395a77c157a6116fab9887488b6e40ee6cd5551df4d48fb7ae44e705c13a3bb7d102039a79427dcd31ec77a0553e3d712ba7d396b",
address = "9c46863dda60dd78aa628330347167caf0ba0dfc"
}
]
}
$ sudo service rsk restart

Now you will need some Smart BTCs to test transfers and work with smart contracts. We can get them through the faucet provided by the project for the testnet.

In a few seconds you will have balance in the account:

RSK > web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]), 'ether').toString();
0.001

Now, make a transaction between accounts:

RSK > web3.eth.sendTransaction({from: web3.eth.accounts[0], to: web3.eth.accounts[1], value: web3.toWei('0.0001','ether')});
0xffc7aac1d83d3ffd1c516e62058bd48cc3df530e24ee216c6474850d2e4f91d1

Check the balances:

RSK > ana = web3.eth.accounts[0];
0x54aaa49f761dc048df63e81378054bcad2604230
RSK > bob = web3.eth.accounts[1];
0x9c46863dda60dd78aa628330347167caf0ba0dfc
RSK > web3.fromWei(web3.eth.getBalance(ana), 'ether').toString();
0.0009
RSK > web3.fromWei(web3.eth.getBalance(bob), 'ether').toString();
0.0001

Create a Truffle project with the OpenZeppelin library:

$ mkdir ~/rsk_erc20
$ cd ~/rsk_erc20
$ truffle init
$ vi truffle.js
module.exports = {
networks: {
rsk: {
from: "
0x54aaa49f761dc048df63e81378054bcad2604230",
gasPrice: 1,
gas:
6732000,
host: "localhost",
port: 4444,
network_id: "*" // Match any network id
}
}
};
$ npm init -y
$ npm install -E openzeppelin-solidity

Observation: Replace address with the one you created by you previously.

Then create a standard contract ERC20:

$ vi contracts/RSKToken.sol
pragma solidity ^0.4.23;
import 'openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol';
contract RSKToken is BasicToken {

string public constant name = "RSKToken";
string public constant symbol = "RSKT";
uint8 public constant decimals = 18;

constructor() public {
totalSupply_ = 100 * (10 ** uint256(decimals));
balances[msg.sender] = totalSupply_;
}
}

Deploy contract on RSK network:

$ sed s/Migrations/RSKToken/g migrations/1_initial_migration.js > migrations/2_rsktoken.js
$ truffle compile
$ truffle migrate --network rsk

With the contract implemented, it is possible to perform tokens transfer between accounts:

$ truffle console --network rsk
truffle(rsk)> RSKToken.deployed().then(function(c) { erc20 = c });
truffle(rsk)> ana = web3.eth.accounts[0];
'0x54aaa49f761dc048df63e81378054bcad2604230'
truffle(rsk)> bob = web3.eth.accounts[1];
'0x9c46863dda60dd78aa628330347167caf0ba0dfc'
truffle(rsk)> erc20.balanceOf(ana).then(function(a){ return web3.fromWei(a.toString(),'ether'); });
'100'
truffle(rsk)> erc20.balanceOf(bob).then(function(b){ return web3.fromWei(b.toString(),'ether'); });
'0'
truffle(rsk)> erc20.transfer(bob, web3.toWei(10,'ether'), {from: ana})
{ tx: '0x65f68dc534ece096d5ce00aa4c78d823b812aa71e14924405ec5fc42076eded5',
receipt:
{ transactionHash: '0x65f68dc534ece096d5ce00aa4c78d823b812aa71e14924405ec5fc42076eded5',
transactionIndex: 0,
blockHash: '0x991422cea4de1c0a72493cdbc3161b09163253ac8df05bf946829297aab59077',
blockNumber: 627946,
cumulativeGasUsed: 51801,
gasUsed: 51801,
contractAddress: null,
logs: [ [Object] ],
from: '0x54aaa49f761dc048df63e81378054bcad2604230',
to: '0x6ab06a95fdbc0855b9bcc4bafbc37aec7b070d2d',
root: '0x01',
status: '0x01' },
logs:
[ { logIndex: 0,
blockNumber: 627946,
blockHash: '0x991422cea4de1c0a72493cdbc3161b09163253ac8df05bf946829297aab59077',
transactionHash: '0x65f68dc534ece096d5ce00aa4c78d823b812aa71e14924405ec5fc42076eded5',
transactionIndex: 0,
address: '0x6ab06a95fdbc0855b9bcc4bafbc37aec7b070d2d',
event: 'Transfer',
args: [Object] } ] }
truffle(rsk)> erc20.balanceOf(ana).then(function(a){ return web3.fromWei(a.toString(),'ether'); });
'90'
truffle(rsk)> erc20.balanceOf(bob).then(function(b){ return web3.fromWei(b.toString(),'ether'); });
'10'

Ready! ERC20 token successfully transferred to RSK network!

Conclusion

In this post I showed how to run a RSK node, sidechain that will enable the execution of smart contracts using Bitcoin. Because it is compatible with EVM, it has the great advantage of running codes written for Ethereum.

Just as the Lightning Network, which focuses on enabling execution of micro-transactions instantly in scale through the introduction of a new layer / network, RSK is a solution that enables the execution of smart contracts also through a distinct protocol.