RSK: Bitcoin smart contracts
O Bitcoin permite a execução de contratos. Alguns exemplos de smart contracts são multisig wallet e HTLC (ambos necessários para a Lightning Netowork).
Por ter como foco principal servir como uma plataforma financeira, sua linguagem (Script) é limitada (turing incomplete) e mais segura, já que possibilita menor margem para erros de programação em seus contratos.
Por acreditar ser necessária uma rede blockchain que tivesse como foco o de servir como plataforma para construção de aplicações descentralizadas (além de apenas usada para transações financeiras) que Vitalik Buterin criou a plataforma Ethereum.
O Rootstock é um projeto para execução de contratos inteligentes (turing complete) ao ecosistema do Bitcoin. Trata-se de uma Sidechain que utiliza como moeda o SBTC (Smart-BTC) que é conversível 1:1 com o Bitcoin (2-way peg). Esta conversão entre moedas é feita através da Federação RSK, composta em sua maioria por membros respeitados da comunidade. (Ex.: Xapo, Bitpay, Jaxx, BitGo, OKCoin, Zeppelin e etc).
Sempre que há uma transferência de BTCs destinado à rede RSK, o que acontece é que esses BTCs ficam presos na carteira da federação e a mesma quantidade de SBTCs são transferidos para sua carteira RSK (e vice-versa).
Uma característica interessante da solução é que ela é compatível com a Ethereum Virtual Machine (EVM) e seus contratos também são escritos em Solidity.
A Mainnet RSK já está rodando mas por enquanto fechada à participantes pré-aprovados (whitelist).
Neste post iremos subir um nó RSK testnet, realizar deploy de smart contract e algumas realizar transações.
Observação: Utilizei sistema operacional Ubuntu 16.04 (Xenial) recém instalado.
Instalação
$ sudo add-apt-repository ppa:rsksmart/rskj
$ sudo apt-get update
$ sudo apt-get install rskj
Tenha certeza que seu nó está configurado para a rede testnet. O link /etc/rsk/node.conf deve apontar para o arquivo /etc/rsk/testnet.conf.
$ ls /etc/rsk/node.conf -l
lrwxrwxrwx 1 root root 21 Jul 3 17:57 /etc/rsk/node.conf -> /etc/rsk/testnet.conf
Para rodar o nó rsk, use:
$ sudo service rsk start
O nó está sincronizando, baixe agora o projeto rsk-utilities que possibilitará acesso ao nó via console, caso ainda não os tenha, instale o NPM e o NodeJs pois serão necessários:
$ 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
Agora acesse o nó via console:
$ node ~/rsk-utils/utilities-master/console/console.js
RSK > web3.eth.syncing
{ startingBlock: 0, currentBlock: 48527, highestBlock: 52416 }
O console.js é um wrapper que utiliza o web3.js do ethereum. Assim sendo o console RSK é bem semelhante ao de um cliente Ethereum (Ex.: geth).
Agora devemos esperar a sincronização de nosso nó. Para verificar o último bloco da rede, utilize o explorer rsk testnet.
Quando a blockchain estiver atualizada o comando web3.eth.syncing retornará false e o comando web3.eth.blockNumber será igual ao útimo do explorer.
Accounts e Transações
Com seu nó atualizado, crie agora duas accounts para realizarmos uma transação entre elas.
$ 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"
}
Agora será preciso adicionar os accounts no arquivo de configuração do RSK e também habilitar a função carteira do nó, que por padrão está desabilitada no nó. Procure pela seção wallet no arquivo de configuração (/etc/rsk/node.conf)e acrescente as linhas abaixo:
$ sudo vi /etc/rsk/node.confwallet {
enabled = true
accounts = [
{
privateKey = "1ec575c11c227059b6c438f22773261f5876cdea60e83b607467e68ee1f2e6ff",
publicKey = "0490894e27b5663954aa5f595417ac6ea447a577f7ec58534c789fefb1d2920e995ca366912887a6fcfdd9694d94743d6eb7d6355c14aa5f70c534ef31628e2737",
address = "54aaa49f761dc048df63e81378054bcad2604230"
},
{
privateKey = "3489806ce2af94a6c227fe35de457242fc92f71a211b0b966970fab8d191d9cc",
publicKey = "0412e7a4d0420f636ff114414395a77c157a6116fab9887488b6e40ee6cd5551df4d48fb7ae44e705c13a3bb7d102039a79427dcd31ec77a0553e3d712ba7d396b",
address = "9c46863dda60dd78aa628330347167caf0ba0dfc"}
]
}$ sudo service rsk restart
Agora precisaremos de alguns Smart BTCs para testarmos transferências e posteriormente trabalharmos com contratos inteligentes. Podemos obtê-los através de faucet fornecido pelo projeto para a testnet.
Em poucos segundos você terá saldo no account:
RSK > web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]), 'ether').toString();
0.001
Faça agora uma transação entre as contas:
RSK > web3.eth.sendTransaction({from: web3.eth.accounts[0], to: web3.eth.accounts[1], value: web3.toWei('0.0001','ether')});
0xffc7aac1d83d3ffd1c516e62058bd48cc3df530e24ee216c6474850d2e4f91d1
Verifique os saldos dos accounts:
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
Contratos
Crie um projeto Truffle com a biblioteca OpenZeppelin:
$ mkdir ~/rsk_erc20
$ cd ~/rsk_erc20
$ truffle init
$ vi truffle.jsmodule.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
Observação: Substitua o endereço de origem pelo criado por você anteriormente.
Em seguida crie um contrato padrão ERC20:
$ vi contracts/RSKToken.solpragma 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_;
}
}
Faça agora o deploy do contrato na rede RSK:
$ sed s/Migrations/RSKToken/g migrations/1_initial_migration.js > migrations/2_rsktoken.js
$ truffle compile
$ truffle migrate --network rsk
Com o contrato implantado, é possível realizar testes de transfência de tokens entre os 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'
Pronto! Foi realizada transferência de token ERC20 na rede RSK com sucesso!
Conclusão
Neste post mostrei como subir um nó RSK, sidechain que possibilitará a execução de smart contracts utilizando o Bitcoin. Por ser compatível com a EVM ela possui a grande vantagem de rodar códigos escritos para o Ethereum.
Assim como a Lightning Network, que tem como foco possibilitar a execução de micro-transações instantâneamente em escala através de introdução de uma nova camada/rede, o RSK é uma solução que possibilita a execução de contratos inteligentes também através de protocolo distinto.