Skip to content

Commit

Permalink
[Docs] Add BTCRelay to validator document.
Browse files Browse the repository at this point in the history
  • Loading branch information
dm4 committed Nov 5, 2018
1 parent ef9a19d commit dd2463d
Showing 1 changed file with 88 additions and 107 deletions.
195 changes: 88 additions & 107 deletions docs/validator-only-contract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,146 +26,127 @@ isValidator Grammar
// If the address is a validator => return true
// Otherwise => return false
Examples
--------

Compile isValidator Contract
----------------------------
BTCRelay
````````

There is a simple contract that leverage isValidator to grant validators to modify states.
Here we use `BTCRelay <https://github.com/CyberMiles/smart_contracts/tree/master/BTCRelay>`_ contract as an example to show how validator only contract works.
BTCRelay is a contract that store BTC headers and verify BTC transactions.

.. code:: ts
pragma lity ^1.2.4;
contract ValidatorOnlyContractExample {
uint[] BTCHeaders;
modifier ValidatorOnly() {
require(
isValidator(msg.sender),
"Only validator can use this function."
);
_;
}
function pushBTCHeader(uint blockHash) public ValidatorOnly returns (uint headersLength) {
BTCHeaders.push(blockHash);
headersLength = BTCHeaders.length;
}
function getBTCHeader(uint blockNum) view public returns (uint) {
return BTCHeaders[blockNum];
}
Download and compile it using ``lityc`` (version >= 1.2.2):

function getBTCHeaders() view public returns (uint[]) {
return BTCHeaders;
}
}
and we could compile it using `lityc` (version >= 1.2.2):
.. code:: bash
.. code:: ts
$ wget https://raw.githubusercontent.com/CyberMiles/smart_contracts/master/BTCRelay/BTCRelay.sol
$ lityc --abi --bin -o output BTCRelay.sol
$ mkdir output
$ ./lityc --abi --bin -o output ValidatorOnlyContractExample.sol
$ cat output/ValidatorOnlyContractExample.abi
[{"constant":false,"inputs":[{"name":"blockHash","type":"uint256"}],"name":"pushBTCHeader","outputs":[{"name":"headersLength","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBTCHeaders","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"blockNum","type":"uint256"}],"name":"getBTCHeader","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
$ cat output/ValidatorOnlyContractExample.bin
608060405234801561001057600080fd5b506102dd806100206000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636537eff61461005c578063bae9203d1461009d578063e415df9e14610109575b600080fd5b34801561006857600080fd5b506100876004803603810190808035906020019092919050505061014a565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b2610237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100f55780820151818401526020810190506100da565b505050509050019250505060405180910390f35b34801561011557600080fd5b506101346004803603810190808035906020019092919050505061028f565b6040518082815260200191505060405180910390f35b60003373ffffffffffffffffffffffffffffffffffffffff16f615156101fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f4f6e6c792076616c696461746f722063616e2075736520746869732066756e6381526020017f74696f6e2e00000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60008290806001815401808255809150509060018203906000526020600020016000909192909190915055506000805490509050919050565b6060600080548060200260200160405190810160405280929190818152602001828054801561028557602002820191906000526020600020905b815481526020019060010190808311610271575b5050505050905090565b6000808281548110151561029f57fe5b906000526020600020015490509190505600a165627a7a723058200785a80032fa88b662ace5fdae019671d7b1807c904adf4500b68af6cc1edaaf0029
and then we could deploy it to Travis chain:

.. code:: bash
Deploy contract to Travis
-------------------------
$ travis attach http://localhost:8545
After we get contract ABI and bytecode, we could deploy it to Travis chain.
// Prepare accounts
> validatorAccount = web3.cmt.accounts[0]
"0x7eff122b94897ea5b0e2a9abf47b86337fafebdc"
> normalAccount = personal.newAccount('test')
"0x34bb135d77771038a2fda3aa7cd5dc3fb4cc6abd"
> personal.unlockAccount(validatorAccount, '1234', 86400)
true
> personal.unlockAccount(normalAccount, 'test', 86400)
true
> cmt.sendTransaction({from: validatorAccount, to: normalAccount, value: 100000000000000000})
.. code:: bash
// Deploy contract
# Get Travis console
travis attach http://127.0.0.1:8545
# Deploy contract (in Travis console)
personal.unlockAccount(cmt.accounts[0], '1234');
abi = [{"constant":false,"inputs":[{"name":"blockHash","type":"uint256"}],"name":"pushBTCHeader","outputs":[{"name":"headersLength","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBTCHeaders","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"blockNum","type":"uint256"}],"name":"getBTCHeader","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
bytecode = "0x608060405234801561001057600080fd5b506102dd806100206000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636537eff61461005c578063bae9203d1461009d578063e415df9e14610109575b600080fd5b34801561006857600080fd5b506100876004803603810190808035906020019092919050505061014a565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b2610237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100f55780820151818401526020810190506100da565b505050509050019250505060405180910390f35b34801561011557600080fd5b506101346004803603810190808035906020019092919050505061028f565b6040518082815260200191505060405180910390f35b60003373ffffffffffffffffffffffffffffffffffffffff16f615156101fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f4f6e6c792076616c696461746f722063616e2075736520746869732066756e6381526020017f74696f6e2e00000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60008290806001815401808255809150509060018203906000526020600020016000909192909190915055506000805490509050919050565b6060600080548060200260200160405190810160405280929190818152602001828054801561028557602002820191906000526020600020905b815481526020019060010190808311610271575b5050505050905090565b6000808281548110151561029f57fe5b906000526020600020015490509190505600a165627a7a723058200785a80032fa88b662ace5fdae019671d7b1807c904adf4500b68af6cc1edaaf0029"
contract = web3.cmt.contract(abi);
c = contract.new(
> abi = <...>
> bytecode = <...>
> contract = web3.cmt.contract(abi);
> btcrelay = contract.new(
{
from: web3.cmt.accounts[0],
data: bytecode,
gas: "4700000"
},
function(e, contract) {
if (contract.address) {
console.log("contract address: " + contract.address);
console.log("transactionHash: " + contract.transactionHash);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
}
);
Use contract to test the functionality of isValidator
-----------------------------------------------------
.. code:: bash
// Contract mined! address: 0x05ea0f73204ea39d7231706a49c174a20380cfec transactionHash: 0x1acbd651d91f1edd3520da59dfda077c9f2ca3bbd9aa09bbc3304ec76a8b41ef
# Create a normal account, the return address will be different in your environment. Don't worry.
> newAccount = personal.newAccount("6666")
"0x52c3b25530e7c14b9c19eefc757fcfce3ef48316"
Now we try to call ``storeHeader`` function using both ``validatorAccount`` and ``normalAccount``
# Validator sends some cmt to the new account
> cmt.sendTransaction({from: cmt.account[0], to: newAccount, value: web3.toWei(1, "cmt")})
.. code:: bash
# Check whether the new account receives 1 cmt.
> cmt.getBalance(newAccount)
1000000000000000000
> height = 125552
> header = '0x0x0100000081cd02ab7e569e8bcd9317e2fe99f2de44d49ab2b8851ba4a308000000000000e320b6c2fffc8d750423db8b1eb942ae710e951ed797f7affc8892b0f1fc122bc7f5d74df2b9441a42a14695'
# At first, the BTCHeaders is empty
> c.getBTCHeaders.call()
[]
// Send transaction with validator account
# newAccount sends pushBTCHeader()
> tx_push_should_not_pass = c.pushBTCHeader.sendTransaction(0x0000000000000000000d87d1114bd39151486cdbfa2635ba8645791df0a0afd1, {from: newAccount, gas: "4700000"})
"0x8c3dc24ac03bdfbf0529a7a3a98cb7e598c7061062fd1688f099a944f8badb68"
> cmt.getTransactionReceipt(tx_push_should_not_pass)
> tx = btcrelay.storeHeader.sendTransaction(header, height, {from: validatorAccount, gas: "300000"})
"0xe5d83d5ca82a00b6311ec9b8c0bab4df3f7a62971231791182686ba8f594b7eb"
> cmt.getTransactionReceipt(tx)
{
blockHash: "0x1dd34d641b0c6355cef9f3ba6ec9e14520fd069c60fdd3afa37fcbb09d9a1420",
blockNumber: 575,
blockHash: "0x91186a59e8fb19c1db440ab0697266fb3407a10844342278a55e1dcf0eb501e1",
blockNumber: 72145,
contractAddress: null,
cumulativeGasUsed: 22906,
from: "0xd6a7662eb9a49f2ad96c4f82f526d49fb988ce68",
gasUsed: 22906,
logs: [],
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
status: "0x0",
to: "0xccad3cb4b2a2cb917b2c6eb4025c78d4cadeb804",
transactionHash: "0x8c3dc24ac03bdfbf0529a7a3a98cb7e598c7061062fd1688f099a944f8badb68",
cumulativeGasUsed: 140024,
from: "0x7eff122b94897ea5b0e2a9abf47b86337fafebdc",
gasUsed: 140024,
logs: [{
address: "0x05ea0f73204ea39d7231706a49c174a20380cfec",
blockHash: "0x91186a59e8fb19c1db440ab0697266fb3407a10844342278a55e1dcf0eb501e1",
blockNumber: 72145,
data: "0x00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d",
logIndex: 0,
removed: false,
topics: ["0xf82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c744"],
transactionHash: "0xe5d83d5ca82a00b6311ec9b8c0bab4df3f7a62971231791182686ba8f594b7eb",
transactionIndex: 0
}],
logsBloom: "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000800000
00000000000000000000000000000000000000000000001000000000000000100020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000",
status: "0x1",
to: "0x05ea0f73204ea39d7231706a49c174a20380cfec",
transactionHash: "0xe5d83d5ca82a00b6311ec9b8c0bab4df3f7a62971231791182686ba8f594b7eb",
transactionIndex: 0
}
# Check the BTCHeaders is empty
> c.getBTCHeaders.call()
[]
# Validator sends pushBTCHeader()
# BTC Block #542210 (hash = 0x0000000000000000000d87d1114bd39151486cdbfa2635ba8645791df0a0afd1)
> tx_push_should_pass = c.pushBTCHeader.sendTransaction(0x0000000000000000000d87d1114bd39151486cdbfa2635ba8645791df0a0afd1, {from: cmt.accounts[0], gas: "4700000"})
"0x0bbe6ace1c23d13fb8b4604398c793591c62fd68e38f1752d1ad38153f939e5c"
> cmt.getTransactionReceipt(tx_push_should_pass)
// Send transaction with normal account
> tx = btcrelay.storeHeader.sendTransaction(header, height, {from: normalAccount, gas: "300000"})
"0xed05e610feae32bd51931b9d0068104dc60a9595590d17b73e1916c2288b0cf9"
> cmt.getTransactionReceipt(tx)
{
blockHash: "0x08aef08ca19b97b4cfe0fae32ac9bf4369a7290d4e60691ee69f800cec055784",
blockNumber: 586,
blockHash: "0x611671eff48e414706daa66f1fcc404428832dd79c2b6a9481a28f46ef93a430",
blockNumber: 72173,
contractAddress: null,
cumulativeGasUsed: 63385,
from: "0x7eff122b94897ea5b0e2a9abf47b86337fafebdc",
gasUsed: 63385,
cumulativeGasUsed: 27466,
from: "0x34bb135d77771038a2fda3aa7cd5dc3fb4cc6abd",
gasUsed: 27466,
logs: [],
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
status: "0x1",
to: "0xccad3cb4b2a2cb917b2c6eb4025c78d4cadeb804",
transactionHash: "0x0bbe6ace1c23d13fb8b4604398c793591c62fd68e38f1752d1ad38153f939e5c",
logsBloom: "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000",
status: "0x0",
to: "0x05ea0f73204ea39d7231706a49c174a20380cfec",
transactionHash: "0xed05e610feae32bd51931b9d0068104dc60a9595590d17b73e1916c2288b0cf9",
transactionIndex: 0
}
# Check the BTCHeaders has one entry
> c.getBTCHeaders.call()
[1.295967676125722e+54]
> c.getBTCHeader.call(0)
1.295967676125722e+54
We could see when sending transaction using ``validatorAccount``, the transactions triggered ``storeHeader`` function successfully and emit log.
Log data ``0x00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d`` is returned hash of block header.
When sending transaction using ``normalAccount``, it could not pass ``validatorOnly()`` check and failed.
If you want to interact with BTCRelay contract, you could check our
`fetchd <https://github.com/CyberMiles/smart_contracts/tree/master/BTCRelay/fetchd>`_
as an example to fetch and store BTC headers.

0 comments on commit dd2463d

Please sign in to comment.