From 508f6fda49215630b1c19cff6906825bb8301e10 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 4 Jun 2018 14:56:11 +0100 Subject: [PATCH 001/203] Ion Stage 2 Branch Init --- Makefile | 55 -- README.md | 192 ------- __main__.py | 3 - abi/ERC223.abi | 1 - abi/IonLink.abi | 1 - abi/IonLock.abi | 1 - abi/Token.abi | 1 - contracts/ERC223.sol | 15 - contracts/ERC223Compatible.sol | 9 - contracts/IonCompatible.sol | 19 - contracts/IonLink.sol | 100 ---- contracts/IonLock.sol | 88 ---- contracts/Token.sol | 103 ---- docs/Roadmap.md | 108 ++++ example.sh | 60 --- ion/Ion.py | 297 ----------- ion/__init__.py | 0 ion/__main__.py | 11 - ion/args.py | 63 --- ion/crypto.py | 85 --- ion/ethrpc.py | 938 --------------------------------- ion/lithium/__init__.py | 0 ion/lithium/api.py | 141 ----- ion/lithium/lithium.py | 250 --------- ion/merkle.py | 133 ----- ion/utils.py | 117 ---- requirements.txt | 19 - setup.py | 16 - test/integration.py | 191 ------- test/link.js | 88 ---- test/lock.js | 372 ------------- test/test_api.py | 135 ----- test/test_lithium.py | 159 ------ test/test_merkle.py | 118 ----- test/token.js | 47 -- 35 files changed, 108 insertions(+), 3828 deletions(-) delete mode 100644 Makefile delete mode 100644 __main__.py delete mode 100644 abi/ERC223.abi delete mode 100644 abi/IonLink.abi delete mode 100644 abi/IonLock.abi delete mode 100644 abi/Token.abi delete mode 100644 contracts/ERC223.sol delete mode 100644 contracts/ERC223Compatible.sol delete mode 100644 contracts/IonCompatible.sol delete mode 100644 contracts/IonLink.sol delete mode 100644 contracts/IonLock.sol delete mode 100644 contracts/Token.sol create mode 100644 docs/Roadmap.md delete mode 100755 example.sh delete mode 100644 ion/Ion.py delete mode 100644 ion/__init__.py delete mode 100644 ion/__main__.py delete mode 100644 ion/args.py delete mode 100644 ion/crypto.py delete mode 100644 ion/ethrpc.py delete mode 100644 ion/lithium/__init__.py delete mode 100644 ion/lithium/api.py delete mode 100644 ion/lithium/lithium.py delete mode 100644 ion/merkle.py delete mode 100644 ion/utils.py delete mode 100644 requirements.txt delete mode 100644 setup.py delete mode 100644 test/integration.py delete mode 100644 test/link.js delete mode 100644 test/lock.js delete mode 100644 test/test_api.py delete mode 100644 test/test_lithium.py delete mode 100644 test/test_merkle.py delete mode 100644 test/token.js diff --git a/Makefile b/Makefile deleted file mode 100644 index 67adfd7..0000000 --- a/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -SOLC=solc --optimize -PYTHON=python -GANACHE=./node_modules/.bin/ganache-cli -TRUFFLE=./node_modules/.bin/truffle - -build: - mkdir -p build - npm install - $(PYTHON) -mpip install -r requirements.txt - -docker-build: dist/ion - docker build --rm=true -t clearmatics/ion:latest -f Dockerfile.alpine-glibc . - -docker-run: - docker run --rm=true -ti clearmatics/ion:latest shell - -python-lint: - $(PYTHON) -mpylint ion/ - -solidity-lint: - npm run lint - -requirements: requirements.txt - $(PYTHON) -mpip install -r requirements.txt - -abi: - mkdir -p abi - -abi/%.abi: build/%.abi abi - cp $< $@ - -build/%.bin: contracts/%.sol - $(SOLC) -o build --asm --bin --overwrite --abi $< - -build/%.combined.bin: build/%.combined.sol - $(SOLC) -o build --asm --bin --overwrite --abi $< - -build/%.combined.sol: contracts/%.sol build - cat $< | sed -e 's/\bimport\(\b.*\);/#include \1/g' | cpp -Icontracts | sed -e 's/^#.*$$//g' > $@ - -clean: - rm -rf build chaindata dist - find . -name '*.pyc' -exec rm '{}' ';' - rm -rf *.pyc *.pdf *.egg-info - -testrpc: - npm run testrpca - -test-js: - npm run test - -test-unit: - $(PYTHON) -m unittest discover test/ - -test: test-unit test-js diff --git a/README.md b/README.md index 55c4297..df897b3 100644 --- a/README.md +++ b/README.md @@ -2,195 +2,3 @@ The Ion Interoperability Protocol provides mechanisms to perform atomic swaps and currency transfers across multiple turing-complete blockchains. - -Ion consists of 3 core smart contracts: -* IonLock: Escrow contract where funds are deposited to and withdrawn from -* IonLink: Maintains state of counter-blockchain and verifies withdrawals with merkle proofs -* ERC223 Token: A placeholder ERC223 Token to perform exchanges with. - -A tool called Lithium is an event relay used to facilitate to communication between the chains. Lithium forwards `IonLock` deposit events to the opposite chain's `IonLink` as a state update to inform of a party's escrowing of funds. - -Check out the [Wiki](https://github.com/clearmatics/ion/wiki) for more detailed explanations. - -## Cross-chain payment - -Cross-chain payment flow of two different tokens on their respective blockchains with Alice and Bob as the parties involved is as follows: - -Chain A: Alice's chain -Chain B: Bob's chain - -1. Alice Deposits to chain A IonLock -2. Wait for Lithium (Event Relay) to update chain B IonLink -3. Bob Deposits to chain B IonLock -4. Wait for Lithium (Event Relay) to update chain A IonLink -5. Alice withdraws from chain B IonLock with proof of her deposit on to chain A IonLock -6. Bob withdraws from chain A IonLock with proof of his deposit on to chain B IonLock -7. Both parties successfully withdraw and atomic swap is complete. - -Note that withdrawing is blocked for both chains until funds are deposited into the escrow of the opposite chain. - -### Caveats - -Currently notable flaws in the design: -* All funds deposited must be withdrawn at once -* The number of tokens deposited must also equal the funds attempting to be withdrawn i.e. 1:1 exchange -* Payment references are currently redundant as proofs submitted to verify a withdrawal are only used to prove that the party has deposited on the other chain and is not used to distinguish the funds to be withdrawn as noted in the first point. - -## Install and Test - -Install all the dependencies which need Node v9.0.0, NPM, and Python 2.7. Furthermore it is recommended to use a isolated Python environment with a tool such as `virtualenv`. - -``` -$ make build -``` - -### Testing - -Prior to running contract tests please launch an Ethereum client. A simple way to do this is through the `ganache-cli` or alternatively use the `npm run testrpca`. - -Test: -``` -$ make test -``` - -This will run both the Javascript tests for the smart contracts and the Python tests for the Lithium RPC relay. - -Additionally contributors to this project should use linting tools when making commits, for both solidity and python code. - -``` -$ make python-lint -$ make solidity-lint -``` - -## Setup - -To perform cross-chain payments, the contracts must be deployed on each chain. - -Deploy two testrpc networks, if necessary, in separate terminals: -``` -$ npm run testrpca -$ npm run testrpcb -``` - -Compile and deploy the contracts on to the relevant networks: -``` -$ npm run compile -$ npm run deploya -$ npm run deployb -``` - -## Tutorial - -The following tutorial describes how to perform token transfer between two accounts on separate blockchains. - -There is an example script that runs through a basic flow from start to finish that is designed to run on the testrpcs. -``` -$ ./example.sh -``` - -This tutorial leverages Ganache and Truffle but could easily be performed on other test networks. - -To perform cross-chain payments, the contracts must be deployed on each chain, which for the sake of simplicity the account and contract addresses are assumed to be the same on both chains. - -ALICE=0x22d491bde2303f2f43325b2108d26f1eaba1e32b - -BOB=0xffcf8fdee72ac11b5c542428b35eef5769c409f0 - -TOKEN=0x254dffcd3277c0b1660f6d42efbb754edababc2b - -IONLOCK=0xc89ce4735882c9f0f0fe26686c53074e09b0d550 - -IONLINK=0xcfeb869f69431e42cdb54a4f4f105c19c080a601 - -IP=127.0.0.1 - -PORT_A=8545 - -PORT_B=8546 - -API_PORT_A=8555 - -API_PORT_B=8556 - -It is recommended to use an isolated python environment. - -### Step 1: Deploy event listeners - -Launch `lithium` listener A: -``` -$ python -mion lithium --rpc-from $IP:$PORT_A --rpc-to $IP:$PORT_B --from-account $ALICE --to-account $BOB --lock $IONLOCK --link $IONLINK --api-port $API_PORT_A -``` -Launch `lithium` listener B: -``` -$ python -mion lithium --rpc-from $IP:$PORT_B --rpc-to $IP:$PORT_A --from-account $BOB --to-account $ALICE --lock $IONLOCK --link $IONLINK --api-port $API_PORT_B -``` - -### Step 2: Mint token on each chain - -Mint for Alice on chain A: -``` -$ python -mion ion mint --rpc $IP_A:$PORT_A --account $ACC_A --tkn $TOKEN_ADDR --value 5000 -$ Token minted. -$ New balance = 5000 -``` - -Mint for Bob on chain B: -``` -$ python -mion ion mint --rpc $IP_B:$PORT_B --account $ACC_B --tkn $TOKEN_ADDR --value 5000 -$ Token minted. -$ New balance = 5000 -``` - -### Step 3: Escrow funds and get proof on chain A - -Alice deposits to IonLock on chain A: -``` -$ python -mion ion deposit --rpc $IP_A:$PORT_A --account $ACC_A --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -$ Token transferred. -$ New balance = 0 -``` - -Alice finds her merkle proof on chain A: -``` -$ python -mion ion proof --lithium-port $((PORT_A + 10)) --account $ACC_A --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -$ Received proof: -$ Path 0 : 96504857948636356700030147503635580074187355628971816059136194586624797022097 -$ Path 1 : 94482339386605321136956967184442353585778610538212146199456190006347461027622 -$ Path 2 : 4063950032426277920165979059513600522532612014504803720221874727295772434160 -$ Latest IonLink block 72772631658565070356215801224320765885121569368220205553212543964032472153198 -``` - -### Step 4: Escrow funds and get proof on chain B - -Bob deposits to IonLock on chain B: -``` -$ python -mion ion deposit --rpc $IP_B:$PORT_B --account $ACC_B --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -$ Token transferred. -$ New balance = 0 -``` - -Bob finds his merkle proof on chain B: -``` -$ python -mion ion proof --lithium-port $((PORT_B + 10)) --account $ACC_B --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -$ Received proof: -$ Path 0 : 59798365828871537698849691593400364996559135249658580970523805101316187754033 -$ Path 1 : 91398783457376278236011129913922372139721274533348447063742181262540672449047 -$ Path 2 : 23390520989103446330618879673836571332049395218389607622791772153046182206533 -$ Latest IonLink block 20043025639256222802481390718671994518152666652712633686609639039181086747014 -``` - -### Step 5: Withdraw funds using proof on chain B - -Alice withdraws giving her proof and reference: -``` -$ python -mion ion withdraw --lithium-port $((PORT_B + 10)) --rpc $IP_A:$PORT_A --account $ACC_B --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -$ New balance = 5000 -``` - -### Step 6: Withdraw funds using proof on chain A - -Bob withdraws giving his proof and reference: -``` -$ python -mion ion withdraw --lithium-port $((PORT_A + 10)) --rpc $IP_B:$PORT_B --account $ACC_A --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -$ New balance = 5000 -``` diff --git a/__main__.py b/__main__.py deleted file mode 100644 index 8fc3f69..0000000 --- a/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -from ion.__main__ import commands -import Crypto.Hash.keccak -commands.main() diff --git a/abi/ERC223.abi b/abi/ERC223.abi deleted file mode 100644 index efc95c8..0000000 --- a/abi/ERC223.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"data","type":"bytes"}],"name":"Transfer","type":"event"}] \ No newline at end of file diff --git a/abi/IonLink.abi b/abi/IonLink.abi deleted file mode 100644 index 85dfa80..0000000 --- a/abi/IonLink.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"block_id","type":"uint256"}],"name":"GetRoot","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"block_id","type":"uint256"}],"name":"GetPrevious","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"in_state","type":"uint256[]"}],"name":"Update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"block_id","type":"uint256"},{"name":"leaf_hash","type":"uint256"},{"name":"proof","type":"uint256[]"}],"name":"Verify","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"block_id","type":"uint256"}],"name":"GetTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GetLatestBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"Destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"genesis","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"IonLinkUpdated","type":"event"}] \ No newline at end of file diff --git a/abi/IonLock.abi b/abi/IonLock.abi deleted file mode 100644 index 9295f9f..0000000 --- a/abi/IonLock.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"currency","type":"address"},{"name":"ion","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_recipient","type":"address"},{"indexed":false,"name":"_currency","type":"address"},{"indexed":true,"name":"value","type":"uint256"},{"indexed":true,"name":"ref","type":"bytes32"},{"indexed":false,"name":"data","type":"bytes"}],"name":"IonTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_recipient","type":"address"},{"indexed":false,"name":"_currency","type":"address"},{"indexed":true,"name":"value","type":"uint256"},{"indexed":true,"name":"ref","type":"bytes32"}],"name":"IonWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"value","type":"uint256"},{"indexed":true,"name":"ref","type":"bytes32"}],"name":"IonMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"value","type":"uint256"},{"indexed":true,"name":"ref","type":"bytes32"}],"name":"IonBurn","type":"event"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"tokenFallback","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"},{"name":"_ref","type":"bytes32"},{"name":"_block_id","type":"uint256"},{"name":"_proof","type":"uint256[]"}],"name":"Withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/abi/Token.abi b/abi/Token.abi deleted file mode 100644 index f67bd8e..0000000 --- a/abi/Token.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"rawTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"metadataTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"AccountTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"data","type":"bytes"}],"name":"Transfer","type":"event"}] \ No newline at end of file diff --git a/contracts/ERC223.sol b/contracts/ERC223.sol deleted file mode 100644 index d93f9a3..0000000 --- a/contracts/ERC223.sol +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -contract ERC223 { - uint public totalSupply; - - function balanceOf(address who) constant public returns (uint); - - function transfer(address to, uint value) public; - - function transfer(address to, uint value, bytes data) public; - - event Transfer(address indexed from, address indexed to, uint value, bytes data); -} diff --git a/contracts/ERC223Compatible.sol b/contracts/ERC223Compatible.sol deleted file mode 100644 index 1ccfac2..0000000 --- a/contracts/ERC223Compatible.sol +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -import "./ERC223.sol"; - -contract ERC223ReceivingContract { - function tokenFallback(address _from, uint _value, bytes _data) public; -} diff --git a/contracts/IonCompatible.sol b/contracts/IonCompatible.sol deleted file mode 100644 index d16ac04..0000000 --- a/contracts/IonCompatible.sol +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -contract IonLinkInterface { - function Verify(uint256 block_id, uint256 leaf_hash, uint256[] proof) - public view returns (bool); -} - - -contract IonCompatible { - event IonTransfer(address _recipient, address _currency, uint256 indexed value, bytes32 indexed ref, bytes data); - - event IonWithdraw(address _recipient, address _currency, uint256 indexed value, bytes32 indexed ref); - - event IonMint(uint256 value, bytes32 indexed ref); - - event IonBurn(uint256 value, bytes32 indexed ref); -} diff --git a/contracts/IonLink.sol b/contracts/IonLink.sol deleted file mode 100644 index 8e541c4..0000000 --- a/contracts/IonLink.sol +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -import "./Merkle.sol"; -import "./IonCompatible.sol"; - -contract IonLink is IonLinkInterface { - struct IonBlock { - uint256 root; - uint256 prev; - uint256 time; - } - - mapping(uint256 => IonBlock) internal m_blocks; - - uint256 public LatestBlock; - - address Owner; - - event IonLinkUpdated(); - - constructor ( uint256 genesis ) public { - Owner = msg.sender; - LatestBlock = genesis; - } - - - function Destroy () public { - require( msg.sender == Owner ); - - selfdestruct( msg.sender ); - } - - - function GetBlock( uint256 block_id ) internal - view returns (IonBlock storage) { - IonBlock storage blk = m_blocks[block_id]; - - return blk; - } - - - function GetTime( uint256 block_id ) - public view returns (uint256) { - return GetBlock(block_id).time; - } - - - function GetPrevious( uint256 block_id ) - public view returns (uint256) { - return GetBlock(block_id).prev; - } - - - function GetRoot( uint256 block_id ) public view returns (uint256) { - return GetBlock(block_id).root; - } - - function GetLatestBlock() public view returns (uint256) { - return LatestBlock; - } - - /** - * Supplies a sequence of merkle roots which create a hash-chain - * - * hash = H(hash, root) - */ - function Update( uint256[] in_state ) public { - require( in_state.length > 1 ); - - uint256 prev_hash = LatestBlock; - - for( uint256 i = 0; i < in_state.length; i++ ) { - uint256 block_hash = uint256(keccak256(prev_hash, in_state[i])); - - IonBlock storage blk = m_blocks[block_hash]; - - blk.root = in_state[i]; - - // Record state at time of block creation - blk.prev = prev_hash; - blk.time = block.timestamp; - - prev_hash = block_hash; - } - - LatestBlock = prev_hash; - - - emit IonLinkUpdated(); - } - - - function Verify( uint256 block_id, uint256 leaf_hash, uint256[] proof ) - public view returns (bool) { - - return Merkle.Verify( GetRoot(block_id), leaf_hash, proof ); - } -} diff --git a/contracts/IonLock.sol b/contracts/IonLock.sol deleted file mode 100644 index b82eb69..0000000 --- a/contracts/IonLock.sol +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -import "./ERC223Compatible.sol"; -import "./IonCompatible.sol"; - - -contract IonLock is ERC223ReceivingContract, IonCompatible{ - uint256 m_balance; - - ERC223 m_currency; - - IonLinkInterface m_ion; - - // Logs the unique references that have been submitted - mapping(bytes32 => bool) m_withdraws; - - // Keeps reference to latest block that transfer was performed on - uint256 public LatestBlock; - - constructor( ERC223 currency, IonLinkInterface ion ) public { - require( address(currency) != 0 ); - - m_ion = ion; - - m_currency = currency; - - LatestBlock = block.number; - } - - - /** - * When ERC223 tokens are sent to this contract it mints the - * equivalent value of its own currency and gives it to the - * sender using Ion. - * - * @param _from Who sent us the token - * @param _value Amount of tokens - * @param _data Arbitrary data, to be used as the payment reference - */ - function tokenFallback(address _from, uint _value, bytes _data) public { - require( msg.sender == address(m_currency) ); - - require( _value > 0 ); - - require( (m_balance + _value) > m_balance ); - - m_balance += _value; - - bytes32 ref = keccak256(_data); - - emit IonMint( _value, ref ); - - emit IonTransfer( _from, address(this), _value, ref, _data ); - - LatestBlock = block.number; - } - - - /** - * When given proof that a payment exists in a proof uploaded to IonLink - * it will allow the sender to withdraw tokens of the specified value. - * - * @param _value Amount of token to withdraw - * @param _ref Payment reference hash - * @param _block_id IonLink block ID - * @param _proof Merkle proof - */ - function Withdraw( uint256 _value, bytes32 _ref, uint256 _block_id, uint256[] _proof ) public { - require( false == m_withdraws[_ref] ); - - // Definition of leaf structure - uint256 leaf_hash = uint256(keccak256(msg.sender, m_currency, address(this), _value, _ref)); - - require( m_ion.Verify(_block_id, leaf_hash, _proof) ); - - m_withdraws[_ref] = true; - - require( (m_balance - _value) < _value ); - - m_balance -= _value; - - m_currency.transfer(msg.sender, _value); - - emit IonWithdraw(msg.sender, m_currency, _value, _ref); - } -} diff --git a/contracts/Token.sol b/contracts/Token.sol deleted file mode 100644 index 516a945..0000000 --- a/contracts/Token.sol +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -import "./ERC223Compatible.sol"; -import './SafeMath.sol'; - -/** - * @title Reference implementation of the ERC223 standard token. - */ -contract Token is ERC223 { - using SafeMath for uint256; - - mapping(address => uint256) balances; // List of user balances. - - event AccountTransfer(); - - constructor() public { - totalSupply = 0; - } - - - function mint(uint256 _value) public { - totalSupply = totalSupply.add(_value); - - balances[msg.sender] = balances[msg.sender].add(_value); - } - - - function burn(uint256 _value) public { - balances[msg.sender] = balances[msg.sender].sub(_value); - - totalSupply = totalSupply.sub(_value); - } - - function metadataTransfer(address _to, uint256 _value, bytes _data) public { - transfer(_to, _value, _data); - } - - function rawTransfer(address _to, uint256 _value) public { - transfer(_to, _value); - } - - /** - * @dev Transfer the specified amount of tokens to the specified address. - * Invokes the `tokenFallback` function if the recipient is a contract. - * The token transfer fails if the recipient is a contract - * but does not implement the `tokenFallback` function - * or the fallback function to receive funds. - * - * @param _to Receiver address. - * @param _value Amount of tokens that will be transferred. - * @param _data Transaction metadata. - */ - function transfer(address _to, uint256 _value, bytes _data) public { - balances[msg.sender] = balances[msg.sender].sub(_value); - balances[_to] = balances[_to].add(_value); - - // Standard function transfer similar to ERC20 transfer with no _data . - // Added due to backwards compatibility reasons . - uint256 codeLength; - - assembly { - // Retrieve the size of the code on target address, this needs assembly . - codeLength := extcodesize(_to) - } - - if(codeLength>0) { - ERC223ReceivingContract receiver = ERC223ReceivingContract(_to); - receiver.tokenFallback(msg.sender, _value, _data); - } else { - emit AccountTransfer(); - } - - emit Transfer(msg.sender, _to, _value, _data); - } - - - /** - * @dev Transfer the specified amount of tokens to the specified address. - * This function works the same with the previous one - * but doesn't contain `_data` param. - * Added due to backwards compatibility reasons. - * - * @param _to Receiver address. - * @param _value Amount of tokens that will be transferred. - */ - function transfer(address _to, uint256 _value) public { - bytes memory empty; - return transfer(_to, _value, empty); - } - - - /** - * @dev Returns balance of the `_owner`. - * - * @param _owner The address whose balance will be returned. - * @return balance Balance of the `_owner`. - */ - function balanceOf(address _owner) public view returns (uint256) { - return balances[_owner]; - } -} diff --git a/docs/Roadmap.md b/docs/Roadmap.md new file mode 100644 index 0000000..50f82af --- /dev/null +++ b/docs/Roadmap.md @@ -0,0 +1,108 @@ +# Ion Stage 2: Phase 1 Roadmap + +Ion Stage 2 separates the cross chain payment use case from the interoperability solution. Focus has moved away from pure atomic exchange of value across chains, towards a mechanism to prove state across chains. + +Given two blockchains A and B the state of B should be verifiable on A and vice-versa. To do this a smart-contract should be developed which effectively becomes a light client of the corresponding blockchain. This facilitates interoperability on a much larger scale than simply value transactions. + +However the cross chain payment still serves as an illustrative example of how the solution would work in a specific scenario, but it is not part of the core solution to be developed. The Ion Stage 2 relies on a smart contract that allows storing and verification of the state of another chain. The verification of blocks from a foreign blockchain on a native chain should leverage the underlying consensus of the chain that is to be passed. + +In Phase 1 we intend to tackle two different aspects: +* Storing and proving of state from a foreign chain +* Validation of passed foreign state + +We assume the context of the validator set is an existing known set of nodes that also engage in the consensus protocol of a foreign chain so as to ensure the validity of signed state. + +## Nomenclature +We define are a common set of terminology which will be used herein that have a specific meaning or context within the project. + +* Native Chain: Refers to the chain where active interaction is taking place. This is where state from the foreign chain will be sent to for persistence and be verified against. +* Foreign Chain: Refers to the chain whose state is being persisted. Signed data about blocks from this chain will be passed to the native chain and stored. + +The above naming scheme applies in the context of describing interaction flow in a one-way setting where state is passed from one chain to another. In more complex flow where both chains are actively interacted with, this naming convention may be omitted to reduce confusion. + +* Proof: Refers to merkle proof-like mechanisms to assert the existence of an item or event in a block or root hash +* Validation: Refers to the signing and verifying of signatures of a piece of data, usually the block hash/header of a foreign chain +* State: Refers to the data captured and transferred between chains that facilitates the ability to prove a state transition of another chain. This will consist of another chain's block header and block hash. + +## Targets +State-proving is our fundamental goal but we frame our use-case around performing a cross-chain PvP payment. Any programmable contract can interface with the Relay contract and we outline an initial example through our use-case of how this would be achieved. + +In order to perform a cross-chain PvP payment we must: + * Prove state of blockchain A on B + * Verify the signatures of block signatories from a different blockchain + * Settle a cross-chain transaction between two counterparties via the above mechanisms + * Provide well-documented interfaces to allow users to easily interact with the project + +### Assumptions +Listed here are the assumptions with which the project is being developed: + * Ethereum-based blockchain + * PBFT Consensus Protocol or other immediate-finality algorithms + * Permissioned network + * Validator set is known and assumed as correct + +## Project Planning +Ion stage 2 will be developed using agile methodologies, with weekly sprints. Note that the sprint objective will remain dynamic and should change as the project continues. + +### Sprint 1 - PoC Final Proposal Definition. +Date: 04.06.2018 - 08.06.2018 + +Description: +We aim to describe fully how the Phase 1 PoC would work, detailing in entirety the functionality of all smart-contracts to be developed. + +Output: + * Project specification. + +### Sprint 2 - Skeleton Implementation +Date: 11.06.2018 - 15.06.2018 + +Description: +It should be shown that it is indeed possible to prove the state of a foreign on a native chain and make assertions of that state. Separately it should be shown that the validators from foreign chain can be added to the native chain. Blocks submitted and validated on the foreign chain validated on the native chain using the signature of the foreign validator set. + +Output: + * Smart contract for state proof verification + * Tests for state proofs + * Smart contract for block validation + * Tests for block validation + +### Sprint 3 - Validation of Passed State +Date: 18.06.2018 - 22.06.2018 + +Description: +The two separate problems of validation and proofs should be integrated and a minimum smart-contract that allows the immediate validation of a submitted block be developed. + +Output: + * Single contract which allows state proof and block validation to be performed simultaneously + +### Sprint 4 - User Flow Development +Date: 25.06.2018 - 29.06.2018 + +Description: +Given the original user stories the smart contract should now contain minimum functions necessary to interact with the project. This should naturally be an extension of the previous week to smooth out the integration and interaction flows of the stack. + +Output: + * Smart contract should now have protection for edge-cases + * Addition of user permissioniong + * Automation of block generation + +### Sprint 5 - Tooling and Documentation +Date: 02.07.2018 - 06.07.2018 + +Description: +Develop the tooling and documentation necessary for users to clone the repository and run the base functions immediately. We should write enough API documentation to allow developers to immediately be able to interface their own interoperability contracts to the Relay contract. + +Output: + * CLI + * Tutorial + * Development Documentation + +### Sprint 6 - Testing and QA +Date: 09.07.2018 - 13.07.2018 + +Description: +Enhance testing to show attack resilience and any known vulnerabilities. + +Output: + * Complete test coverage + * Code Review + * Documentation of all possible vulnerabilities + diff --git a/example.sh b/example.sh deleted file mode 100755 index 9dc76fe..0000000 --- a/example.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash - -ACC_A=0x22d491bde2303f2f43325b2108d26f1eaba1e32b -ACC_B=0xffcf8fdee72ac11b5c542428b35eef5769c409f0 -TOKEN_ADDR=0x254dffcd3277c0b1660f6d42efbb754edababc2b -LOCK_ADDR=0xc89ce4735882c9f0f0fe26686c53074e09b0d550 -LINK_ADDR=0xcfeb869f69431e42cdb54a4f4f105c19c080a601 -PORT_A=8545 -PORT_B=8546 -IP_A=127.0.0.1 -IP_B=127.0.0.1 -API_PORT_A=8555 -API_PORT_B=8556 - -echo "==== Chain A ====" -echo "...Minting" -python -mion ion mint --rpc $IP_A:$PORT_A --account $ACC_A --tkn $TOKEN_ADDR --value 5000 -echo "" -echo "Press any key to proceed" -read enter - -echo "...Depositing" -python -mion ion deposit --rpc $IP_A:$PORT_A --account $ACC_A --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -echo "" -echo "Press any key to proceed" -read enter - -echo "...Fetching proof" -python -mion ion proof --lithium-port $API_PORT_A --account $ACC_A --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -echo "" -echo "Press any key to proceed" -read enter - -echo "==== Chain B ====" -echo "...Minting" -python -mion ion mint --rpc $IP_B:$PORT_B --account $ACC_B --tkn $TOKEN_ADDR --value 5000 -echo "" -echo "Press any key to proceed" -read enter - -echo "...Depositing" -python -mion ion deposit --rpc $IP_B:$PORT_B --account $ACC_B --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -echo "" -echo "Press any key to proceed" -read enter - -echo "...Fetching proof" -python -mion ion proof --lithium-port $API_PORT_B --account $ACC_B --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -echo "" -echo "Press any key to proceed" -read enter - -echo "==== Withdrawing from Chain A ====" -python -mion ion withdraw --lithium-port $API_PORT_B --rpc $IP_A:$PORT_A --account $ACC_B --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff -echo "" -echo "Press any key to proceed" -read enter - -echo "==== Withdrawing from Chain B ====" -python -mion ion withdraw --lithium-port $API_PORT_A --rpc $IP_B:$PORT_B --account $ACC_A --lock $LOCK_ADDR --tkn $TOKEN_ADDR --value 5000 --ref stuff diff --git a/ion/Ion.py b/ion/Ion.py deleted file mode 100644 index c8ee7db..0000000 --- a/ion/Ion.py +++ /dev/null @@ -1,297 +0,0 @@ -# Copyright (c) 2016-2018 Clearmatics Technologies Ltd -# SPDX-License-Identifier: LGPL-3.0+ -""" -Ion: command line tool to allow users to intereact with lithium -""" -from __future__ import print_function - -import click -import requests -import simplejson - -from ion.merkle import merkle_hash -from ethereum.utils import keccak -from .ethrpc import BadStatusCodeError, BadJsonError, BadResponseError, ConnectionError -from .args import arg_ethrpc, arg_bytes20, arg_lithium_api -PRIMITIVE = (int, long, float, str, bool) - -def rpc_call_with_exceptions(function, *args): - """ - Wraps RPC function calls with expected errors - """ - try: - result = function(*args) - if isinstance(result, PRIMITIVE): - return result - return True - except BadStatusCodeError as err: - print("Error with status code ", err.message) - except BadJsonError as err: - print("BadJson Error: ", err.message) - except BadResponseError as err: - print("BadResponseError: ", err.message) - except ConnectionError as err: - print("Connection Error: ", err.message) - - return False - - -@click.command(help="Mint Token. Mints tokens to target account") -@click.option('--rpc', callback=arg_ethrpc, metavar="ip:port", default='127.0.0.1:8545', help="Source Ethereum JSON-RPC server") -@click.option('--account', callback=arg_bytes20, metavar="0x...20", required=True, help="Target account of funds.") -@click.option('--tkn', callback=arg_bytes20, metavar="0x...20", required=True, help="Token contract address") -@click.option('--value', type=int, required=True, metavar="N", help="Value") -def mint(rpc, account, tkn, value): - """ - Mints specified number of token to address - :param rpc: ip:port of RPC endpoint - :param account: address of recipient of tokens - :param tkn: token contract address - :param value: amount of token to mint - :return: 0, address balance is printed to console - """ - token = rpc.proxy("abi/Token.abi", tkn, account) - - result = rpc_call_with_exceptions(token.mint, value) - if result: - print("Token minted.") - - result = rpc_call_with_exceptions(token.balanceOf, account) - if result is not None: - print("New balance =", result) - - return 0 - -@click.command(help="Balance check. Check token balance of target account") -@click.option('--rpc', callback=arg_ethrpc, metavar="ip:port", default='127.0.0.1:8545', help="Source Ethereum JSON-RPC server") -@click.option('--account', callback=arg_bytes20, metavar="0x...20", required=True, help="Account of balance check.") -@click.option('--tkn', callback=arg_bytes20, metavar="0x...20", required=True, help="Token contract address") -def balance(rpc, account, tkn): - """ - Returns token balance information for an address - :param rpc: ip:port of RPC endpoint - :param account: address to check balance of - :param tkn: token address of token contract currency of the balance check - :return: 0, result is printed to console as int - """ - token = rpc.proxy("abi/Token.abi", tkn, account) - - result = rpc_call_with_exceptions(token.balanceOf, account) - if result is not None: - print("Balance =", result) - - - return 0 - -@click.command(help="IonLock Deposit. Deposits funds to IonLock contract.") -@click.option('--rpc', callback=arg_ethrpc, metavar="ip:port", default='127.0.0.1:8545', help="Source Ethereum JSON-RPC server") -@click.option('--account', callback=arg_bytes20, metavar="0x...20", required=True, help="Source account of funds.") -@click.option('--lock', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLock contract address") -@click.option('--tkn', callback=arg_bytes20, metavar="0x...20", required=True, help="Token contract address") -@click.option('--value', type=int, required=True, metavar="N", help="Value") -@click.option('--ref', type=str, required=True, metavar="abcd", help="Some payment reference") -def ionlock_deposit(rpc, account, lock, tkn, value, ref): - """ - Deposits from an address to IonLock contract with reference - :param rpc: ip:port of RPC endpoint - :param account: address of source of funds for deposit - :param lock: IonLock contract address - :param tkn: token contract address - :param value: amount to deposit - :param ref: str, an arbitrary reference for the payment - :return: 0, result is printed to the console - """ - token = rpc.proxy("abi/Token.abi", tkn, account) - - result = rpc_call_with_exceptions(token.metadataTransfer, lock, value, ref) - if result: - print("Token transferred.") - - result = rpc_call_with_exceptions(token.balanceOf, account) - if result is not None: - print("New balance =", result) - - return 0 - -@click.command(help="IonLock Withdraw. Withdraws funds from IonLock contract.") -@click.option('--lithium-port', type=int, metavar="8555", required=True, help="Lithium API port") -@click.option('--rpc', callback=arg_ethrpc, metavar="ip:port", default='127.0.0.1:8545', help="Ethereum JSON-RPC server to withdraw funds from") -@click.option('--account', callback=arg_bytes20, metavar="0x...20", required=True, help="Beneficiary of funds.") -@click.option('--lock', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLock contract address") -@click.option('--tkn', callback=arg_bytes20, metavar="0x...20", required=True, help="Token contract address of chain to receive from") -@click.option('--value', type=int, required=True, metavar="N", help="Value") -@click.option('--ref', type=str, required=True, metavar="0x...20", help="Payment reference") -def ionlock_withdraw(lithium_port, rpc, account, lock, tkn, value, ref): - """ - Withdraws to an address from IonLock contract by supplying information from the deposit made on the opposite chain by the account attempting withdrawal - :param lithium_port: port of lithium api - :param rpc: ip:port of RPC endpoint to the chain that the withdrawal is being made from - :param account: address of recipient of withdrawal funds and also address that deposit on opposite chain was made under - :param lock: IonLock contract address (Currently only works if contract addresses on both chains are identical) - :param tkn: Token contract address (Currently only works if contract addresses on both chains are identical) - :param value: Amount to be withdrawn (Currently only works if value deposited on other chain is same as amount to be withdrawn) - :param ref: str, the payment reference used in the deposit on the opposite chain - :return: 0, results are printed to the console - """ - ionlock = rpc.proxy("abi/IonLock.abi", lock, account) - token = rpc.proxy("abi/Token.abi", tkn, account) - - joined_data = account.encode('hex') + tkn.encode('hex') + lock.encode('hex') + "{0:0{1}x}".format(value,64) + keccak.new(digest_bits=256).update(str(ref)).hexdigest() - api_url = 'http://127.0.0.1:' + str(lithium_port) - r = requests.post(api_url + "/api/blockid", json={'leaf': joined_data}) - - try: - blockid = r.json()['blockid'] - r = requests.post(api_url + "/api/proof", json={'leaf': joined_data, 'blockid': blockid}) - - path = r.json()['proof'] - path = [int(x) for x in path] - hashed_ref = keccak.new(digest_bits=256).update(str(ref)).hexdigest() - - result = rpc_call_with_exceptions(ionlock.Withdraw, value, hashed_ref.decode('hex'), int(blockid), path) - - result = rpc_call_with_exceptions(token.balanceOf, account) - if result is not None: - print("New balance =", result) - - - except simplejson.errors.JSONDecodeError as e: - print(e.message) - - return 0 - -@click.command(help="IonLink Verify. Checks the supplied proof with IonLink.") -@click.option('--lithium-port', type=int, metavar="8555", required=True, help="Lithium API port") -@click.option('--rpc', callback=arg_ethrpc, metavar="ip:port", required=True, help="Ethereum JSON-RPC server to verify against") -@click.option('--account', callback=arg_bytes20, metavar="0x...20", required=True, help="Beneficiary of funds.") -@click.option('--link', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLock contract address") -@click.option('--lock', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLock contract address of chain to receive from") -@click.option('--tkn', callback=arg_bytes20, metavar="0x...20", required=True, help="Token contract address of chain to receive from") -@click.option('--value', type=int, required=True, metavar="N", help="Value") -@click.option('--ref', type=str, required=True, metavar="abcd", help="Payment reference") -def ionlink_verify(lithium_port, rpc, account, link, lock, tkn, value, ref): - """ - Verifies a supplied merkle leaf of a deposit with a path against the merkle root held by IonLink - Deposit chain: chain that deposit was made on - Verification chain: chain that has been updated with merkle roots that is being verified against - :param lithium_port: port of lithium api - :param rpc: ip:port of RPC endpoint to Verification chain - :param account: address that deposit was made by - :param link: IonLink contact address on Verification chain - :param lock: IonLock contract address on Deposit chain - :param tkn: Token contract address on Deposit chain - :param value: amount deposited - :param ref: str, reference used in the deposit - :return: 0, results are printed to console - """ - ionlink = rpc.proxy("abi/IonLink.abi", link, account) - - joined_data = account.encode('hex') + tkn.encode('hex') + lock.encode('hex') + "{0:0{1}x}".format(value,64) + keccak.new(digest_bits=256).update(str(ref)).hexdigest() - hashed_data = merkle_hash(int(joined_data, 16)) - api_url = 'http://127.0.0.1:' + str(lithium_port) - r = requests.post(api_url + "/api/blockid", json={'leaf': joined_data}) - - try: - blockid = r.json()['blockid'] - r = requests.post(api_url + "/api/proof", json={'leaf': joined_data, 'blockid': blockid}) - - path = r.json()['proof'] - path = [int(x) for x in path] - - r = requests.post(api_url + "/api/verify", json={'leaf': joined_data, 'proof': path, 'blockid': blockid}) - print("Lithium proof:") - print(r.text) - - print("IonLink Proof at block id", blockid) - result = rpc_call_with_exceptions(ionlink.Verify, int(blockid), hashed_data, path) - print(result) - - except simplejson.errors.JSONDecodeError as e: - print(e.message) - - return 0 - - - -@click.command(help="Merkle proof. Acquires the merkle path to a leaf in Lithium merkle tree for submission during withdraw.") -@click.option('--lithium-port', type=int, metavar="8555", required=True, help="Lithium API port") -@click.option('--account', callback=arg_bytes20, metavar="0x...20", required=True, help="Sender of funds.") -@click.option('--lock', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLock contract address of chain to receive from") -@click.option('--tkn', callback=arg_bytes20, metavar="0x...20", required=True, help="Token contract address of chain to receive from") -@click.option('--value', type=int, required=True, metavar="N", help="Value") -@click.option('--ref', type=str, required=True, metavar="abcd", help="Payment reference") -def merkle_proof_path(lithium_port, account, lock, tkn, value, ref): - """ - Generates a merkle path to a leaf corresponding to a deposit made - :param lithium_port: port of lithium api - :param account: address that deposit was made by - :param lock: IonLock contract address where deposit was made to - :param tkn: Token contract address of token deposited - :param value: amount of token deposited - :param ref: str, reference used for the deposit - :return: 0, merkle path is printed to the console - """ - joined_data = account.encode('hex') + tkn.encode('hex') + lock.encode('hex') + "{0:0{1}x}".format(value,64) + keccak.new(digest_bits=256).update(str(ref)).hexdigest() - api_url = 'http://127.0.0.1:' + str(lithium_port) - r = requests.post(api_url + "/api/blockid", json={'leaf': joined_data}) - - try: - blockid = r.json()['blockid'] - r = requests.post(api_url + "/api/proof", json={'leaf': joined_data, 'blockid':blockid}) - - print("Received proof:") - [print("Path ", r.json()['proof'].index(x), " : ", x) for x in r.json()['proof']] - - print("Latest IonLink block",blockid) - - except simplejson.errors.JSONDecodeError as e: - print(e.message) - - return 0 - -@click.command(help="Merkle Verify. Verifies proof with Lithium merkle tree.") -@click.argument('proof', nargs=-1) -@click.option('--lithium-port', type=int, metavar="8555", required=True, help="Lithium API port") -@click.option('--account', callback=arg_bytes20, metavar="0x...20", required=True, help="Sender of funds.") -@click.option('--lock', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLock contract address of chain to receive from") -@click.option('--tkn', callback=arg_bytes20, metavar="0x...20", required=True, help="Token contract address of chain to receive from") -@click.option('--value', type=int, required=True, metavar="N", help="Value") -@click.option('--ref', type=str, required=True, metavar="abcd", help="Payment reference") -def merkle_verify(proof, lithium_port, account, lock, tkn, value, ref): - """ - Verifies a supplied merkle path with a leaf corresponding to a deposit made to the merkle tree held by Lithium - :param proof: space-separated list of hashes as decimal of the path to the leaf - :param lithium_port: port of lithium api - :param account: address that deposit was made by - :param lock: IonLock contract address where deposit was made to - :param tkn: Token contract address of token deposited - :param value: amount of token deposited - :param ref: str, reference used for the deposit - :return: 0, result is printed to the console - """ - joined_data = account.encode('hex') + tkn.encode('hex') + lock.encode('hex') + "{0:0{1}x}".format(value,64) + keccak.new(digest_bits=256).update(str(ref)).hexdigest() - proof = [int(x) for x in proof] - api_url = 'http://127.0.0.1:' + str(lithium_port) - r = requests.post(api_url + "/api/blockid", json={'leaf': joined_data}) - - try: - blockid = r.json()['blockid'] - r = requests.post(api_url + "/api/verify", json={'leaf': joined_data, 'proof': proof, 'blockid':blockid}) - print("Received proof:") - print(r.text) - - except simplejson.errors.JSONDecodeError as e: - print(e.message) - - return 0 - - - -commands = click.Group('commands', help="Ion Interface") -commands.add_command(mint, "mint") -commands.add_command(balance, "balance") -commands.add_command(ionlock_deposit, "deposit") -commands.add_command(ionlock_withdraw, "withdraw") -commands.add_command(ionlink_verify, "ionlink_verify") -commands.add_command(merkle_proof_path, "proof") -commands.add_command(merkle_verify, "verify") diff --git a/ion/__init__.py b/ion/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ion/__main__.py b/ion/__main__.py deleted file mode 100644 index ad5d030..0000000 --- a/ion/__main__.py +++ /dev/null @@ -1,11 +0,0 @@ -import click - -from Ion import commands as ion_commands -from ion.lithium.lithium import etheventrelay as lithium - -commands = click.Group('commands') -commands.add_command(ion_commands, "ion") -commands.add_command(lithium, "lithium") - -if __name__ == "__main__": - commands.main() diff --git a/ion/args.py b/ion/args.py deleted file mode 100644 index 64066ed..0000000 --- a/ion/args.py +++ /dev/null @@ -1,63 +0,0 @@ -## Copyright (c) 2016-2018 Clearmatics Technologies Ltd -## SPDX-License-Identifier: LGPL-3.0+ - -#!/usr/bin/env python -""" -Provides a set of useful arguements for interacting with ethrpc -""" -from .ethrpc import EthJsonRpc -from .utils import require, scan_bin - - -def arg_bytes(ctx, param, value): - if value is None: - return None - value = scan_bin(value) - return value - -def make_bytes_n(num_bytes): - def arg_bytes_n(ctx, param, value): - value = arg_bytes(ctx, param, value) - if value is None: - return None - require(len(value) == num_bytes, str(num_bytes) + " bytes required") - return value - return arg_bytes_n - - -arg_bytes20 = make_bytes_n(20) -arg_bytes32 = make_bytes_n(32) - - -def make_uint_n(num): - def arg_uint_n(ctx, param, value): - if value is None: - return None - value = int(value) - require(value >= 0) - require(value <= (1 << (num-1))) - return value - return arg_uint_n - -arg_uint256 = make_uint_n(256) - - -def arg_ethrpc(ctx, param, value): - if value is None: - return None - ip_addr, port = value.split(':') - port = int(port) - require(port > 0) - require(port < 0xFFFF) - if port == 443: - return EthJsonRpc(ip_addr, port, True) - return EthJsonRpc(ip_addr, port) - -def arg_lithium_api(ctx, param, value): - if value is None: - return None - ip_addr, port = value.split(':') - port = int(port) - require(port > 0) - require(port < 0xFFFF) - return {'ip_addr': ip_addr, 'port': port} diff --git a/ion/crypto.py b/ion/crypto.py deleted file mode 100644 index 4f5307d..0000000 --- a/ion/crypto.py +++ /dev/null @@ -1,85 +0,0 @@ -## Copyright (c) 2016-2018 Clearmatics Technologies Ltd -## SPDX-License-Identifier: LGPL-3.0+ - -#!/usr/bin/env python -""" -Crypto: Has a load of useful crypto stuff -""" -from collections import namedtuple - -from ethereum.utils import big_endian_to_int, encode_int32 -from rlp.utils_py2 import ascii_chr - -from sha3 import keccak_256 - -from utils import Marshalled, u256be, safe_ord - -try: - import coincurve -except ImportError: - from py_ecc.secp256k1 import ecdsa_raw_recover, ecdsa_raw_sign - import warnings - warnings.warn('could not import coincurve', ImportWarning) - coincurve = None - - -# -------------------------------------------------------------------- -# Datatypes - - -_EcdsaSignatureStruct = namedtuple('EcdsaSignature', ('v', 'r', 's')) - - -class EcdsaSignature(_EcdsaSignatureStruct, Marshalled): - def __init__(self, *args, **kwa): - _EcdsaSignatureStruct.__init__(*args, **kwa) - - def dump(self): - # TODO: make same format as coincurve 65 byte str - return ''.join([chr(self.v), self.r, self.s]) - - def recover(self, rawhash): - assert isinstance(self, EcdsaSignature) - v, r, s = self - if coincurve and hasattr(coincurve, "PublicKey"): - try: - pk = coincurve.PublicKey.from_signature_and_message( - ''.join([r, s, ascii_chr(v - 27)]), - rawhash, - hasher=None, - ) - pub = pk.format(compressed=False)[1:] - except BaseException: - pub = b"\x00" * 64 - else: - r = big_endian_to_int(r) - s = big_endian_to_int(s) - result = ecdsa_raw_recover(rawhash, (v, r, s)) - if result: - x, y = result - pub = encode_int32(x) + encode_int32(y) - else: - raise ValueError('Invalid VRS') - assert len(pub) == 64 - - # Convert to Ethereum address - return keccak_256(pub).digest()[12:] - - -# -------------------------------------------------------------------- -# ECDSA signature and address recovery - - -def ecdsa_sign(rawhash, key): - # type: (bytes, bytes) -> EcdsaSignature - if coincurve and hasattr(coincurve, 'PrivateKey'): - pk = coincurve.PrivateKey(key) - signature = pk.sign_recoverable(rawhash, hasher=None) - v = safe_ord(signature[64]) + 27 - r = signature[0:32] - s = signature[32:64] - else: - v, r, s = ecdsa_raw_sign(rawhash, key) - r = u256be(r) - s = u256be(s) - return EcdsaSignature(v, r, s) diff --git a/ion/ethrpc.py b/ion/ethrpc.py deleted file mode 100644 index 497b61a..0000000 --- a/ion/ethrpc.py +++ /dev/null @@ -1,938 +0,0 @@ -""" -For licensing information, see: - -https://github.com/ConsenSys/ethjsonrpc/blob/master/LICENSE - -This file contains the public domain interface definition -""" - -import json -import requests -import time -import warnings -from collections import namedtuple -from ethereum.abi import encode_abi, decode_abi -from requests.adapters import HTTPAdapter -from requests.exceptions import ConnectionError as RequestsConnectionError - -from .crypto import keccak_256 -from .utils import require, big_endian_to_int, zpad, encode_int - -GETH_DEFAULT_RPC_PORT = 8545 -ETH_DEFAULT_RPC_PORT = 8545 -PARITY_DEFAULT_RPC_PORT = 8545 -PYETHAPP_DEFAULT_RPC_PORT = 4000 -MAX_RETRIES = 3 -JSON_MEDIA_TYPE = 'application/json' - - -BLOCK_TAG_EARLIEST = 'earliest' -BLOCK_TAG_LATEST = 'latest' -BLOCK_TAG_PENDING = 'pending' -BLOCK_TAGS = ( - BLOCK_TAG_EARLIEST, - BLOCK_TAG_LATEST, - BLOCK_TAG_PENDING, -) - - -class EthJsonRpcError(Exception): - pass - - -class ConnectionError(EthJsonRpcError): - pass - - -class BadStatusCodeError(EthJsonRpcError): - pass - - -class BadJsonError(EthJsonRpcError): - pass - - -class BadResponseError(EthJsonRpcError): - pass - - - - -def hex_to_dec(x): - ''' - Convert hex to decimal - ''' - return int(x, 16) - - -def clean_hex(d): - ''' - Convert decimal to hex and remove the "L" suffix that is appended to large - numbers - ''' - return hex(d).rstrip('L') - -def validate_block(block): - if isinstance(block, basestring): - if block not in BLOCK_TAGS: - raise ValueError('invalid block tag') - if isinstance(block, int): - block = hex(block) - return block - - -def wei_to_ether(wei): - ''' - Convert wei to ether - ''' - return 1.0 * wei / 10**18 - - -def ether_to_wei(ether): - ''' - Convert ether to wei - ''' - return ether * 10**18 - - -class EthTransaction(namedtuple('_TxStruct', ('rpc', 'txid'))): - def receipt(self, wait=False, tick_fn=None): - first = True - while True: - receipt = self.rpc.eth_getTransactionReceipt(self.txid) - # TODO: turn into asynchronous notification / future - if receipt: - return receipt - if not wait: - break - try: - if first: - if isinstance(wait, callable): - wait() - first = False - elif tick_fn: - tick_fn(self) - time.sleep(1) - except KeyboardInterrupt: - break - - def __str__(self): - return self.txid - - -class EthJsonRpc(object): - ''' - Ethereum JSON-RPC client class - ''' - - DEFAULT_GAS_PER_TX = 900000 - DEFAULT_GAS_PRICE = 50 * 10**9 # 50 gwei - - def __init__(self, host='localhost', port=GETH_DEFAULT_RPC_PORT, tls=False): - self.host = host - self.port = port - self.tls = tls - self.session = requests.Session() - self.session.mount(self.host, HTTPAdapter(max_retries=MAX_RETRIES)) - - def _call(self, method, params=None, _id=1): - - params = params or [] - data = { - 'jsonrpc': '2.0', - 'method': method, - 'params': params, - 'id': _id, - } - scheme = 'http' - if self.tls: - scheme += 's' - url = '{}://{}:{}'.format(scheme, self.host, self.port) - headers = {'Content-Type': JSON_MEDIA_TYPE} - try: - r = self.session.post(url, headers=headers, data=json.dumps(data)) - except RequestsConnectionError: - raise ConnectionError(url) - if r.status_code / 100 != 2: - raise BadStatusCodeError(r.status_code) - try: - response = r.json() - except ValueError: - raise BadJsonError(r.text) - try: - return response['result'] - except KeyError: - raise BadResponseError(response) - - def _encode_function(self, signature, param_values): - - prefix = big_endian_to_int(keccak_256(signature.encode('utf-8')).digest()[:4]) - - if signature.find('(') == -1: - raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...') - - if signature.find(')') - signature.find('(') == 1: - return encode_int(prefix) - - types = signature[signature.find('(') + 1: signature.find(')')].split(',') - encoded_params = encode_abi(types, param_values) - return zpad(encode_int(prefix), 4) + encoded_params - - def _solproxy_bind(self, method, address, account): - ins = [_['type'] for _ in method['inputs']] - outs = [_['type'] for _ in method['outputs']] - sig = method['name'] + '(' + ','.join(ins) + ')' - # XXX: messy... - if method['constant']: - return lambda *args, **kwa: (self.call(address, sig, args, outs, **kwa) - if len(outs) > 1 else - self.call(address, sig, args, outs, **kwa)[0]) - if account is None: - # Without account, cannot call non-constant methods - return None - return lambda *args, **kwa: (self.call_with_transaction(account, address, sig, args, **kwa) - if len(outs) > 1 else - self.call_with_transaction(account, address, sig, args, **kwa)[0]) - - def proxy(self, abi, address, account=None): - # XXX: specific to Ethereum addresses, 20 octets - if len(address) == 20: - address = address.encode('hex') - require(len(address) == 40) - if account is not None: - if len(account) == 20: - account = account.encode('hex') - require(len(account) == 40) - - if isinstance(abi, file): - abi = json.load(abi) - elif isinstance(abi, str): - with open(abi) as jsonfile: - abi = json.load(jsonfile) - require(isinstance(abi, list)) - - proxy = dict() - for method in abi: - if method['type'] != 'function': - continue - - handler = self._solproxy_bind(method, address, account) - if handler is None: - continue - - sig = "%s(%s)" % (method['name'], ','.join([i['type'] for i in method['inputs']])) - sig_hash = keccak_256(bytes(sig)).hexdigest()[:8] - - # Provide an alternate, where the explicit function signature - proxy[method['name']] = handler - proxy[method['name'] + '_' + sig_hash] = handler - - return namedtuple('SolProxy', proxy.keys())(*proxy.values()) - -################################################################################ -# high-level methods -################################################################################ - - def transfer(self, from_, to, amount): - ''' - Send wei from one address to another - ''' - return self.eth_sendTransaction(from_address=from_, to_address=to, value=amount) - - def create_contract(self, from_, code, gas, sig=None, args=None): - ''' - Create a contract on the blockchain from compiled EVM code. Returns the - transaction hash. - ''' - from_ = from_ or self.eth_coinbase() - if sig is not None and args is not None: - types = sig[sig.find('(') + 1: sig.find(')')].split(',') - encoded_params = encode_abi(types, args) - code += encoded_params.encode('hex') - return self.eth_sendTransaction(from_address=from_, gas=gas, data=code) - - def get_contract_address(self, tx): - ''' - Get the address for a contract from the transaction that created it - ''' - receipt = self.eth_getTransactionReceipt(tx) - return receipt['contractAddress'] - - def call(self, address, sig, args, result_types): - ''' - Call a contract function on the RPC server, without sending a - transaction (useful for reading data) - ''' - data = self._encode_function(sig, args) - data_hex = data.encode('hex') - response = self.eth_call(to_address=address, data=data_hex) - # XXX: horrible hack for when RPC returns '0x0'... - if (len(result_types) == 0 or result_types[0] == 'uint256') and response == '0x0': - response = '0x' + ('0' * 64) - return decode_abi(result_types, response[2:].decode('hex')) - - def call_with_transaction(self, from_, address, sig, args, gas=None, gas_price=None, value=None): - ''' - Call a contract function by sending a transaction (useful for storing - data) - ''' - gas = gas or self.DEFAULT_GAS_PER_TX - gas_price = gas_price or self.DEFAULT_GAS_PRICE - data = self._encode_function(sig, args) - data_hex = data.encode('hex') - return self.eth_sendTransaction(from_address=from_, to_address=address, data=data_hex, gas=gas, - gas_price=gas_price, value=value) - -################################################################################ -# JSON-RPC methods -################################################################################ - - def web3_clientVersion(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_clientversion - - TESTED - ''' - return self._call('web3_clientVersion') - - def web3_sha3(self, data): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3 - - TESTED - ''' - data = str(data).encode('hex') - return self._call('web3_sha3', [data]) - - def net_version(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version - - TESTED - ''' - return self._call('net_version') - - def net_listening(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening - - TESTED - ''' - return self._call('net_listening') - - def net_peerCount(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peercount - - TESTED - ''' - return hex_to_dec(self._call('net_peerCount')) - - def eth_protocolVersion(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolversion - - TESTED - ''' - return self._call('eth_protocolVersion') - - def eth_syncing(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_syncing - - TESTED - ''' - return self._call('eth_syncing') - - def eth_coinbase(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase - - TESTED - ''' - return self._call('eth_coinbase') - - def eth_mining(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining - - TESTED - ''' - return self._call('eth_mining') - - def eth_hashrate(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate - - TESTED - ''' - return hex_to_dec(self._call('eth_hashrate')) - - def eth_gasPrice(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasprice - - TESTED - ''' - return hex_to_dec(self._call('eth_gasPrice')) - - def eth_accounts(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts - - TESTED - ''' - return self._call('eth_accounts') - - def eth_blockNumber(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber - - TESTED - ''' - return hex_to_dec(self._call('eth_blockNumber')) - - def eth_getBalance(self, address=None, block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance - - TESTED - ''' - address = address or self.eth_coinbase() - block = validate_block(block) - return hex_to_dec(self._call('eth_getBalance', [address, block])) - - def eth_getStorageAt(self, address=None, position=0, block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat - - TESTED - ''' - block = validate_block(block) - return self._call('eth_getStorageAt', [address, hex(position), block]) - - def eth_getTransactionCount(self, address, block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount - - TESTED - ''' - block = validate_block(block) - return hex_to_dec(self._call('eth_getTransactionCount', [address, block])) - - def eth_getBlockTransactionCountByHash(self, block_hash): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbyhash - - TESTED - ''' - return hex_to_dec(self._call('eth_getBlockTransactionCountByHash', [block_hash])) - - def eth_getBlockTransactionCountByNumber(self, block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbynumber - - TESTED - ''' - block = validate_block(block) - return hex_to_dec(self._call('eth_getBlockTransactionCountByNumber', [block])) - - def eth_getUncleCountByBlockHash(self, block_hash): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblockhash - - TESTED - ''' - return hex_to_dec(self._call('eth_getUncleCountByBlockHash', [block_hash])) - - def eth_getUncleCountByBlockNumber(self, block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblocknumber - - TESTED - ''' - block = validate_block(block) - return hex_to_dec(self._call('eth_getUncleCountByBlockNumber', [block])) - - def eth_getCode(self, address, default_block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode - - NEEDS TESTING - ''' - if isinstance(default_block, basestring): - if default_block not in BLOCK_TAGS: - raise ValueError - return self._call('eth_getCode', [address, default_block]) - - def eth_sign(self, address, data): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign - - NEEDS TESTING - ''' - return self._call('eth_sign', [address, data]) - - def eth_sendTransaction(self, to_address=None, from_address=None, gas=None, gas_price=None, value=None, data=None, - nonce=None): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction - - NEEDS TESTING - ''' - if len(to_address) == 20: - to_address = to_address.encode('hex') - if len(from_address) == 20: - from_address = from_address.encode('hex') - params = {} - params['from'] = from_address or self.eth_coinbase() - if to_address is not None: - params['to'] = to_address - if gas is not None: - params['gas'] = hex(gas) - if gas_price is not None: - params['gasPrice'] = clean_hex(gas_price) - if value is not None: - params['value'] = clean_hex(value) - if data is not None: - params['data'] = data - if nonce is not None: - params['nonce'] = hex(nonce) - txid = self._call('eth_sendTransaction', [params]) - return EthTransaction(self, txid) - - def eth_sendRawTransaction(self, data): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendrawtransaction - - NEEDS TESTING - ''' - return self._call('eth_sendRawTransaction', [data]) - - def eth_call(self, to_address, from_address=None, gas=None, gas_price=None, value=None, data=None, - default_block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call - - NEEDS TESTING - ''' - if isinstance(default_block, basestring): - if default_block not in BLOCK_TAGS: - raise ValueError - if from_address is not None and len(from_address) == 20: - from_address = from_address.encode('hex') - if len(to_address) == 20: - to_address = to_address.encode('hex') - obj = {} - obj['to'] = to_address - if from_address is not None: - obj['from'] = from_address - if gas is not None: - obj['gas'] = hex(gas) - if gas_price is not None: - obj['gasPrice'] = clean_hex(gas_price) - if value is not None: - obj['value'] = value - if data is not None: - obj['data'] = data - return self._call('eth_call', [obj, default_block]) - - def eth_estimateGas(self, to_address=None, from_address=None, gas=None, gas_price=None, value=None, data=None, - default_block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas - - NEEDS TESTING - ''' - if isinstance(default_block, basestring): - if default_block not in BLOCK_TAGS: - raise ValueError - obj = {} - if to_address is not None: - obj['to'] = to_address - if from_address is not None: - obj['from'] = from_address - if gas is not None: - obj['gas'] = hex(gas) - if gas_price is not None: - obj['gasPrice'] = clean_hex(gas_price) - if value is not None: - obj['value'] = value - if data is not None: - obj['data'] = data - return hex_to_dec(self._call('eth_estimateGas', [obj, default_block])) - - def eth_getBlockByHash(self, block_hash, tx_objects=True): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash - - TESTED - ''' - return self._call('eth_getBlockByHash', [block_hash, tx_objects]) - - def eth_getBlockByNumber(self, block=BLOCK_TAG_LATEST, tx_objects=True): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber - - TESTED - ''' - block = validate_block(block) - return self._call('eth_getBlockByNumber', [block, tx_objects]) - - def eth_getTransactionByHash(self, tx_hash): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash - - TESTED - ''' - return self._call('eth_getTransactionByHash', [tx_hash]) - - def eth_getTransactionByBlockHashAndIndex(self, block_hash, index=0): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblockhashandindex - - TESTED - ''' - return self._call('eth_getTransactionByBlockHashAndIndex', [block_hash, hex(index)]) - - def eth_getTransactionByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblocknumberandindex - - TESTED - ''' - block = validate_block(block) - return self._call('eth_getTransactionByBlockNumberAndIndex', [block, hex(index)]) - - def eth_getTransactionReceipt(self, tx_hash): - # type: (string) -> dict - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt - - TESTED - ''' - return self._call('eth_getTransactionReceipt', [str(tx_hash)]) - - def eth_getUncleByBlockHashAndIndex(self, block_hash, index=0): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblockhashandindex - - TESTED - ''' - return self._call('eth_getUncleByBlockHashAndIndex', [block_hash, hex(index)]) - - def eth_getUncleByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblocknumberandindex - - TESTED - ''' - block = validate_block(block) - return self._call('eth_getUncleByBlockNumberAndIndex', [block, hex(index)]) - - def eth_getCompilers(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcompilers - - TESTED - ''' - return self._call('eth_getCompilers') - - def eth_compileSolidity(self, code): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilesolidity - - TESTED - ''' - return self._call('eth_compileSolidity', [code]) - - def eth_compileLLL(self, code): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilelll - - N/A - ''' - return self._call('eth_compileLLL', [code]) - - def eth_compileSerpent(self, code): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compileserpent - - N/A - ''' - return self._call('eth_compileSerpent', [code]) - - def eth_newFilter(self, from_block=BLOCK_TAG_LATEST, to_block=BLOCK_TAG_LATEST, address=None, topics=None): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter - - NEEDS TESTING - ''' - _filter = { - 'fromBlock': from_block, - 'toBlock': to_block, - 'address': address, - 'topics': topics, - } - return self._call('eth_newFilter', [_filter]) - - def eth_newBlockFilter(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter - - TESTED - ''' - return self._call('eth_newBlockFilter') - - def eth_newPendingTransactionFilter(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter - - TESTED - ''' - return hex_to_dec(self._call('eth_newPendingTransactionFilter')) - - def eth_uninstallFilter(self, filter_id): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter - - NEEDS TESTING - ''' - return self._call('eth_uninstallFilter', [filter_id]) - - def eth_getFilterChanges(self, filter_id): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges - - NEEDS TESTING - ''' - return self._call('eth_getFilterChanges', [filter_id]) - - def eth_getFilterLogs(self, filter_id): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs - - NEEDS TESTING - ''' - return self._call('eth_getFilterLogs', [filter_id]) - - def eth_getLogs(self, filter_object): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs - - NEEDS TESTING - ''' - return self._call('eth_getLogs', [filter_object]) - - def eth_getWork(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getwork - - TESTED - ''' - return self._call('eth_getWork') - - def eth_submitWork(self, nonce, header, mix_digest): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submitwork - - NEEDS TESTING - ''' - return self._call('eth_submitWork', [nonce, header, mix_digest]) - - def eth_submitHashrate(self, hash_rate, client_id): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submithashrate - - TESTED - ''' - return self._call('eth_submitHashrate', [hex(hash_rate), client_id]) - - def db_putString(self, db_name, key, value): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#db_putstring - - TESTED - ''' - warnings.warn('deprecated', DeprecationWarning) - return self._call('db_putString', [db_name, key, value]) - - def db_getString(self, db_name, key): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#db_getstring - - TESTED - ''' - warnings.warn('deprecated', DeprecationWarning) - return self._call('db_getString', [db_name, key]) - - def db_putHex(self, db_name, key, value): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#db_puthex - - TESTED - ''' - if not value.startswith('0x'): - value = '0x{}'.format(value) - warnings.warn('deprecated', DeprecationWarning) - return self._call('db_putHex', [db_name, key, value]) - - def db_getHex(self, db_name, key): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#db_gethex - - TESTED - ''' - warnings.warn('deprecated', DeprecationWarning) - return self._call('db_getHex', [db_name, key]) - - def shh_version(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version - - N/A - ''' - return self._call('shh_version') - - def shh_post(self, topics, payload, priority, ttl, from_=None, to=None): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post - - NEEDS TESTING - ''' - whisper_object = { - 'from': from_, - 'to': to, - 'topics': topics, - 'payload': payload, - 'priority': hex(priority), - 'ttl': hex(ttl), - } - return self._call('shh_post', [whisper_object]) - - def shh_newIdentity(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newidentity - - N/A - ''' - return self._call('shh_newIdentity') - - def shh_hasIdentity(self, address): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_hasidentity - - NEEDS TESTING - ''' - return self._call('shh_hasIdentity', [address]) - - def shh_newGroup(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newgroup - - N/A - ''' - return self._call('shh_newGroup') - - def shh_addToGroup(self): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_addtogroup - - NEEDS TESTING - ''' - return self._call('shh_addToGroup') - - def shh_newFilter(self, to, topics): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newfilter - - NEEDS TESTING - ''' - _filter = { - 'to': to, - 'topics': topics, - } - return self._call('shh_newFilter', [_filter]) - - def shh_uninstallFilter(self, filter_id): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_uninstallfilter - - NEEDS TESTING - ''' - return self._call('shh_uninstallFilter', [filter_id]) - - def shh_getFilterChanges(self, filter_id): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges - - NEEDS TESTING - ''' - return self._call('shh_getFilterChanges', [filter_id]) - - def shh_getMessages(self, filter_id): - ''' - https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getmessages - - NEEDS TESTING - ''' - return self._call('shh_getMessages', [filter_id]) - - -class ParityEthJsonRpc(EthJsonRpc): - ''' - EthJsonRpc subclass for Parity-specific methods - ''' - - def __init__(self, host='localhost', port=PARITY_DEFAULT_RPC_PORT, tls=False): - EthJsonRpc.__init__(self, host=host, port=port, tls=tls) - - def trace_filter(self, from_block=None, to_block=None, from_addresses=None, to_addresses=None): - ''' - https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_filter - - TESTED - ''' - params = {} - if from_block is not None: - from_block = validate_block(from_block) - params['fromBlock'] = from_block - if to_block is not None: - to_block = validate_block(to_block) - params['toBlock'] = to_block - if from_addresses is not None: - if not isinstance(from_addresses, list): - from_addresses = [from_addresses] - params['fromAddress'] = from_addresses - if to_addresses is not None: - if not isinstance(to_addresses, list): - to_addresses = [to_addresses] - params['toAddress'] = to_addresses - return self._call('trace_filter', [params]) - - def trace_get(self, tx_hash, positions): - ''' - https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_get - - NEEDS TESTING - ''' - if not isinstance(positions, list): - positions = [positions] - return self._call('trace_get', [tx_hash, positions]) - - def trace_transaction(self, tx_hash): - ''' - https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_transaction - - TESTED - ''' - return self._call('trace_transaction', [tx_hash]) - - def trace_block(self, block=BLOCK_TAG_LATEST): - ''' - https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_block - - TESTED - ''' - block = validate_block(block) - return self._call('trace_block', [block]) diff --git a/ion/lithium/__init__.py b/ion/lithium/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ion/lithium/api.py b/ion/lithium/api.py deleted file mode 100644 index 5abfab2..0000000 --- a/ion/lithium/api.py +++ /dev/null @@ -1,141 +0,0 @@ -## Copyright (c) 2016-2018 Clearmatics Technologies Ltd -## SPDX-License-Identifier: LGPL-3.0+ - -#!/usr/bin/env python -""" -API - -Provides a set of endpoints from which users can derive the key information regarding proofs -which is required when withdrawing funds from IonLock -""" - -from flask import Flask, request, jsonify - -# from flask import Flask, url_for -from ion.merkle import merkle_tree, merkle_path, merkle_proof - - -app = Flask(__name__) - -@app.route('/') - -@app.route('/api/leaves', methods=['GET', 'POST']) -def api_leaves(): - """ - GET: Return: All leaves held by Lithium - POST: Arguments: JSON with a blockid in the form {'blockid': } - Return: All relevant leaves under the specified blockid - """ - - if request.method == 'POST': - json = request.get_json() - blockid = json[u'blockid'] - if blockid is not None: - nleaves = app.lithium.checkpoints[blockid] - byte_leaves = app.lithium.leaves[0:nleaves] - hex_leaves = [x.encode('hex') for x in byte_leaves] - - elif request.method == 'GET': - byte_leaves = app.lithium.leaves - hex_leaves = [x.encode('hex') for x in byte_leaves] - - dict = {u'leaves': hex_leaves} - - return jsonify(dict) - -@app.route('/api/root', methods=['GET']) -def api_root(): - """ - GET: Return: The root for the merkle tree of all leaves - """ - byte_leaves = app.lithium.leaves - tree, root = merkle_tree(byte_leaves) - dict = {u'root': root} - return jsonify(dict) - -@app.route('/api/checkpoints', methods=['GET']) -def api_checkpoint(): - """Returns the checkpoints""" - return jsonify(app.lithium.checkpoints) - -@app.route('/api/blockid', methods=['POST']) -def api_blockid(): - """ - POST: Arguments: JSON with a leaf in the form {'leaf': } - Return: If passed a valid leaf returns corresponding blockid otherwise returns error string. - """ - if request.method == 'POST': - json = request.get_json() - leaf = json[u'leaf'] - - hex_leaves = [x.encode('hex') for x in app.lithium.leaves] - byte_checkpoints = app.lithium.checkpoints - - if leaf is not None: - leaf_index = hex_leaves.index(leaf) - blockid = None - for block in byte_checkpoints: - if leaf_index >= byte_checkpoints[block]: - pass - else: - blockid = block - break - - dict = {u'blockid': str(blockid)} - return jsonify(dict) - else: - return "No valid leaf received." - -@app.route('/api/proof', methods=['POST']) -def api_proof(): - """ - POST: Arguments: JSON with leaf, blockid in the form {'leaf': , 'blockid': } - Return: If passed valid information returns merkle proof to supplied leaf of relevant blockid - """ - if request.method == 'POST': - json = request.get_json() - leaf = json[u'leaf'] - blockid = json[u'blockid'] - else: - return "Please POST leaf data." - - - if leaf is not None and blockid is not None: - nleaves = app.lithium.checkpoints[blockid] - tree, root = merkle_tree(app.lithium.leaves[:nleaves]) - - hex_leaf = leaf.decode('hex') - - path = merkle_path(hex_leaf, tree) - - string_path = [str(x) for x in path] - dict = {u'proof': string_path} - return jsonify(dict) - else: - return "No valid leaf received." - -@app.route('/api/verify', methods=['POST']) -def api_verify_proof(): - """ - POST: Arguments: JSON with leaf, proof, blockid in the form {'leaf': , 'proof': [] 'blockid': } - Return: If passed valid information returns a boolean verifying in the supplied leaf is part of the merkle tree - """ - if request.method == 'POST': - json = dict(request.get_json()) - leaf = json[u'leaf'] - proof = json[u'proof'] - blockid = json[u'blockid'] - else: - return "Please POST leaf and path data." - - if leaf is not None and proof is not None and blockid is not None: - nleaves = app.lithium.checkpoints[blockid] - leaves = app.lithium.leaves[0:nleaves] - tree, root = merkle_tree(leaves) - - hex_leaf = leaf.decode('hex') - proof = merkle_proof(hex_leaf, proof, root) - - return jsonify({"verified":proof}) - else: - return "No valid leaf or path provided." diff --git a/ion/lithium/lithium.py b/ion/lithium/lithium.py deleted file mode 100644 index 162efaa..0000000 --- a/ion/lithium/lithium.py +++ /dev/null @@ -1,250 +0,0 @@ -# Copyright (c) 2016-2018 Clearmatics Technologies Ltd -# SPDX-License-Identifier: LGPL-3.0+ -""" -Lithium: Event Relayer between two Ethereum chains - -Connects to two RPC endpoints, listens to IonLock events from one chain, packs them, constructs merkle roots and submits them to the IonLink contract of the other chain - -This tool was designed to facilitate the information swap between two EVM chains and only works in one direction. To allow two-way communication, two Lithium instances must be initialised. -""" -from __future__ import print_function - -import threading -import random -import string -import click -from ethereum.utils import scan_bin, sha3, keccak - -from ion.args import arg_bytes20, arg_ethrpc -from ion.merkle import merkle_tree, merkle_hash - -from ion.lithium.api import app - -TRANSFER_SIGNATURE = keccak.new(digest_bits=256) \ - .update('IonTransfer(address,address,uint256,bytes32,bytes)') \ - .hexdigest() - -EVENT_SIGNATURES = [TRANSFER_SIGNATURE] - - -def random_string(amount): - """ - Returns a random string to hash as pseudo data - """ - return ''.join(random.SystemRandom() \ - .choice(string.ascii_uppercase + string.digits) for _ in range(amount)) - - -def pack_txn(txn): - """ - Packs all the information about a transaction into a deterministic fixed-sized array of bytes - from || to - """ - tx_from, tx_to, tx_value, tx_input = [scan_bin(x + ('0' * (len(x) % 2))) \ - for x in [txn['from'], txn['to'], txn['value'], txn['input']]] - - return ''.join([ - tx_from, - tx_to - ]) - - -def pack_log(txn, log): - """ - Packs a log entry into one or more entries. - sender account || token address of opposite chain from sender || ionLock address of opposite chain from sender || value || hash(reference) - """ - print(scan_bin(log['topics'][2]).encode('hex')) - return ''.join([ - scan_bin(txn['from']), - scan_bin(txn['to']), - scan_bin(log['address']), - scan_bin(log['topics'][1]), - scan_bin(log['topics'][2]), - ]) - - -def pack_items(items): - """ - Ensures items has minimum of 4 leaves - """ - start = len(items) - if start < 4: - for _ in range(start, 4): - new_item = random_string(16) - items.append(sha3(new_item)) - else: - pass - - -class Lithium(object): - """ - Lithium process the blocks for the event relat to identify the IonLock transactions which occur - on the rpc_from chains, which are then added to the IonLink of the rpc_to chain. - """ - def __init__(self): - self.checkpoints = {} - self.leaves = [] - self._run_event = None - self._relay_to = None - - def process_block(self, rpc, block_height, transfers): - """Returns all items within the block""" - block = rpc.eth_getBlockByNumber(block_height, False) - items = [] - log_count = 0 - tx_count = 0 - if block['transactions']: - for tx_hash in block['transactions']: - transaction = rpc.eth_getTransactionByHash(tx_hash) - if transaction['to'] is None: - continue - - tx_count += 1 - packed_txns = pack_txn(transaction) - item_value = packed_txns - receipt = rpc.eth_getTransactionReceipt(tx_hash) - transfer = False - if receipt['logs']: - for log_entry in receipt['logs']: - if log_entry['topics'][0][2:] in EVENT_SIGNATURES: - print("Processing IonLock Transfer Event") - - log_items = pack_log(transaction, log_entry) - item_value = log_items - log_count += 1 - transfer = True - - transfers.append(transfer) - items.append(item_value) - - return items, tx_count, log_count - - - def process_block_group(self, rpc, block_group): - """Process a group of blocks, returning the packed events and transactions""" - print("Processing block group") - items = [] - transfers = [] - group_tx_count = 0 - group_log_count = 0 - for block_height in block_group: - block_items, tx_count, log_count = self.process_block(rpc, block_height, transfers) - items += block_items - group_tx_count += tx_count - group_log_count += log_count - - return items, group_tx_count, group_log_count, transfers - - - def iter_blocks(self, run_event, rpc, start=1, group=1, backlog=0, interval=1): - """Iterate through the block numbers""" - old_head = min(start, max(1, rpc.eth_blockNumber() - backlog)) - print("Starting block header: ", start) - print("Previous block header: ", old_head) - old_head -= old_head % group - blocks = [] - is_latest = False - - # Infinite loop event listener... - while run_event.is_set(): - head = rpc.eth_blockNumber() + 1 - for i in range(old_head, head): - if i == (head - 1): - is_latest = True - blocks.append(i) - if len(blocks) % group == 0: - yield is_latest, blocks - blocks = [] - is_latest = False - old_head = head - - - def lithium_submit(self, batch, prev_root, rpc, link, account, checkpoints, leaves): - """Submit batch of merkle roots to IonLink""" - ionlink = rpc.proxy("abi/IonLink.abi", link, account) - if not batch: - return False - - nleaves = len(leaves) - for pair in batch: - if pair[2]: - current_root = pair[1] - ionlink.Update([prev_root, current_root]) - ionlink_latest = ionlink.GetLatestBlock() - print("Latest submitted root", current_root) - - checkpoints[str(ionlink_latest)] = nleaves - - prev_root = current_root - - return prev_root - - - def lithium_instance(self, run_event, rpc_from, rpc_to, from_account, to_account, lock, - link, batch_size): - ionlock = rpc_from.proxy("abi/IonLock.abi", lock, from_account) - batch = [] - - prev_root = merkle_hash("merkle-tree-extra") - - print("Starting block iterator") - print("Latest Block: ", ionlock.LatestBlock) - - for is_latest, block_group in self.iter_blocks(run_event, rpc_from, ionlock.LatestBlock()): - items, group_tx_count, group_log_count, transfers = self.process_block_group(rpc_from, block_group) - if items: - for value in items: - self.leaves.append(value) - - pack_items(self.leaves) - print("blocks %d-%d (%d tx, %d events)" % (min(block_group), max(block_group), group_tx_count, group_log_count)) - tree, root = merkle_tree(self.leaves) - batch.append((block_group[0], root, transfers[0])) - - if is_latest or len(batch) >= batch_size: - print("Submitting batch of", len(batch), "blocks") - prev_root = self.lithium_submit(batch, prev_root, rpc_to, link, to_account, self.checkpoints, self.leaves) - batch = [] - return 0 - - def run(self, rpc_from, rpc_to, from_account, to_account, lock, link, batch_size): - """ Launches the etheventrelay on a thread""" - self._run_event = threading.Event() - self._run_event.set() - - self._relay_to = threading.Thread(target=self.lithium_instance, \ - args=(self._run_event, rpc_from, rpc_to, from_account, to_account, lock, link, batch_size)) - self._relay_to.start() - - def stop(self): - """ Stops the etheventrelay thread """ - self._run_event.clear() - self._relay_to.join() - - -@click.command(help="Ethereum event merkle tree relay daemon") -@click.option('--rpc-from', callback=arg_ethrpc, metavar="ip:port", default='127.0.0.1:8545', help="Source Ethereum JSON-RPC server") -@click.option('--rpc-to', callback=arg_ethrpc, metavar="ip:port", default='127.0.0.1:8546', help="Destination Ethereum JSON-RPC server") -@click.option('--from-account', callback=arg_bytes20, metavar="0x...20", required=True, help="Sender") -@click.option('--to-account', callback=arg_bytes20, metavar="0x...20", required=True, help="Recipient") -@click.option('--lock', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLock contract address") -@click.option('--link', callback=arg_bytes20, metavar="0x...20", required=True, help="IonLink contract address") -@click.option('--api-port', type=int, required=True, metavar="N", help="API server endpoint") -@click.option('--batch-size', type=int, default=32, metavar="N", help="Upload at most N items per transaction") -def etheventrelay(rpc_from, rpc_to, from_account, to_account, lock, link, api_port, batch_size): - lithium = Lithium() - app.lithium = lithium - try: - lithium.run(rpc_from, rpc_to, from_account, to_account, lock, link, batch_size) - app.run(host='127.0.0.1', port=api_port) - except Exception as e: - print(e.message) - - lithium.stop() - - -if __name__ == "__main__": - import sys - from os import path - sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) diff --git a/ion/merkle.py b/ion/merkle.py deleted file mode 100644 index b96b905..0000000 --- a/ion/merkle.py +++ /dev/null @@ -1,133 +0,0 @@ -## Copyright (c) 2016-2018 Clearmatics Technologies Ltd -## SPDX-License-Identifier: LGPL-3.0+ - -#!/usr/bin/env python -""" -Merkle: -Provides an interface to produce merkle trees, proofs, etc. -""" -from __future__ import print_function - -import random - -from .crypto import keccak_256 -from .utils import zpad, int_to_big_endian, bit_clear, bit_test, bit_set, bytes_to_int - - -def serialize(v): - """Convert to value to a hashable scalar""" - if isinstance(v, str): - return v - if isinstance(v, (int, long)): - return zpad(int_to_big_endian(v), 32) - raise NotImplementedError(v) - - -hashs = lambda *x: bytes_to_int(keccak_256(''.join(map(serialize, x))).digest()) - -merkle_hash = lambda *x: bit_clear(hashs(*x), 0xFF) - -def merkle_tree(items): - """ - Hashes a list of items, then creates a Merkle tree where the items are - hashed in pairs to form the next level of the tree until the level is - only one item (the root). - - ``` - [ [ H(0), H(1), H(2), H(3) ] # Level 0 - [ H(H(0)||H(1)), H(H(2)||H(3)) ] # Level 1 - [ H(H(H(0)||H(1))||H(H(2)||H(3))) ] ] # Level 2 (root) - ``` - - If a level has an odd number of items it is padded with an 'extra' item - to keep the tree perfectly balanced. - - The first level of items is sorted. - - :type items: list - :return: list, long - """ - tree = [sorted(map(merkle_hash, items))] - extra = merkle_hash("merkle-tree-extra") - while True: - level = tree[-1] - # Ensure level has an even number of items, pad it with an 'extra item' - if len(level) % 2 != 0: - level.append(extra) - # Hash each pair in the list to create the next level - it = iter(level) - tree.append([merkle_hash(item, next(it)) for item in it]) - if len(tree[-1]) == 1: - break - return tree, tree[-1][0] - - -def merkle_path(item, tree): - """ - Given a tree and an item, return a path which can be used to - verify the item exists within a root. - - The path for `x` is: L5, L11 - The root is: 17, or `H(11, H(5, H(D)))` - - ``` - | - v - a b c x <- items - | | | | - L2 R3 [L5] H(x) <- level 0 - \ / \ / - \/ \/ - [L11] H(L5, H(x)) <- level 1 - \ / - \ / - H(L11, H(L5, H(x))) <- level 2 (root) - ``` - """ - item = merkle_hash(item) - # TODO handle item passed not being in list more elegantly - idx = tree[0].index(item) - - path = [] - for level in tree[:-1]: - if (idx % 2) == 0: - path.append(bit_set(level[idx+1], 0xFF)) - else: - path.append(level[idx-1]) - idx = idx // 2 - return path - - -def merkle_proof(leaf, path, root): - """ - Verify Merkle path for an item matches the root - - The most significant bit of every item in the path is used to - determine if it's a 'left' or 'right' node, meaning: - - H(node, item) or H(item, node) - """ - node = merkle_hash(leaf) - for item in path: - if bit_test(item, 0xFF): - node = merkle_hash(node, bit_clear(item, 0xFF)) - else: - node = merkle_hash(item, node) - return node == root - - -def main(): - # Create 99 trees of 1..N items - for i in range(1, 100): - items = range(0, i) - tree, root = merkle_tree(items) - - # Verify all items exist within the root - random.shuffle(items) - for item in items: - proof = merkle_path(item, tree) - assert merkle_proof(item, proof, root) is True - - -if __name__ == "__main__": - main() diff --git a/ion/utils.py b/ion/utils.py deleted file mode 100644 index f572430..0000000 --- a/ion/utils.py +++ /dev/null @@ -1,117 +0,0 @@ -import sys -from base64 import b64encode, b64decode -import binascii -import json - -from rlp.sedes import big_endian_int -from rlp.utils import decode_hex, str_to_bytes - -if sys.version_info.major == 2: - def bytearray_to_bytestr(value): - return bytes(''.join(chr(c) for c in value)) -else: - def bytearray_to_bytestr(value): - return bytes(value) - - -TT256 = 2 ** 256 - - -safe_ord = ord if sys.version_info.major == 2 else lambda x: x if isinstance(x, int) else ord(x) - -bytes_to_int = lambda x: reduce(lambda o, b: (o << 8) + safe_ord(b), [0] + list(x)) - - -bit_clear = lambda n, b: n ^ (1<<(b-1)) if n & 1<<(b-1) else n - -bit_set = lambda n, b: n | (1<<(b-1)) - -bit_test = lambda n, b: 0 != (n & (1<<(b-1))) - - -def packl(lnum): - assert lnum >= 0 - if lnum == 0: - return b'\0' - s = hex(lnum)[2:].rstrip('L') - if len(s) & 1: - s = '0' + s - return binascii.unhexlify(s) - -int_to_big_endian = packl - - -def big_endian_to_int(x): return big_endian_int.deserialize( - str_to_bytes(x).lstrip(b'\x00')) - -zpad = lambda x, l: b'\x00' * max(0, l - len(x)) + x - - -u256be = lambda v: zpad(int_to_big_endian(v), 32) - -flatten = lambda l: [item for sublist in l for item in sublist] - -# Turns a `defaultdict(defaultdict)` into a flat dictionary -dict_dump = lambda diff: {c: dict(d.items()) for c, d in diff.items()} - - -def is_numeric(x): return isinstance(x, (int, long)) - - -def encode_int(v): - """encodes an integer into serialization""" - if not is_numeric(v) or v < 0 or v >= TT256: - raise Exception("Integer invalid or out of range: %r" % v) - return int_to_big_endian(v) - - -def scan_bin(v): - if v[:2] in ('0x', b'0x'): - return decode_hex(v[2:]) - else: - return decode_hex(v) - - -def require(arg, msg=None): - if not arg: - raise RuntimeError(msg or "Requirement failed") - - -class Marshalled(object): - def tojson(self): - return tojson(self) - - def marshal(self): - return marshal(list(self)) - - @classmethod - def unmarshal(cls, args): - return cls(*map(unmarshal, args)) - - -def tojson(x): - return json.dumps(marshal(x)) - - -def marshal(x): - if isinstance(x, (int, long, type(None))): - return x - if isinstance(x, (str, bytes, unicode)): - return b64encode(x) - if isinstance(x, (tuple, list)): - return map(marshal, x) - if isinstance(x, Marshalled): - return x.marshal() - raise ValueError("Cannot marshal type: %r - %r" % (type(x), x)) - - -def unmarshal(x): - if x is None or isinstance(x, (int, long)): - return x - if isinstance(x, (str, bytes, unicode)): - return b64decode(x) - if isinstance(x, (tuple, list)): - return map(unmarshal, x) - if isinstance(x, Marshalled): - return x.unmarshal(x) - raise ValueError("Cannot unmarshal type: %r - %r" % (type(x), x)) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index b6de249..0000000 --- a/requirements.txt +++ /dev/null @@ -1,19 +0,0 @@ -requests==2.18.4 -eth-abi==1.0.0 -eth-hash==0.1.0 -eth-utils==1.0.1 -ethereum==2.3.1 -jsonrpc2==0.4.1 -flask==1.0.2 -flask_restful==0.3.6 -gevent==1.2.2 -rlp==0.6.0 -python-jsonrpc==0.10.0 -graphviz==0.8.3 -coincurve==7.1.0 -msgpack-python==0.5.6 -coverage==4.5.1 -click==6.7 -prompt_toolkit==1.0.15 -pylint==1.8.4 -simplejson diff --git a/setup.py b/setup.py deleted file mode 100644 index faa4639..0000000 --- a/setup.py +++ /dev/null @@ -1,16 +0,0 @@ -from setuptools import setup -from pip.req import parse_requirements -from pip.download import PipSession - - -setup( - name='ion', - version='0.1', - packages=['ion'], - py_modules=['__main__'], - install_requires=[str(ir.req) for ir in parse_requirements('requirements.txt', session=PipSession())], - entry_points=''' - [console_scripts] - ion=ion.__main__:main - ''' -) diff --git a/test/integration.py b/test/integration.py deleted file mode 100644 index fad83fa..0000000 --- a/test/integration.py +++ /dev/null @@ -1,191 +0,0 @@ -## Copyright (c) 2016-2018 Clearmatics Technologies Ltd -## SPDX-License-Identifier: LGPL-3.0+ - -#!/usr/bin/env python -''' -integration tests - -This set of tests should test the locking of funds on chain A and the subsequent withdrawal -on chain B -''' - -import unittest -import socket - -from ethereum.utils import sha3 - -from ion.args import arg_bytes20, arg_ethrpc -from ion.merkle import merkle_tree, merkle_hash, merkle_path, merkle_proof -from ion.utils import u256be - -from ion.lithium.lithium import iter_blocks, lithium_process_block_group, lithium_submit - -# Definition of the fundamental variables required -chainA = "127.0.0.1:8545" -chainB = "127.0.0.1:8546" -owner = arg_bytes20(None, None, "0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1") -lock = arg_bytes20(None, None, "0xe982e462b094850f12af94d21d470e21be9d0e9c") -link = arg_bytes20(None, None, "0xc89ce4735882c9f0f0fe26686c53074e09b0d550") -tokAddr = arg_bytes20(None, None, "0x9561c133dd8580860b6b7e504bc5aa500f0f06a7") -send = arg_bytes20(None, None, "0xffcf8fdee72ac11b5c542428b35eef5769c409f0") -recv = arg_bytes20(None, None, "0x22d491bde2303f2f43325b2108d26f1eaba1e32b") -dummy = arg_bytes20(None, None, "0x1df62f291b2e969fb0849d99d9ce41e2f137006e") - -class IntegrationTest(unittest.TestCase): - - def test_integration(self): - print("\nTest: Integration") - - totalSupply_a = 1000 - totalSupply_b = 1000 - value_a = 10 - value_b = 10 - rawRef_a = 'Hello world!' - rawRef_b = 'Hello world!' - - # Assert that both testrpc A and B are live - sockA = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sockA.settimeout(2) - self.assertFalse(sockA.connect_ex(('127.0.0.1',8545)), "Please run testrpc on 127.0.0.1:8545") - sockB = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sockB.settimeout(2) - self.assertFalse(sockB.connect_ex(('127.0.0.1',8546)), "Please run testrpc on 127.0.0.1:8546") - - # First iteration of block - rpc_a = arg_ethrpc(None, None, '127.0.0.1:8545') - rpc_b = arg_ethrpc(None, None, '127.0.0.1:8546') - ionlock_a = rpc_a.proxy("abi/IonLock.abi", lock, owner) - ionlock_b = rpc_b.proxy("abi/IonLock.abi", lock, owner) - ionlink_a = rpc_a.proxy("abi/IonLink.abi", link, owner) - ionlink_b = rpc_b.proxy("abi/IonLink.abi", link, owner) - token_a = rpc_a.proxy("abi/Token.abi", tokAddr, send) - token_b = rpc_b.proxy("abi/Token.abi", tokAddr, recv) - batch_a = [] - batch_b = [] - transfers = [] - prev_root = merkle_hash("merkle-tree-extra") - - - -################################################################################ - print("Starting block iterator: rpc_a") - print("latest Block rpc_a: ", ionlock_a.LatestBlock()) - # Note this is the un-wound infinite loop of iter_blocks - start = rpc_a.eth_blockNumber() - - - # Now deploy the tokens on the networks - token_a.mint(totalSupply_a) - token_a.metadataTransfer(lock, value_a, rawRef_a) - - obh = min(start + 1, max(1, rpc_a.eth_blockNumber() - 0)) - print("Starting block header rpc_a: ", start) - print("Previous block header rpc_a: ", obh) - self.assertEqual(start, 8) - obh -= obh % 1 - blocks = [] - is_latest = False - - - # Pack the blocks into batches - bh = rpc_a.eth_blockNumber() + 1 - print("Current block header rpc_a: ", bh) - for i in range(obh, bh): - # XXX TODO: I think this is why the latest block info is not always in sync with geth - if i == (bh - 1): - is_latest = True - blocks.append(i) - obh = bh - - # Show the blocks to work on and then rename just to keep convention from lithium.py - block_group = blocks - self.assertEqual(len(blocks), 2) - - # Process the block on chain A - items, group_tx_count, group_log_count, transfers = lithium_process_block_group(rpc_a, block_group) - item_tree_a, root = merkle_tree(items) - - for i in range(0, len(block_group)): - batch_a.append( (block_group[i], root, transfers[i]) ) - - prev_root = lithium_submit(batch_a, prev_root, rpc_b, link, owner) - latestBlockB = ionlink_b.GetLatestBlock() - path_a = merkle_path(items[1], item_tree_a) - - leafHashB = sha3(items[1]) - reference_a = sha3(rawRef_a) - - ionlock_b = rpc_b.proxy("abi/IonLock.abi", lock, send) - # print(ionlink_b.Verify(latestBlockB, leafHashB, path_a)) - -################################################################################ - print("Starting block iterator: rpc_b") - print("latest Block rpc_b: ", ionlock_b.LatestBlock()) - # Note this is the un-wound infinite loop of iter_blocks - start = rpc_b.eth_blockNumber() - - - # Now deploy the tokens on the networks - token_b.mint(totalSupply_b) - token_b.metadataTransfer(lock, value_b, rawRef_b) - - obh = min(start + 1, max(1, rpc_b.eth_blockNumber() - 0)) - print("Starting block header rpc_b: ", start) - print("Previous block header rpc_b: ", obh) - self.assertEqual(start, 9) - obh -= obh % 1 - blocks = [] - is_latest = False - - - # Pack the blocks into batches - bh = rpc_b.eth_blockNumber() + 1 - print("Current block header rpc_b: ", bh) - for i in range(obh, bh): - # XXX TODO: I think this is why the latest block info is not always in sync with geth - if i == (bh - 1): - is_latest = True - blocks.append(i) - obh = bh - - # Show the blocks to work on and then rename just to keep convention from lithium.py - block_group = blocks - self.assertEqual(len(blocks), 2) - - - # Process the block on chain B - items, group_tx_count, group_log_count, transfers = lithium_process_block_group(rpc_b, block_group) - - item_tree_b, root = merkle_tree(items) - - for i in range(0, len(block_group)): - batch_b.append( (block_group[i], root, transfers[i]) ) - - prev_root = lithium_submit(batch_b, prev_root, rpc_a, link, owner) - latestBlockA = ionlink_a.GetLatestBlock() - path_b = merkle_path(items[1], item_tree_b) - - leafHashA = sha3(items[1]) - reference_b = sha3(rawRef_b) - - ionlock_a = rpc_a.proxy("abi/IonLock.abi", lock, recv) - -################################################################################ - - self.assertEqual(token_a.balanceOf(lock), value_a) - self.assertEqual(token_b.balanceOf(lock), value_b) - self.assertEqual(token_a.balanceOf(recv), 0) - self.assertEqual(token_b.balanceOf(send), 0) - - ionlock_b.Withdraw(value_a, reference_a, latestBlockB, path_a) - ionlock_a.Withdraw(value_b, reference_b, latestBlockA, path_b) - self.assertEqual(token_a.balanceOf(lock), 0) - self.assertEqual(token_b.balanceOf(lock), 0) - self.assertEqual(token_a.balanceOf(recv), value_a) - self.assertEqual(token_b.balanceOf(send), value_b) - -if __name__ == '__main__': - import sys - from os import path - sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - unittest.main() diff --git a/test/link.js b/test/link.js deleted file mode 100644 index a91c28f..0000000 --- a/test/link.js +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const crypto = require('crypto'); - -const merkle = require('./helpers/merkle.js') - -const IonLink = artifacts.require("IonLink"); -const utils = require('./helpers/utils.js') - -const randomHex = () => crypto.randomBytes(32).toString('hex'); -const randomArr = () => { - const result = [] - const size =(Math.floor(Math.random() * 10) + 1); - for(let i = size; 0 < i; i-- ) - result.push(randomHex()) - return result -} - -contract('IonLink', (accounts) => { - it('GetRoot', async () => { - //const ionLink = await IonLink.new(10); - const ionLink = await IonLink.deployed(); - - const testData1 = randomArr() - const tree1 = merkle.createMerkle(testData1) - const testData2 = randomArr() - const tree2 = merkle.createMerkle(testData2) - const testData3 = randomArr() - const tree3 = merkle.createMerkle(testData3) - - const rootArr1 = [tree1[1],tree2[1],tree3[1]] - const receipt1 = await ionLink.Update(rootArr1) - - const testData4 = randomArr() - const tree4 = merkle.createMerkle(testData4) - const testData5 = randomArr() - const tree5 = merkle.createMerkle(testData5) - const testData6 = randomArr() - const tree6 = merkle.createMerkle(testData6) - - const rootArr2 = [tree4[1],tree5[1],tree6[1]] - const receipt2 = await ionLink.Update(rootArr2) - - const latestBlock = await ionLink.GetLatestBlock() - const previousBlock = await ionLink.GetPrevious(latestBlock) - const latestRoot = await ionLink.GetRoot(latestBlock) - const previousRoot = await ionLink.GetRoot(previousBlock) - assert.equal(tree6[1].toString(16),latestRoot.toString(16),'latest root is wrong') - assert.equal(tree5[1].toString(16),previousRoot.toString(16),'previous root is wrong') - }) - - it('Update', async () => { - //const ionLink = await IonLink.new(10); - const ionLink = await IonLink.deployed(); - - const testData1 = randomArr() - const tree1 = merkle.createMerkle(testData1) - const testData2 = randomArr() - const tree2 = merkle.createMerkle(testData2) - - const leaf = testData2[0] - const leafHash = merkle.merkleHash(leaf) - const path = merkle.pathMerkle(leaf,tree2[0]) - const rootArg = [tree1[1],tree2[1]] - - const receiptUpdate = await ionLink.Update(rootArg) - const latestBlock = await ionLink.GetLatestBlock() - const valid = await ionLink.Verify(latestBlock,leafHash,path) - assert(valid,'IonLink.verify() failed!') - - assert( receiptUpdate.logs.length > 0) - assert.equal( receiptUpdate.logs[0].event, 'IonLinkUpdated', 'IonLinkUpdated event not found in logs' ) - }) - - it('duplicate root', async () => { - //const ionLink = await IonLink.new(10); - const ionLink = await IonLink.deployed(); - - const testData = randomArr() - const tree = merkle.createMerkle(testData) - - const receiptUpdate = await ionLink.Update([tree[1],tree[1]]) - const latestBlock = await ionLink.GetLatestBlock() - const previousBlock = await ionLink.GetPrevious(latestBlock) - assert.notEqual(latestBlock.toString(16),previousBlock.toString(16),'submitted smae root 2x should have different hashes!') - }) -}); diff --git a/test/lock.js b/test/lock.js deleted file mode 100644 index ef470aa..0000000 --- a/test/lock.js +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3Utils = require('web3-utils'); -const web3Abi = require('web3-eth-abi'); -const crypto = require('crypto'); - -const merkle = require('./helpers/merkle.js') -const Token = artifacts.require("Token"); -const IonLink = artifacts.require("IonLink"); -const IonLock = artifacts.require("IonLock"); - -const randomHex = () => crypto.randomBytes(32).toString('hex'); -const randomArr = () => { - const result = [] - const size =(Math.floor(Math.random() * 10) + 1); - for(let i = size; 0 < i; i-- ) - result.push(randomHex()) - return result -} -const send2Lock = async (from,tokenAddr,ionLockAddr,value,rawRef) => { - const overloadedTransferAbi = { - "constant": false, - "inputs": [ - { "name": "_to", "type": "address" }, - { "name": "_value", "type": "uint256" }, - { "name": "_data", "type": "bytes" } - ], - "name": "transfer", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - const transferMethodTransactionData = web3Abi.encodeFunctionCall( - overloadedTransferAbi, - [ ionLockAddr, value, Web3Utils.toHex(rawRef) ] - ); - const receiptTransfer1 = await web3.eth.sendTransaction({ from: from, to: tokenAddr, data: transferMethodTransactionData, value: 0 }); - return receiptTransfer1; -} -const waitLockEvent = async (lockContract,rawRef) => { - const ionMintEventObj = lockContract.IonMint() - const ionTransferEventObj = lockContract.IonTransfer() - let ref - try { - const ionMintEvent = await watchEvent(ionMintEventObj) - const ionTransferEvent = await watchEvent(ionTransferEventObj) - assert.equal(ionTransferEvent.args.ref,Web3Utils.sha3(rawRef),'ref different than expected after transfer!') - ref = ionTransferEvent.args.ref - } catch (err) { - console.log('event error:', err) - assert.fail('event error:' + err) - } - ionMintEventObj.stopWatching() - ionTransferEventObj.stopWatching() - return ref -} -const joinIonLinkData = (receiverAddr,tokenAddr,ionLockAddr,value,reference) => { - const valueHex = '0x'+Web3Utils.toBN(value).toString(16).padStart(64,'0') // make an hex that is good to sha3 in solidity uint256 -> 64 bytes - const leaf = '0x' + [receiverAddr,tokenAddr,ionLockAddr,valueHex,reference].map(el=>el.slice(2)).join('') // joined args need to be added to the random leafs of the tree - // const leaf = '0x' + [receiverAddr,ionLockAddr,tokenAddr,valueHex,reference].map(el=>el.slice(2)).join('') // joined args need to be added to the random leafs of the tree - return leaf -} - -const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))) - -contract('IonLock', (accounts) => { - - it('tokenFallback is called by Token.transfer', async () => { - const token = await Token.new(); - const ionLink = await IonLink.new(0); - const ionLock = await IonLock.new(token.address, ionLink.address); - - const owner = accounts[0] - const totalSupply = 1000 - const value = 10 // value transferred - - const receiptMint = await token.mint(totalSupply) - - const receiptTransfer1 = await token.rawTransfer(ionLock.address,value) - - const ionMintEventObj = ionLock.IonMint() - const ionTransferEventObj = ionLock.IonTransfer() - try { - const ionMintEvent = await watchEvent(ionMintEventObj) - const ionTransferEvent = await watchEvent(ionTransferEventObj) - - assert.equal(ionMintEvent.args.value.toString(10),''+value,'IonMint event unexpected value!') - assert.equal(ionMintEvent.args.ref,ionTransferEvent.args.ref,'IonMint event ref not equal to IonTransfer event ref!') - - } catch (err) { - console.log('event error:', err) - assert.fail('event error:' + err) - } - ionMintEventObj.stopWatching() - ionTransferEventObj.stopWatching() - - }) - - it('withdraw', async () => { - const token = await Token.new(); - const ionLink = await IonLink.new(0); - const ionLock = await IonLock.new(token.address, ionLink.address); - - const owner = accounts[0] - const totalSupply = 1000 - const value = 10 // value transferred - - const receiptMint = await token.mint(totalSupply) - - const receiptTransfer1 = await token.transfer(ionLock.address,value) - - // get reference from events - const ionMintEventObj = ionLock.IonMint() - const ionTransferEventObj = ionLock.IonTransfer() - let ref - try { - const ionMintEvent = await watchEvent(ionMintEventObj) - const ionTransferEvent = await watchEvent(ionTransferEventObj) - ref = ionTransferEvent.args.ref - - } catch (err) { - console.log('event error:', err) - assert.fail('event error:' + err) - } - ionMintEventObj.stopWatching() - ionTransferEventObj.stopWatching() - - assert(ref,'reference is empty!') //check that ref has something - - // hash details to be added to IonLink - const reference = ref - const valueHex = '0x'+Web3Utils.toBN(value).toString(16).padStart(64,'0') // make an hex that is good to sha3 in solidity uint256 -> 64 bytes - const lockAddr = ionLock.address - const tokenAddr = token.address - const withdrawReceiver = accounts[1] - - //concat the arguments of sh3 in solidity (in the same way solidity does) - const joinedArgs = '0x' + [withdrawReceiver,tokenAddr,lockAddr,valueHex,reference].map(el=>el.slice(2)).join('') - - //const hashData = Web3Utils.soliditySha3(withdrawReceiver,lockAddr,tokenAddr,value,reference) //it is the same - const hashData = Web3Utils.sha3(joinedArgs) - //console.log([withdrawReceiver,lockAddr,tokenAddr,value,reference],hashData) - //console.log( joinedArgs,hashData2) - - // submit hashdata to IonLink - const leaf = joinedArgs // joined args need to be added to the random leafs of the tree - const testData = randomArr() - testData[0] = leaf - const tree = merkle.createMerkle(testData) - const treeExtra = merkle.createMerkle(randomArr()) // IonLink needs 2 roots min to update - - const leafHash = merkle.merkleHash(leaf) - const path = merkle.pathMerkle(leaf,tree[0]) - const rootArg = [treeExtra[1],tree[1]] - - const receiptUpdate = await ionLink.Update(rootArg) - const latestBlock = await ionLink.GetLatestBlock() - const valid = await ionLink.Verify(latestBlock,leafHash,path) - assert(valid,'leaf not found in tree') - - // withdraw from ionlock - const receiptWithdraw = await ionLock.Withdraw(value,reference,latestBlock,path,{ from: withdrawReceiver }) - - const balanceOwner = await token.balanceOf(owner) - const balanceReceiver = await token.balanceOf(withdrawReceiver) - - assert.equal(balanceOwner,totalSupply - value, 'sender balance wrong!') - assert.equal(balanceReceiver,value, 'receiver balance wrong!') - }) - - - // using the overloaded function is a problem for truffle so it is better to have a different test for that - it('withdraw with reference', async () => { - const token = await Token.new(); - const ionLink = await IonLink.new(0); - const ionLock = await IonLock.new(token.address, ionLink.address); - - const owner = accounts[0] - const totalSupply = 1000 - const value = 10 // value transferred - const rawRef = 'Hello world!' - - const receiptMint = await token.mint(totalSupply) - - //const receiptTransfer1 = await token.transfer(ionLock.address,value) - const overloadedTransferAbi = { - "constant": false, - "inputs": [ - { "name": "_to", "type": "address" }, - { "name": "_value", "type": "uint256" }, - { "name": "_data", "type": "bytes" } - ], - "name": "transfer", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - const transferMethodTransactionData = web3Abi.encodeFunctionCall( - overloadedTransferAbi, - [ - ionLock.address, - value, - Web3Utils.toHex(rawRef) - ] - ); - const receiptTransfer1 = await web3.eth.sendTransaction( - { - from: owner, - to: token.address, - data: transferMethodTransactionData, - value: 0 - } - ); - - // get reference from events - const ionMintEventObj = ionLock.IonMint() - const ionTransferEventObj = ionLock.IonTransfer() - let ref - try { - const ionMintEvent = await watchEvent(ionMintEventObj) - const ionTransferEvent = await watchEvent(ionTransferEventObj) - assert.equal(ionTransferEvent.args.ref,Web3Utils.sha3(rawRef),'ref different than expected after transfer!') - - } catch (err) { - console.log('event error:', err) - assert.fail('event error:' + err) - } - ionMintEventObj.stopWatching() - ionTransferEventObj.stopWatching() - - // hash details to be added to IonLink - const reference = Web3Utils.sha3(rawRef) //hash our reference - const valueHex = '0x'+Web3Utils.toBN(value).toString(16).padStart(64,'0') // make an hex that is good to sha3 in solidity uint256 -> 64 bytes - const lockAddr = ionLock.address - const tokenAddr = token.address - const withdrawReceiver = accounts[1] - - //concat the arguments of sh3 in solidity (in the same way solidity does) - const joinedArgs = '0x' + [withdrawReceiver,tokenAddr,lockAddr,valueHex,reference].map(el=>el.slice(2)).join('') - - //const hashData = Web3Utils.soliditySha3(withdrawReceiver,lockAddr,tokenAddr,value,reference) //it is the same - const hashData = Web3Utils.sha3(joinedArgs) - //console.log([withdrawReceiver,lockAddr,tokenAddr,value,reference],hashData) - //console.log( joinedArgs,hashData2) - - // submit hashdata to IonLink - const leaf = joinedArgs // joined args need to be added to the random leafs of the tree - const testData = randomArr() - testData[0] = leaf - const tree = merkle.createMerkle(testData) - const treeExtra = merkle.createMerkle(randomArr()) // IonLink needs 2 roots min to update - - const leafHash = merkle.merkleHash(leaf) - const path = merkle.pathMerkle(leaf,tree[0]) - const rootArg = [treeExtra[1],tree[1]] - - const receiptUpdate = await ionLink.Update(rootArg) - const latestBlock = await ionLink.GetLatestBlock() - const valid = await ionLink.Verify(latestBlock,leafHash,path) - assert(valid,'leaf not found in tree') - - // withdraw from ionlock - const receiptWithdraw = await ionLock.Withdraw(value,reference,latestBlock,path,{ from: withdrawReceiver }) - - const balanceOwner = await token.balanceOf(owner) - const balanceReceiver = await token.balanceOf(withdrawReceiver) - - assert.equal(balanceOwner,totalSupply - value, 'sender balance wrong!') - assert.equal(balanceReceiver,value, 'receiver balance wrong!') - }) - - it('withdraw different chains with reference', async () => { - const token = await Token.new(); - const ionLink = await IonLink.new(0); - const ionLock = await IonLock.new(token.address, ionLink.address); - const tokenB = await Token.new(); - const ionLinkB = await IonLink.new(0); - const ionLockB = await IonLock.new(tokenB.address, ionLinkB.address); - - const owner = accounts[0] - const totalSupply = 1000 - const value = 10 // value transferred - const rawRef = Web3Utils.sha3('Reference from deposit on chain A') - const totalSupplyB = 1000 - const valueB = 10 // value transferred - const rawRefB = Web3Utils.sha3('Reference from deposit on chain B') - - const sender = accounts[3] - const withdrawReceiver = accounts[5] - const senderB = accounts[4] - const withdrawReceiverB = accounts[6] - - const receiptMint = await token.mint(totalSupply) - const receiptTransfer = await token.transfer(sender,totalSupply) - const receiptMintB = await tokenB.mint(totalSupplyB) - const receiptTransferB = await tokenB.transfer(senderB,totalSupplyB) - - // wait lock events blocks the rest of the test from running if no event is triggered - // A -> LOCK_A // get REFERENCE_A - const receiptSend2Lock = await send2Lock(sender,token.address,ionLock.address,value,rawRef) - const ref = await waitLockEvent(ionLock,rawRef) - - // B -> LOCK_B // get REFERENCE_B - const receiptSend2LockB = await send2Lock(senderB,tokenB.address,ionLockB.address,value,rawRefB) - const refB = await waitLockEvent(ionLockB,rawRefB) - - // hash details to be added to IonLink - // MERKLE_ROOT(REFERENCE_B) -> LINK_A - // this marks B as the recipient of the tokens - const leaf = joinIonLinkData(withdrawReceiverB,token.address,ionLock.address,value,refB) - - const testData = randomArr() - testData[0] = leaf - const tree = merkle.createMerkle(testData) - const treeExtra = merkle.createMerkle(randomArr()) // IonLink needs 2 roots min to update - - const leafHash = merkle.merkleHash(leaf) - const path = merkle.pathMerkle(leaf,tree[0]) - const rootArg = [treeExtra[1],tree[1]] - - const receiptUpdate = await ionLink.Update(rootArg) - const latestBlock = await ionLink.GetLatestBlock() - const valid = await ionLink.Verify(latestBlock,leafHash,path) - assert(valid,'leaf not found in tree') - - // MERKLE_ROOT(REFERENCE_A) -> LINK_B - // this marks A as the recipient of the tokens - const leafB = joinIonLinkData(withdrawReceiver,tokenB.address,ionLockB.address,valueB,ref) - - const testDataB = randomArr() - testDataB[0] = leafB - const treeB = merkle.createMerkle(testDataB) - const treeExtraB = merkle.createMerkle(randomArr()) // IonLink needs 2 roots min to update - - const leafHashB = merkle.merkleHash(leafB) - const pathB = merkle.pathMerkle(leafB,treeB[0]) - const rootArgB = [treeExtraB[1],treeB[1]] - - const receiptUpdateB = await ionLinkB.Update(rootArgB) - const latestBlockB = await ionLinkB.GetLatestBlock() - const validB = await ionLinkB.Verify(latestBlockB,leafHashB,pathB) - assert(validB,'leaf not found in tree') - - // withdraw from ionlock - // LOCK_A -> B - const receiptWithdraw = await ionLock.Withdraw(value,refB,latestBlock,path,{ from: withdrawReceiverB }) - - const balanceSender = await token.balanceOf(sender) - const balanceReceiver = await token.balanceOf(withdrawReceiverB) - - assert.equal(balanceSender,totalSupply - value, 'sender balance wrong!') - assert.equal(balanceReceiver,value, 'receiver balance wrong!') - - assert(receiptWithdraw.logs.length > 0) - assert.equal( receiptWithdraw.logs[0].event, 'IonWithdraw', 'Chain A IonWithdraw event not found in logs' ) - - // LOCK_B -> A - const receiptWithdrawB = await ionLockB.Withdraw(valueB,ref,latestBlockB,pathB,{ from: withdrawReceiver }) - - const balanceSenderB = await tokenB.balanceOf(senderB) - const balanceReceiverB = await tokenB.balanceOf(withdrawReceiver) - - assert.equal(balanceSenderB,totalSupplyB - valueB, 'sender balance wrong!') - assert.equal(balanceReceiverB,valueB, 'receiver balance wrong!') - - assert(receiptWithdrawB.logs.length > 0) - assert.equal( receiptWithdrawB.logs[0].event, 'IonWithdraw', 'Chain B IonWithdraw event not found in logs' ) - }) -}); diff --git a/test/test_api.py b/test/test_api.py deleted file mode 100644 index 6a40d66..0000000 --- a/test/test_api.py +++ /dev/null @@ -1,135 +0,0 @@ -## Copyright (c) 2016-2018 Clearmatics Technologies Ltd -## SPDX-License-Identifier: LGPL-3.0+ - -#!/usr/bin/env python -''' -API tests - -This tests the API which gives users access to the data required to make a withdrawal. -''' - -import unittest -import requests -import json - -from ion.lithium.api import app - - -CHECKPOINTS = \ - { - u'81d9d8277b8f741b859de5455b9b56ff240d2ecf19101df3da9b76b137e5a7e6': 4, - u'6ce75c011eac6f587c54493784ce2139b70e38b5b04fedab2bf5a84b500d0d92': 7 - } - -LEAVES = \ - { - u'leaves': [ - u'ffcf8fdee72ac11b5c542428b35eef5769c409f0c89ce4735882c9f0f0fe26686c53074e09b0d550d833215cbcc3f914bd1c9ece3ee7bf8b14f841bb03e8e6a7765f46f721f4be3c5369983d84a6a86ed7c17bcea6b39876d1920c6532fa', - u'45b6d9232f9a2d8808fef6ee5339482aed37a8588a8668cb88fde5ffaab67ba1', - u'51f8fcbbea5fb362345c94c4cd6809db199965fc22d7aa913a8ca73387fb5a30', - u'73e34f24b39488c9d00971d23969be48654df4ad8e275c698ba4e88f4206b612', - u'90f8bf6a479f320ead074411a4b0e7944ea8c9c1c89ce4735882c9f0f0fe26686c53074e09b0d550', - u'90f8bf6a479f320ead074411a4b0e7944ea8c9c1c89ce4735882c9f0f0fe26686c53074e09b0d550', - u'ffcf8fdee72ac11b5c542428b35eef5769c409f0c89ce4735882c9f0f0fe26686c53074e09b0d550d833215cbcc3f914bd1c9ece3ee7bf8b14f841bb03e8e6a7765f46f721f4be3c5369983d84a6a86ed7c17bcea6b39876d1920c6532fa'] - } - -EXPECTED_BLOCKID = \ - { - u'blockid': u'6ce75c011eac6f587c54493784ce2139b70e38b5b04fedab2bf5a84b500d0d92' - } - -PROOF = \ - { - u'proof': [ - u'54014011439648363204354998496393219114331058923926644452979013882180058964973', - u'111156487848132035204691335325227635200969078435864690888530225168808220587159', - u'112042151246272191572954036892630855408766946838390755837084327398547991526295' - ] - } - -class MockLithium(): - leaves = ['\xff\xcf\x8f\xde\xe7*\xc1\x1b\\T$(\xb3^\xefWi\xc4\t\xf0\xc8\x9c\xe4sX\x82\xc9\xf0\xf0\xfe&hlS\x07N\t\xb0\xd5P\xd83!\\\xbc\xc3\xf9\x14\xbd\x1c\x9e\xce>\xe7\xbf\x8b\x14\xf8A\xbb\x03\xe8\xe6\xa7v_F\xf7!\xf4\xbe\xe7\xbf\x8b\x14\xf8A\xbb\x03\xe8\xe6\xa7v_F\xf7!\xf4\xbe 0) - - for log in receipt['logs']: - packed_log = pack_log(txn, log) - - address = scan_bin(log['address']).encode('hex') - topic1 = scan_bin(log['topics'][1]).encode('hex') - topic2 = scan_bin(log['topics'][2]).encode('hex') - - expected_result = '' + (test_sender_addr[2:]) + (test_recipient_addr[2:]) + address + topic1 + topic2 - - self.assertEqual(packed_log.encode('hex'), expected_result) - - print("Test: Pack Transaction Logs Success") - - - def test_process_block(self): - print("\n==== Test: Process Single Block ====") - lithium = Lithium() - rpc = MockRPC() - transfers = [] - items, tx_count, log_count = lithium.process_block(rpc, rpc.eth_blockNumber(), transfers) - - txn = rpc.eth_getTransactionByHash() - receipt = rpc.eth_getTransactionReceipt() - - self.assertEqual(len(receipt['logs']), 1) - - log = receipt['logs'][0] - packed_log = pack_log(txn, log) - - address = scan_bin(log['address']).encode('hex') - topic1 = scan_bin(log['topics'][1]).encode('hex') - topic2 = scan_bin(log['topics'][2]).encode('hex') - - expected_txn_result = '' + (test_sender_addr[2:]) + (test_recipient_addr[2:]) + address + topic1 + topic2 - self.assertEqual(packed_log.encode('hex'), expected_txn_result) - - self.assertEqual(len(items), 1) - self.assertEqual(items[0].encode('hex'), expected_txn_result) - self.assertEqual(tx_count, 1) - self.assertEqual(log_count, 1) - - print("Test: Process Single Block Success") - - - def test_process_block_group(self): - print("\n==== Test: Process Block Group ====") - lithium = Lithium() - rpc = MockRPC() - items, group_tx_count, group_log_count, transfers = lithium.process_block_group(rpc, [1]) - - txn = rpc.eth_getTransactionByHash() - receipt = rpc.eth_getTransactionReceipt() - - self.assertEqual(len(receipt['logs']), 1) - - log = receipt['logs'][0] - packed_log = pack_log(txn, log) - - address = scan_bin(log['address']).encode('hex') - topic1 = scan_bin(log['topics'][1]).encode('hex') - topic2 = scan_bin(log['topics'][2]).encode('hex') - - expected_txn_result = '' + (test_sender_addr[2:]) + (test_recipient_addr[2:]) + address + topic1 + topic2 - self.assertEqual(packed_log.encode('hex'), expected_txn_result) - - self.assertEqual(len(items), 1) - self.assertEqual(items[0].encode('hex'), expected_txn_result) - self.assertEqual(group_tx_count, 1) - self.assertEqual(group_log_count, 1) - - print("Test: Process Block Group Success") - - - -if __name__ == '__main__': - import sys - from os import path - sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - - unittest.main() diff --git a/test/test_merkle.py b/test/test_merkle.py deleted file mode 100644 index b5537a9..0000000 --- a/test/test_merkle.py +++ /dev/null @@ -1,118 +0,0 @@ -## Copyright (c) 2016-2018 Clearmatics Technologies Ltd -## SPDX-License-Identifier: LGPL-3.0+ - -#!/usr/bin/env python -""" -Test Merkle: -Tests the functionality of the merkle.py -""" -import unittest - -from ion.merkle import merkle_tree, merkle_path, merkle_proof - -EXPECTED_TREE = [ - [ - 8568612641526826488487436752726739043287191320122540356069953783894380777505L, - 8763638472773768691201326883407021568462294246273894496415427229083082408032L, - 19224855404247632006917173431419498680506051063941070371722880450128577361118L, - 61795459977501490647348212754130855970016313872340374962921336716751708851142L, - 64645341593328157176709656265449880868558868673380425455960412802858937540801L, - 74330811247603495249613868516695563873247293176611122272199330092769797099053L, - 78469846343542442363028680824980501212021332975324075417961003849793346933925L, - 75317570447191171753008806478868650352148013528306361601609880810432714200529L - ], - [ - 6560824545851281876686151142367952893930617484325436481370811303698242675212L, - 14094329272021934754728783365468382816047630355461653340632553426278198853241L, - 25919299780512511508061958642305261009583198324725036212440752482930702519878L, - 11791415309425995046749154607832041856871129882141188736462372751874115368248L - ], - [ - 22114525030336665972036957912787127870644756898138077124815002206627656645846L, - 74561778027252859083209130121920474961655350982938755244738788717578708084930L - ], - [ - 5587813875922595628752214729735723034111050560116231646359963981668986135460L - ] - ] - -EXPECTED_ROOT = 5587813875922595628752214729735723034111050560116231646359963981668986135460L - -EXPECTED_PATHS = [ - [ - 19224855404247632006917173431419498680506051063941070371722880450128577361118L, - 6560824545851281876686151142367952893930617484325436481370811303698242675212L, - 103509800336581907939101876374092451924972847149348896254603184719556990494914L - ], - [ - 104265592756520220608901552731040627315465509694716502611474276812410996610513L, - 25919299780512511508061958642305261009583198324725036212440752482930702519878L, - 22114525030336665972036957912787127870644756898138077124815002206627656645846L - ], - [ - 90743482286830539503240959006302832933333810038750515972785732718729991261126L, - 6560824545851281876686151142367952893930617484325436481370811303698242675212L, - 103509800336581907939101876374092451924972847149348896254603184719556990494914L - ], - [ - 8568612641526826488487436752726739043287191320122540356069953783894380777505L, - 43042351581350983610621529617640359779365126521871794350496949428256481263225L, - 103509800336581907939101876374092451924972847149348896254603184719556990494914L - ], - [ - 103278833556932544105506614768867540836564789343021263282063726094748079509037L, - 40739437618755043902641900860004018820188626048551329746326768753852397778232L, - 22114525030336665972036957912787127870644756898138077124815002206627656645846L - ], - [ - 64645341593328157176709656265449880868558868673380425455960412802858937540801L, - 40739437618755043902641900860004018820188626048551329746326768753852397778232L, - 22114525030336665972036957912787127870644756898138077124815002206627656645846L - ], - [ - 37711660782102817547094073135578998531779790412684035506279823231061364818016L, - 43042351581350983610621529617640359779365126521871794350496949428256481263225L, - 103509800336581907939101876374092451924972847149348896254603184719556990494914L - ] - ] - -TEST_DATA = ["1","2","3","4","5","6","7"] - -class MerkleTest(unittest.TestCase): - """ - Test Merkle Class - """ - - def test_merkle_tree(self): - """ - Test merkle tree generation - """ - print("\nTest: Merkle tree generation") - tree, root = merkle_tree(TEST_DATA) - self.assertTrue(tree == EXPECTED_TREE) - self.assertTrue(root == EXPECTED_ROOT) - print("Test: Merkle tree generation success") - - def test_merkle_paths(self): - """ - Test item path generation - """ - print("\nTest: Merkle path generation") - for index, leaf in enumerate(TEST_DATA): - path = merkle_path(leaf, EXPECTED_TREE) - self.assertTrue(path == EXPECTED_PATHS[index]) - - print("Test: Merkle path generation success") - - def test_merkle_proof(self): - """ - Test item paths generated are valid - """ - print("\nTest: Merkle proof generation") - for index, leaf in enumerate(TEST_DATA): - path = merkle_path(leaf, EXPECTED_TREE) - - valid = merkle_proof(leaf, path, EXPECTED_ROOT) - self.assertTrue(valid == True) - - print("Test: Merkle proof generation success") diff --git a/test/token.js b/test/token.js deleted file mode 100644 index bc9dff2..0000000 --- a/test/token.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -'use strict'; - -const BigNumber = web3.BigNumber; - -const should = require('chai') - .use(require('chai-as-promised')) - .use(require('chai-bignumber')(BigNumber)) - .should(); - -const Token = artifacts.require("Token"); - -contract('Token', (accounts) => { - let token; - let token_owner; - - beforeEach(async function() { - token = await Token.new(); - }); - - it("should return the correct totalSupply after construction", async function() - { - const totalSupply = await token.totalSupply(); - totalSupply.should.be.bignumber.equal(new BigNumber(0)); - }); - - - it('should throw an error when trying to transfer to 0x0', async function() - { - await token.mint(500); - - await token.transfer(0x0, 100, {from:accounts[1]}).should.be.rejected; - }); - - it('should throw an error when trying to transfer more than balance', async function() { - (await token.balanceOf(accounts[0], {from:accounts[0]})).should.be.bignumber.equal(new BigNumber(0)); - await token.mint(500, {from:accounts[0]}); - - (await token.balanceOf(accounts[0], {from:accounts[0]})).should.be.bignumber.equal(new BigNumber(500)); - await token.transfer(accounts[1], 501, {from:accounts[0]}).should.be.rejected; - - await token.transfer(accounts[1], 500, {from:accounts[0]}); - (await token.balanceOf(accounts[0], {from:accounts[0]})).should.be.bignumber.equal(new BigNumber(0)); - }); -}); From 9c50c89031609b7cc7238bcafb058ee38bc18fce Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 15 Jun 2018 16:55:56 +0100 Subject: [PATCH 002/203] Ion Relay contract initial commit. Includes chain registration and block submission. Ion tests included. Included a python tool that returns RLP encoded blocks, block hashes and transactions. --- __main__.py | 2 + contracts/EventConsumable.sol | 7 + contracts/EventConsuming.sol | 7 + contracts/Function.sol | 18 + contracts/Ion.sol | 145 ++++++ contracts/IonCompatible.sol | 7 + contracts/RLP.sol | 414 +++++++++++++++ test/helpers/encoder.js | 78 +++ test/ion.js | 127 +++++ tooling/__init__.py | 0 tooling/__main__.py | 4 + tooling/crypto.py | 85 +++ tooling/encoder.py | 86 ++++ tooling/ethrpc.py | 938 ++++++++++++++++++++++++++++++++++ tooling/ion.py | 38 ++ tooling/utils.py | 117 +++++ 16 files changed, 2073 insertions(+) create mode 100644 __main__.py create mode 100644 contracts/EventConsumable.sol create mode 100644 contracts/EventConsuming.sol create mode 100644 contracts/Function.sol create mode 100644 contracts/Ion.sol create mode 100644 contracts/IonCompatible.sol create mode 100644 contracts/RLP.sol create mode 100644 test/helpers/encoder.js create mode 100644 test/ion.js create mode 100644 tooling/__init__.py create mode 100644 tooling/__main__.py create mode 100644 tooling/crypto.py create mode 100644 tooling/encoder.py create mode 100644 tooling/ethrpc.py create mode 100644 tooling/ion.py create mode 100644 tooling/utils.py diff --git a/__main__.py b/__main__.py new file mode 100644 index 0000000..f1bfaac --- /dev/null +++ b/__main__.py @@ -0,0 +1,2 @@ +from tooling.__main__ import commands +commands.main() \ No newline at end of file diff --git a/contracts/EventConsumable.sol b/contracts/EventConsumable.sol new file mode 100644 index 0000000..0004fb2 --- /dev/null +++ b/contracts/EventConsumable.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.0; + +contract EventConsumable { + function EventConsumable(){ + + } +} diff --git a/contracts/EventConsuming.sol b/contracts/EventConsuming.sol new file mode 100644 index 0000000..fe9885b --- /dev/null +++ b/contracts/EventConsuming.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.0; + +contract EventConsuming { + function EventConsuming(){ + + } +} diff --git a/contracts/Function.sol b/contracts/Function.sol new file mode 100644 index 0000000..85132e7 --- /dev/null +++ b/contracts/Function.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.24; + +import "./EventConsuming.sol"; + +contract FunctionConsumesEvent is EventConsuming { + constructor(address _ionCompAddress) EventConsuming(_ionCompAddress) {} + + event Executed(); + + function execute() IonCompatibleOnly { + emit Executed(); + } + + function CheckReceipt() IonCompatibleOnly { + + ion.CheckReceiptProof(); + } +} diff --git a/contracts/Ion.sol b/contracts/Ion.sol new file mode 100644 index 0000000..72fd4aa --- /dev/null +++ b/contracts/Ion.sol @@ -0,0 +1,145 @@ +pragma solidity ^0.4.23; + +import "./RLP.sol"; + +contract Ion { + using RLP for RLP.RLPItem; + using RLP for RLP.Iterator; + using RLP for bytes; + + struct BlockHeader { + bytes32 prevBlockHash; + bytes32 txRootHash; + bytes32 receiptRootHash; + } + + bytes32 public chainId; + bytes32[] public chains; + mapping (bytes32 => bytes32[]) public m_blockhashes; + mapping (bytes32 => BlockHeader) public m_blockheaders; + + /* + * Constructor + * param: id (bytes32) Unique id to identify this chain that the contract is being deployed to. + * + * Supplied with a unique id to identify this chain to others that may interoperate with it. + * The deployer must assert that the id is indeed public and that it is not already being used + * by another chain + */ + constructor(bytes32 _id) public { + chainId = _id; + } + +/* +======================================================================================================================== + + Modifiers + +======================================================================================================================== +*/ + + /* + * onlyRegisteredChains + * param: _id (bytes32) Unique id of chain supplied to function + * + * Modifier that checks if the provided chain id has been registered to this contract + */ + modifier onlyRegisteredChains(bytes32 _id) { + bool chainRegistered = false; + for (uint i = 0; i < chains.length; i++) { + if (_id == chains[i]) { + chainRegistered = true; + break; + } + } + require(chainRegistered, "Chain is not registered"); + _; + } + +/* +======================================================================================================================== + + Functions + +======================================================================================================================== +*/ + + /* + * RegisterChain + * param: chainId (bytes32) Unique id of another chain to interoperate with + * + * Supplied with an id of another chain, checks if this id already exists in the known set of ids + * and adds it to the list of known chains. + */ + function RegisterChain(bytes32 _id) public { + require( _id != chainId, "Cannot add this chain id to chain register" ); + for (uint i = 0; i < chains.length; i++) { + require( chains[i] != _id, "Chain already exists" ); + } + chains.push(_id); + } + + /* + * SubmitBlock + * param: _id (bytes32) Unique id of chain submitting block from + * param: _blockHash (bytes32) Block hash of block being submitted + * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain + * + * Submission of block headers from another chain, deconstructed and persisted as BlockHeader structs defined above + * and adds it to the list of known block hashes and headers of specified chain. + */ + function SubmitBlock(bytes32 _id, bytes32 _blockHash, bytes _rlpBlockHeader) onlyRegisteredChains(_id) public { + RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); + + bytes32 hashedHeader = keccak256(_rlpBlockHeader); + require( hashedHeader == _blockHash ); + + BlockHeader storage blockHeader = m_blockheaders[_blockHash]; + blockHeader.prevBlockHash = bytesToBytes32(header[0].toBytes(), 1); + blockHeader.txRootHash = bytesToBytes32(header[4].toBytes(), 1); + blockHeader.receiptRootHash = bytesToBytes32(header[5].toBytes(), 1); + + addBlockHashToChain(_id, _blockHash); + } + + function CheckTxProof() public { + } + + function CheckReceiptProof() public { + } + + function CheckRootsProof() public { + } + + + function addBlockHashToChain(bytes32 _chainId, bytes32 _hash) internal { + bytes32[] storage blockHashes = m_blockhashes[_chainId]; + + for (uint i = 0; i < blockHashes.length; i++) { + require( blockHashes[i] != _hash ); + } + blockHashes.push(_hash); + } + + function getBlockHeader(bytes32 _blockHash) public view returns (bytes32[3]) { + BlockHeader storage header = m_blockheaders[_blockHash]; + + return [header.prevBlockHash, header.txRootHash, header.receiptRootHash]; + } +/* +======================================================================================================================== + + Helper Functions + +======================================================================================================================== +*/ + function bytesToBytes32(bytes b, uint offset) private pure returns (bytes32) { + bytes32 out; + + for (uint i = 0; i < 32; i++) { + out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); + } + return out; + } +} + diff --git a/contracts/IonCompatible.sol b/contracts/IonCompatible.sol new file mode 100644 index 0000000..2c1a236 --- /dev/null +++ b/contracts/IonCompatible.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.0; + +contract IonCompatible { + function IonCompatible(){ + + } +} diff --git a/contracts/RLP.sol b/contracts/RLP.sol new file mode 100644 index 0000000..9967e65 --- /dev/null +++ b/contracts/RLP.sol @@ -0,0 +1,414 @@ +/** +* @title RLPReader +* +* RLPReader is used to read and parse RLP encoded data in memory. +* +* @author Andreas Olofsson (androlo1980@gmail.com) from https://github.com/androlo/standard-contracts/blob/master/contracts/src/codec/RLP.sol +*/ +library RLP { + + uint constant DATA_SHORT_START = 0x80; + uint constant DATA_LONG_START = 0xB8; + uint constant LIST_SHORT_START = 0xC0; + uint constant LIST_LONG_START = 0xF8; + + uint constant DATA_LONG_OFFSET = 0xB7; + uint constant LIST_LONG_OFFSET = 0xF7; + + + struct RLPItem { + uint _unsafe_memPtr; // Pointer to the RLP-encoded bytes. + uint _unsafe_length; // Number of bytes. This is the full length of the string. + } + + struct Iterator { + RLPItem _unsafe_item; // Item that's being iterated over. + uint _unsafe_nextPtr; // Position of the next item in the list. + } + + /* Iterator */ + + function next(Iterator memory self) internal constant returns (RLPItem memory subItem) { + if(hasNext(self)) { + var ptr = self._unsafe_nextPtr; + var itemLength = _itemLength(ptr); + subItem._unsafe_memPtr = ptr; + subItem._unsafe_length = itemLength; + self._unsafe_nextPtr = ptr + itemLength; + } + else + revert(); + } + + function next(Iterator memory self, bool strict) internal constant returns (RLPItem memory subItem) { + subItem = next(self); + if(strict && !_validate(subItem)) + revert(); + return; + } + + function hasNext(Iterator memory self) internal constant returns (bool) { + var item = self._unsafe_item; + return self._unsafe_nextPtr < item._unsafe_memPtr + item._unsafe_length; + } + + /* RLPItem */ + + /// @dev Creates an RLPItem from an array of RLP encoded bytes. + /// @param self The RLP encoded bytes. + /// @return An RLPItem + function toRLPItem(bytes memory self) internal constant returns (RLPItem memory) { + uint len = self.length; + if (len == 0) { + return RLPItem(0, 0); + } + uint memPtr; + assembly { + memPtr := add(self, 0x20) + } + return RLPItem(memPtr, len); + } + + /// @dev Creates an RLPItem from an array of RLP encoded bytes. + /// @param self The RLP encoded bytes. + /// @param strict Will revert() if the data is not RLP encoded. + /// @return An RLPItem + function toRLPItem(bytes memory self, bool strict) internal constant returns (RLPItem memory) { + var item = toRLPItem(self); + if(strict) { + uint len = self.length; + if(_payloadOffset(item) > len) + revert(); + if(_itemLength(item._unsafe_memPtr) != len) + revert(); + if(!_validate(item)) + revert(); + } + return item; + } + + /// @dev Check if the RLP item is null. + /// @param self The RLP item. + /// @return 'true' if the item is null. + function isNull(RLPItem memory self) internal constant returns (bool ret) { + return self._unsafe_length == 0; + } + + /// @dev Check if the RLP item is a list. + /// @param self The RLP item. + /// @return 'true' if the item is a list. + function isList(RLPItem memory self) internal constant returns (bool ret) { + if (self._unsafe_length == 0) + return false; + uint memPtr = self._unsafe_memPtr; + assembly { + ret := iszero(lt(byte(0, mload(memPtr)), 0xC0)) + } + } + + /// @dev Check if the RLP item is data. + /// @param self The RLP item. + /// @return 'true' if the item is data. + function isData(RLPItem memory self) internal constant returns (bool ret) { + if (self._unsafe_length == 0) + return false; + uint memPtr = self._unsafe_memPtr; + assembly { + ret := lt(byte(0, mload(memPtr)), 0xC0) + } + } + + /// @dev Check if the RLP item is empty (string or list). + /// @param self The RLP item. + /// @return 'true' if the item is null. + function isEmpty(RLPItem memory self) internal constant returns (bool ret) { + if(isNull(self)) + return false; + uint b0; + uint memPtr = self._unsafe_memPtr; + assembly { + b0 := byte(0, mload(memPtr)) + } + return (b0 == DATA_SHORT_START || b0 == LIST_SHORT_START); + } + + /// @dev Get the number of items in an RLP encoded list. + /// @param self The RLP item. + /// @return The number of items. + function items(RLPItem memory self) internal constant returns (uint) { + if (!isList(self)) + return 0; + uint b0; + uint memPtr = self._unsafe_memPtr; + assembly { + b0 := byte(0, mload(memPtr)) + } + uint pos = memPtr + _payloadOffset(self); + uint last = memPtr + self._unsafe_length - 1; + uint itms; + while(pos <= last) { + pos += _itemLength(pos); + itms++; + } + return itms; + } + + /// @dev Create an iterator. + /// @param self The RLP item. + /// @return An 'Iterator' over the item. + function iterator(RLPItem memory self) internal constant returns (Iterator memory it) { + if (!isList(self)) + revert(); + uint ptr = self._unsafe_memPtr + _payloadOffset(self); + it._unsafe_item = self; + it._unsafe_nextPtr = ptr; + } + + /// @dev Return the RLP encoded bytes. + /// @param self The RLPItem. + /// @return The bytes. + function toBytes(RLPItem memory self) internal constant returns (bytes memory bts) { + var len = self._unsafe_length; + if (len == 0) + return; + bts = new bytes(len); + _copyToBytes(self._unsafe_memPtr, bts, len); + } + + /// @dev Decode an RLPItem into bytes. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toData(RLPItem memory self) internal constant returns (bytes memory bts) { + if(!isData(self)) + revert(); + var (rStartPos, len) = _decode(self); + bts = new bytes(len); + _copyToBytes(rStartPos, bts, len); + } + + /// @dev Get the list of sub-items from an RLP encoded list. + /// Warning: This is inefficient, as it requires that the list is read twice. + /// @param self The RLP item. + /// @return Array of RLPItems. + function toList(RLPItem memory self) internal constant returns (RLPItem[] memory list) { + if(!isList(self)) + revert(); + var numItems = items(self); + list = new RLPItem[](numItems); + var it = iterator(self); + uint idx; + while(hasNext(it)) { + list[idx] = next(it); + idx++; + } + } + + /// @dev Decode an RLPItem into an ascii string. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toAscii(RLPItem memory self) internal constant returns (string memory str) { + if(!isData(self)) + revert(); + var (rStartPos, len) = _decode(self); + bytes memory bts = new bytes(len); + _copyToBytes(rStartPos, bts, len); + str = string(bts); + } + + /// @dev Decode an RLPItem into a uint. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toUint(RLPItem memory self) internal constant returns (uint data) { + if(!isData(self)) + revert(); + var (rStartPos, len) = _decode(self); + if (len > 32 || len == 0) + revert(); + assembly { + data := div(mload(rStartPos), exp(256, sub(32, len))) + } + } + + /// @dev Decode an RLPItem into a boolean. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toBool(RLPItem memory self) internal constant returns (bool data) { + if(!isData(self)) + revert(); + var (rStartPos, len) = _decode(self); + if (len != 1) + revert(); + uint temp; + assembly { + temp := byte(0, mload(rStartPos)) + } + if (temp > 1) + revert(); + return temp == 1 ? true : false; + } + + /// @dev Decode an RLPItem into a byte. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toByte(RLPItem memory self) internal constant returns (byte data) { + if(!isData(self)) + revert(); + var (rStartPos, len) = _decode(self); + if (len != 1) + revert(); + uint temp; + assembly { + temp := byte(0, mload(rStartPos)) + } + return byte(temp); + } + + /// @dev Decode an RLPItem into an int. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toInt(RLPItem memory self) internal constant returns (int data) { + return int(toUint(self)); + } + + /// @dev Decode an RLPItem into a bytes32. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toBytes32(RLPItem memory self) internal constant returns (bytes32 data) { + return bytes32(toUint(self)); + } + + /// @dev Decode an RLPItem into an address. This will not work if the + /// RLPItem is a list. + /// @param self The RLPItem. + /// @return The decoded string. + function toAddress(RLPItem memory self) internal constant returns (address data) { + if(!isData(self)) + revert(); + var (rStartPos, len) = _decode(self); + if (len != 20) + revert(); + assembly { + data := div(mload(rStartPos), exp(256, 12)) + } + } + + // Get the payload offset. + function _payloadOffset(RLPItem memory self) private constant returns (uint) { + if(self._unsafe_length == 0) + return 0; + uint b0; + uint memPtr = self._unsafe_memPtr; + assembly { + b0 := byte(0, mload(memPtr)) + } + if(b0 < DATA_SHORT_START) + return 0; + if(b0 < DATA_LONG_START || (b0 >= LIST_SHORT_START && b0 < LIST_LONG_START)) + return 1; + if(b0 < LIST_SHORT_START) + return b0 - DATA_LONG_OFFSET + 1; + return b0 - LIST_LONG_OFFSET + 1; + } + + // Get the full length of an RLP item. + function _itemLength(uint memPtr) private constant returns (uint len) { + uint b0; + assembly { + b0 := byte(0, mload(memPtr)) + } + if (b0 < DATA_SHORT_START) + len = 1; + else if (b0 < DATA_LONG_START) + len = b0 - DATA_SHORT_START + 1; + else if (b0 < LIST_SHORT_START) { + assembly { + let bLen := sub(b0, 0xB7) // bytes length (DATA_LONG_OFFSET) + let dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length + len := add(1, add(bLen, dLen)) // total length + } + } + else if (b0 < LIST_LONG_START) + len = b0 - LIST_SHORT_START + 1; + else { + assembly { + let bLen := sub(b0, 0xF7) // bytes length (LIST_LONG_OFFSET) + let dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length + len := add(1, add(bLen, dLen)) // total length + } + } + } + + // Get start position and length of the data. + function _decode(RLPItem memory self) private constant returns (uint memPtr, uint len) { + if(!isData(self)) + revert(); + uint b0; + uint start = self._unsafe_memPtr; + assembly { + b0 := byte(0, mload(start)) + } + if (b0 < DATA_SHORT_START) { + memPtr = start; + len = 1; + return; + } + if (b0 < DATA_LONG_START) { + len = self._unsafe_length - 1; + memPtr = start + 1; + } else { + uint bLen; + assembly { + bLen := sub(b0, 0xB7) // DATA_LONG_OFFSET + } + len = self._unsafe_length - 1 - bLen; + memPtr = start + bLen + 1; + } + return; + } + + // Assumes that enough memory has been allocated to store in target. + function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private constant { + // Exploiting the fact that 'tgt' was the last thing to be allocated, + // we can write entire words, and just overwrite any excess. + assembly { + { + let i := 0 // Start at arr + 0x20 + let words := div(add(btsLen, 31), 32) + let rOffset := btsPtr + let wOffset := add(tgt, 0x20) + tag_loop: + jumpi(end, eq(i, words)) + { + let offset := mul(i, 0x20) + mstore(add(wOffset, offset), mload(add(rOffset, offset))) + i := add(i, 1) + } + jump(tag_loop) + end: + mstore(add(tgt, add(0x20, mload(tgt))), 0) + } + } + } + + // Check that an RLP item is valid. + function _validate(RLPItem memory self) private constant returns (bool ret) { + // Check that RLP is well-formed. + uint b0; + uint b1; + uint memPtr = self._unsafe_memPtr; + assembly { + b0 := byte(0, mload(memPtr)) + b1 := byte(1, mload(memPtr)) + } + if(b0 == DATA_SHORT_START + 1 && b1 < DATA_SHORT_START) + return false; + return true; + } +} \ No newline at end of file diff --git a/test/helpers/encoder.js b/test/helpers/encoder.js new file mode 100644 index 0000000..188e10b --- /dev/null +++ b/test/helpers/encoder.js @@ -0,0 +1,78 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Web3 = require('web3'); +const Web3Utils = require('web3-utils'); +const Web3Abi = require('web3-eth-abi'); +const rlp = require('rlp'); + +const web3 = new Web3(); + +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); + +function hexToBytes(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + +function bytesToHex(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(""); +} + + +const block = web3.eth.getBlock(7); +console.log("\n\n\n\nBlock = " + JSON.stringify(block)) +// Decompose the values in the block to hash +const parentHash = block.parentHash; +const sha3Uncles = block.sha3Uncles; +const coinbase = block.miner; +const root = block.stateRoot; +const txHash = block.transactionsRoot; +const receiptHash = block.receiptsRoot; +const logsBloom = block.logsBloom; +const difficulty = Web3Utils.toBN(block.difficulty); +const number = Web3Utils.toBN(block.number); +const gasLimit = block.gasLimit; +const gasUsed = block.gasUsed; +const timestamp = Web3Utils.toBN(block.timestamp); +const extraData = block.extraData; +const mixHash = block.mixHash; +const nonce = block.nonce; + +// Remove last 65 Bytes of extraData +const extraBytes = hexToBytes(extraData); +const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); +const extraDataShort = '0x' + bytesToHex(extraBytesShort); + +const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraData, + mixHash, + nonce +]; + +const encodedHeader = rlp.encode(header); + +const headerHash = Web3Utils.sha3(encodedHeader); + +console.log("\n\n\nRLP-encoded header: " +bytesToHex(encodedHeader)); +console.log("\n\n\nHashed header: " +headerHash) +console.log("\n\n\nExpected hash: " +block.hash) +console.log("\n\n\n" + ((rlp.encode(parentHash)))) \ No newline at end of file diff --git a/test/ion.js b/test/ion.js new file mode 100644 index 0000000..1ee4c31 --- /dev/null +++ b/test/ion.js @@ -0,0 +1,127 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Web3Utils = require('web3-utils'); +const BN = require('bignumber.js') +const merkle = require('./helpers/merkle.js') + +const Ion = artifacts.require("Ion"); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" + +const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" +const TESTBLOCK = { + difficulty: 2, + extraData: "0xd88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01", + gasLimit: 939056936520814100, + gasUsed: 26920, + hash: "0xe40cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", + logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + miner: "0x0000000000000000000000000000000000000000", + mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000", + nonce: "0x0000000000000000", + number: 210, + parentHash: "0xf4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72", + receiptsRoot: "0x5ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845", + sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + size: 756, + stateRoot: "0x19ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161ed", + timestamp: 1529069678, + totalDifficulty: 421, + transactions: ["0x93f687edff8cf04c60b177b47ddcd8861c795664e5af1da9116b62d06e91694b"], + transactionsRoot: "0x87c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464", + uncles: [] +} +const TESTRLPENCODING = "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + +contract('Ion.js', (accounts) => { + it('Deploy Ion', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + let chainId = await ion.chainId(); + + assert.equal(chainId, DEPLOYEDCHAINID); + }) + + it('Register Chain', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + // Successfully add id of another chain + await ion.RegisterChain(TESTCHAINID); + let chain = await ion.chains.call(0); + + assert.equal(chain, TESTCHAINID); + + // Fail adding id of this chain + await ion.RegisterChain(DEPLOYEDCHAINID).should.be.rejected; + + // Fail adding id of chain already registered + await ion.RegisterChain(TESTCHAINID).should.be.rejected; + }) + + it('Submit Block', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + // Submit block should succeed + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) + + let blockHash = await ion.m_blockhashes(TESTCHAINID, 0); + let header = await ion.getBlockHeader.call(blockHash); + + // Separate fetched header info + parentHash = header[0]; + txRootHash = header[1]; + receiptRootHash = header[2]; + + // Assert that block was persisted correctly + assert.equal(blockHash, TESTBLOCK.hash); + assert.equal(parentHash, TESTBLOCK.parentHash); + assert.equal(txRootHash, TESTBLOCK.transactionsRoot); + assert.equal(receiptRootHash, TESTBLOCK.receiptsRoot); + }) + + it('Fail Submit Block from unknown chain', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", "0xe40cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000").should.be.rejected; + }) + + it('Fail Submit Block with wrong block hash', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID, "0xe4" + "1" + "cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000").should.be.rejected; + }) + + it('Check Tx Proof', () => { + + }) + + it('Fail Tx Proof', () => { + + }) + + it('Check Receipt Proof', () => { + + }) + + it('Fail Receipt Proof', () => { + + }) + + it('Check Roots Proof', () => { + + }) + + it('Fail Roots Proof', () => { + + }) +}) diff --git a/tooling/__init__.py b/tooling/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tooling/__main__.py b/tooling/__main__.py new file mode 100644 index 0000000..b65e517 --- /dev/null +++ b/tooling/__main__.py @@ -0,0 +1,4 @@ +from .ion import commands + +if __name__ == "__main__": + commands.main() \ No newline at end of file diff --git a/tooling/crypto.py b/tooling/crypto.py new file mode 100644 index 0000000..25a576c --- /dev/null +++ b/tooling/crypto.py @@ -0,0 +1,85 @@ +## Copyright (c) 2016-2018 Clearmatics Technologies Ltd +## SPDX-License-Identifier: LGPL-3.0+ + +#!/usr/bin/env python +""" +Crypto: Has a load of useful crypto stuff +""" +from collections import namedtuple + +from ethereum.utils import big_endian_to_int, encode_int32 +from rlp.utils import ascii_chr + +from sha3 import keccak_256 + +from .utils import Marshalled, u256be, safe_ord + +try: + import coincurve +except ImportError: + from py_ecc.secp256k1 import ecdsa_raw_recover, ecdsa_raw_sign + import warnings + warnings.warn('could not import coincurve', ImportWarning) + coincurve = None + + +# -------------------------------------------------------------------- +# Datatypes + + +_EcdsaSignatureStruct = namedtuple('EcdsaSignature', ('v', 'r', 's')) + + +class EcdsaSignature(_EcdsaSignatureStruct, Marshalled): + def __init__(self, *args, **kwa): + _EcdsaSignatureStruct.__init__(*args, **kwa) + + def dump(self): + # TODO: make same format as coincurve 65 byte str + return ''.join([chr(self.v), self.r, self.s]) + + def recover(self, rawhash): + assert isinstance(self, EcdsaSignature) + v, r, s = self + if coincurve and hasattr(coincurve, "PublicKey"): + try: + pk = coincurve.PublicKey.from_signature_and_message( + ''.join([r, s, ascii_chr(v - 27)]), + rawhash, + hasher=None, + ) + pub = pk.format(compressed=False)[1:] + except BaseException: + pub = b"\x00" * 64 + else: + r = big_endian_to_int(r) + s = big_endian_to_int(s) + result = ecdsa_raw_recover(rawhash, (v, r, s)) + if result: + x, y = result + pub = encode_int32(x) + encode_int32(y) + else: + raise ValueError('Invalid VRS') + assert len(pub) == 64 + + # Convert to Ethereum address + return keccak_256(pub).digest()[12:] + + +# -------------------------------------------------------------------- +# ECDSA signature and address recovery + + +def ecdsa_sign(rawhash, key): + # type: (bytes, bytes) -> EcdsaSignature + if coincurve and hasattr(coincurve, 'PrivateKey'): + pk = coincurve.PrivateKey(key) + signature = pk.sign_recoverable(rawhash, hasher=None) + v = safe_ord(signature[64]) + 27 + r = signature[0:32] + s = signature[32:64] + else: + v, r, s = ecdsa_raw_sign(rawhash, key) + r = u256be(r) + s = u256be(s) + return EcdsaSignature(v, r, s) \ No newline at end of file diff --git a/tooling/encoder.py b/tooling/encoder.py new file mode 100644 index 0000000..926136a --- /dev/null +++ b/tooling/encoder.py @@ -0,0 +1,86 @@ +import rlp +from .ethrpc import EthJsonRpc +from ethereum.utils import sha3 +from .utils import require + +class Block(object): + def __init__(self, block_json): + self.parent_hash = hexstring_to_bytes(block_json['parentHash']) + self.sha3_uncles = hexstring_to_bytes(block_json['sha3Uncles']) + self.coinbase = hexstring_to_bytes(block_json['miner']) + self.root = hexstring_to_bytes(block_json['stateRoot']) + self.tx_hash = hexstring_to_bytes(block_json['transactionsRoot']) + self.receipt_hash = hexstring_to_bytes(block_json['receiptsRoot']) + self.bloom = hexstring_to_bytes(block_json['logsBloom']) + self.difficulty = hexstring_to_bytes(block_json['difficulty']) + self.number = hexstring_to_bytes(block_json['number']) + self.gas_limit = hexstring_to_bytes(block_json['gasLimit']) + self.gas_used = hexstring_to_bytes(block_json['gasUsed']) + self.timestamp = hexstring_to_bytes(block_json['timestamp']) + self.extra_data = hexstring_to_bytes(block_json['extraData']) + self.mix = hexstring_to_bytes(block_json['mixHash']) + self.nonce = hexstring_to_bytes(block_json['nonce']) + self.transactions = block_json['transactions'] + + @property + def header(self): + return [ + self.parent_hash, + self.sha3_uncles, + self.coinbase, + self.root, + self.tx_hash, + self.receipt_hash, + self.bloom, + self.difficulty, + self.number, + self.gas_limit, + self.gas_used, + self.timestamp, + self.extra_data, + self.mix, + self.nonce + ] + + +# Converts hex string into a bytes of the hex representation from "0x..." to b'\x...' +# If value is less than a byte, returns as int +def hexstring_to_bytes(hex): + try: + return bytes.fromhex(hex[2:]) + except ValueError: + return int(hex, 16) + +class RLPEncoder(object): + def __init__(self, host, port, tls=False): + self.rpc = EthJsonRpc(host, port, tls) + + def get_block_by_number(self, n): + block = self.rpc.eth_getBlockByNumber(n) + return block + + def get_block_by_hash(self, h): + block = self.rpc.eth_getBlockByHash(h) + return block + + def get_block(self, x): + if isinstance(x, int): + return self.get_block_by_number(x) + elif isinstance(x, str): + return self.get_block_by_hash(x) + else: + raise Exception("Must supply number or hash") + + def get_transactions(self, block): + block = Block(block) + return block.transactions + + def encode_block(self, block): + return rlp.encode(Block(block).header) + + def hash_block_header(self, block): + encoded = self.encode_block(block) + hash = sha3(encoded).hex() + require('0x'+hash == block['hash'], "Block hash and hashed header do not match:\n{} expected\n{} acquired".format(block['hash'], '0x'+hash)) + + return hash \ No newline at end of file diff --git a/tooling/ethrpc.py b/tooling/ethrpc.py new file mode 100644 index 0000000..1c92b7f --- /dev/null +++ b/tooling/ethrpc.py @@ -0,0 +1,938 @@ +""" +For licensing information, see: + +https://github.com/ConsenSys/ethjsonrpc/blob/master/LICENSE + +This file contains the public domain interface definition +""" + +import json +import requests +import time +import warnings +from collections import namedtuple +from ethereum.abi import encode_abi, decode_abi +from requests.adapters import HTTPAdapter +from requests.exceptions import ConnectionError as RequestsConnectionError + +from .crypto import keccak_256 +from .utils import require, big_endian_to_int, zpad, encode_int + +GETH_DEFAULT_RPC_PORT = 8545 +ETH_DEFAULT_RPC_PORT = 8545 +PARITY_DEFAULT_RPC_PORT = 8545 +PYETHAPP_DEFAULT_RPC_PORT = 4000 +MAX_RETRIES = 3 +JSON_MEDIA_TYPE = 'application/json' + + +BLOCK_TAG_EARLIEST = 'earliest' +BLOCK_TAG_LATEST = 'latest' +BLOCK_TAG_PENDING = 'pending' +BLOCK_TAGS = ( + BLOCK_TAG_EARLIEST, + BLOCK_TAG_LATEST, + BLOCK_TAG_PENDING, +) + + +class EthJsonRpcError(Exception): + pass + + +class ConnectionError(EthJsonRpcError): + pass + + +class BadStatusCodeError(EthJsonRpcError): + pass + + +class BadJsonError(EthJsonRpcError): + pass + + +class BadResponseError(EthJsonRpcError): + pass + + + + +def hex_to_dec(x): + ''' + Convert hex to decimal + ''' + return int(x, 16) + + +def clean_hex(d): + ''' + Convert decimal to hex and remove the "L" suffix that is appended to large + numbers + ''' + return hex(d).rstrip('L') + +def validate_block(block): + if isinstance(block, str): + if block not in BLOCK_TAGS: + raise ValueError('invalid block tag') + if isinstance(block, int): + block = hex(block) + return block + + +def wei_to_ether(wei): + ''' + Convert wei to ether + ''' + return 1.0 * wei / 10**18 + + +def ether_to_wei(ether): + ''' + Convert ether to wei + ''' + return ether * 10**18 + + +class EthTransaction(namedtuple('_TxStruct', ('rpc', 'txid'))): + def receipt(self, wait=False, tick_fn=None): + first = True + while True: + receipt = self.rpc.eth_getTransactionReceipt(self.txid) + # TODO: turn into asynchronous notification / future + if receipt: + return receipt + if not wait: + break + try: + if first: + if isinstance(wait, callable): + wait() + first = False + elif tick_fn: + tick_fn(self) + time.sleep(1) + except KeyboardInterrupt: + break + + def __str__(self): + return self.txid + + +class EthJsonRpc(object): + ''' + Ethereum JSON-RPC client class + ''' + + DEFAULT_GAS_PER_TX = 900000 + DEFAULT_GAS_PRICE = 50 * 10**9 # 50 gwei + + def __init__(self, host='localhost', port=GETH_DEFAULT_RPC_PORT, tls=False): + self.host = host + self.port = port + self.tls = tls + self.session = requests.Session() + self.session.mount(self.host, HTTPAdapter(max_retries=MAX_RETRIES)) + + def _call(self, method, params=None, _id=1): + + params = params or [] + data = { + 'jsonrpc': '2.0', + 'method': method, + 'params': params, + 'id': _id, + } + scheme = 'http' + if self.tls: + scheme += 's' + url = '{}://{}:{}'.format(scheme, self.host, self.port) + headers = {'Content-Type': JSON_MEDIA_TYPE} + try: + r = self.session.post(url, headers=headers, data=json.dumps(data)) + except RequestsConnectionError: + raise ConnectionError(url) + if r.status_code / 100 != 2: + raise BadStatusCodeError(r.status_code) + try: + response = r.json() + except ValueError: + raise BadJsonError(r.text) + try: + return response['result'] + except KeyError: + raise BadResponseError(response) + + def _encode_function(self, signature, param_values): + + prefix = big_endian_to_int(keccak_256(signature.encode('utf-8')).digest()[:4]) + + if signature.find('(') == -1: + raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...') + + if signature.find(')') - signature.find('(') == 1: + return encode_int(prefix) + + types = signature[signature.find('(') + 1: signature.find(')')].split(',') + encoded_params = encode_abi(types, param_values) + return zpad(encode_int(prefix), 4) + encoded_params + + def _solproxy_bind(self, method, address, account): + ins = [_['type'] for _ in method['inputs']] + outs = [_['type'] for _ in method['outputs']] + sig = method['name'] + '(' + ','.join(ins) + ')' + # XXX: messy... + if method['constant']: + return lambda *args, **kwa: (self.call(address, sig, args, outs, **kwa) + if len(outs) > 1 else + self.call(address, sig, args, outs, **kwa)[0]) + if account is None: + # Without account, cannot call non-constant methods + return None + return lambda *args, **kwa: (self.call_with_transaction(account, address, sig, args, **kwa) + if len(outs) > 1 else + self.call_with_transaction(account, address, sig, args, **kwa)[0]) + + def proxy(self, abi, address, account=None): + # XXX: specific to Ethereum addresses, 20 octets + if len(address) == 20: + address = address.encode('hex') + require(len(address) == 40) + if account is not None: + if len(account) == 20: + account = account.encode('hex') + require(len(account) == 40) + + if isinstance(abi, file): + abi = json.load(abi) + elif isinstance(abi, str): + with open(abi) as jsonfile: + abi = json.load(jsonfile) + require(isinstance(abi, list)) + + proxy = dict() + for method in abi: + if method['type'] != 'function': + continue + + handler = self._solproxy_bind(method, address, account) + if handler is None: + continue + + sig = "%s(%s)" % (method['name'], ','.join([i['type'] for i in method['inputs']])) + sig_hash = keccak_256(bytes(sig)).hexdigest()[:8] + + # Provide an alternate, where the explicit function signature + proxy[method['name']] = handler + proxy[method['name'] + '_' + sig_hash] = handler + + return namedtuple('SolProxy', proxy.keys())(*proxy.values()) + + ################################################################################ + # high-level methods + ################################################################################ + + def transfer(self, from_, to, amount): + ''' + Send wei from one address to another + ''' + return self.eth_sendTransaction(from_address=from_, to_address=to, value=amount) + + def create_contract(self, from_, code, gas, sig=None, args=None): + ''' + Create a contract on the blockchain from compiled EVM code. Returns the + transaction hash. + ''' + from_ = from_ or self.eth_coinbase() + if sig is not None and args is not None: + types = sig[sig.find('(') + 1: sig.find(')')].split(',') + encoded_params = encode_abi(types, args) + code += encoded_params.encode('hex') + return self.eth_sendTransaction(from_address=from_, gas=gas, data=code) + + def get_contract_address(self, tx): + ''' + Get the address for a contract from the transaction that created it + ''' + receipt = self.eth_getTransactionReceipt(tx) + return receipt['contractAddress'] + + def call(self, address, sig, args, result_types): + ''' + Call a contract function on the RPC server, without sending a + transaction (useful for reading data) + ''' + data = self._encode_function(sig, args) + data_hex = data.encode('hex') + response = self.eth_call(to_address=address, data=data_hex) + # XXX: horrible hack for when RPC returns '0x0'... + if (len(result_types) == 0 or result_types[0] == 'uint256') and response == '0x0': + response = '0x' + ('0' * 64) + return decode_abi(result_types, response[2:].decode('hex')) + + def call_with_transaction(self, from_, address, sig, args, gas=None, gas_price=None, value=None): + ''' + Call a contract function by sending a transaction (useful for storing + data) + ''' + gas = gas or self.DEFAULT_GAS_PER_TX + gas_price = gas_price or self.DEFAULT_GAS_PRICE + data = self._encode_function(sig, args) + data_hex = data.encode('hex') + return self.eth_sendTransaction(from_address=from_, to_address=address, data=data_hex, gas=gas, + gas_price=gas_price, value=value) + + ################################################################################ + # JSON-RPC methods + ################################################################################ + + def web3_clientVersion(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_clientversion + + TESTED + ''' + return self._call('web3_clientVersion') + + def web3_sha3(self, data): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3 + + TESTED + ''' + data = str(data).encode('hex') + return self._call('web3_sha3', [data]) + + def net_version(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version + + TESTED + ''' + return self._call('net_version') + + def net_listening(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening + + TESTED + ''' + return self._call('net_listening') + + def net_peerCount(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peercount + + TESTED + ''' + return hex_to_dec(self._call('net_peerCount')) + + def eth_protocolVersion(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolversion + + TESTED + ''' + return self._call('eth_protocolVersion') + + def eth_syncing(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_syncing + + TESTED + ''' + return self._call('eth_syncing') + + def eth_coinbase(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase + + TESTED + ''' + return self._call('eth_coinbase') + + def eth_mining(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining + + TESTED + ''' + return self._call('eth_mining') + + def eth_hashrate(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate + + TESTED + ''' + return hex_to_dec(self._call('eth_hashrate')) + + def eth_gasPrice(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasprice + + TESTED + ''' + return hex_to_dec(self._call('eth_gasPrice')) + + def eth_accounts(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts + + TESTED + ''' + return self._call('eth_accounts') + + def eth_blockNumber(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber + + TESTED + ''' + return hex_to_dec(self._call('eth_blockNumber')) + + def eth_getBalance(self, address=None, block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance + + TESTED + ''' + address = address or self.eth_coinbase() + block = validate_block(block) + return hex_to_dec(self._call('eth_getBalance', [address, block])) + + def eth_getStorageAt(self, address=None, position=0, block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat + + TESTED + ''' + block = validate_block(block) + return self._call('eth_getStorageAt', [address, hex(position), block]) + + def eth_getTransactionCount(self, address, block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount + + TESTED + ''' + block = validate_block(block) + return hex_to_dec(self._call('eth_getTransactionCount', [address, block])) + + def eth_getBlockTransactionCountByHash(self, block_hash): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbyhash + + TESTED + ''' + return hex_to_dec(self._call('eth_getBlockTransactionCountByHash', [block_hash])) + + def eth_getBlockTransactionCountByNumber(self, block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbynumber + + TESTED + ''' + block = validate_block(block) + return hex_to_dec(self._call('eth_getBlockTransactionCountByNumber', [block])) + + def eth_getUncleCountByBlockHash(self, block_hash): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblockhash + + TESTED + ''' + return hex_to_dec(self._call('eth_getUncleCountByBlockHash', [block_hash])) + + def eth_getUncleCountByBlockNumber(self, block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblocknumber + + TESTED + ''' + block = validate_block(block) + return hex_to_dec(self._call('eth_getUncleCountByBlockNumber', [block])) + + def eth_getCode(self, address, default_block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode + + NEEDS TESTING + ''' + if isinstance(default_block, basestring): + if default_block not in BLOCK_TAGS: + raise ValueError + return self._call('eth_getCode', [address, default_block]) + + def eth_sign(self, address, data): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign + + NEEDS TESTING + ''' + return self._call('eth_sign', [address, data]) + + def eth_sendTransaction(self, to_address=None, from_address=None, gas=None, gas_price=None, value=None, data=None, + nonce=None): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction + + NEEDS TESTING + ''' + if len(to_address) == 20: + to_address = to_address.encode('hex') + if len(from_address) == 20: + from_address = from_address.encode('hex') + params = {} + params['from'] = from_address or self.eth_coinbase() + if to_address is not None: + params['to'] = to_address + if gas is not None: + params['gas'] = hex(gas) + if gas_price is not None: + params['gasPrice'] = clean_hex(gas_price) + if value is not None: + params['value'] = clean_hex(value) + if data is not None: + params['data'] = data + if nonce is not None: + params['nonce'] = hex(nonce) + txid = self._call('eth_sendTransaction', [params]) + return EthTransaction(self, txid) + + def eth_sendRawTransaction(self, data): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendrawtransaction + + NEEDS TESTING + ''' + return self._call('eth_sendRawTransaction', [data]) + + def eth_call(self, to_address, from_address=None, gas=None, gas_price=None, value=None, data=None, + default_block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call + + NEEDS TESTING + ''' + if isinstance(default_block, basestring): + if default_block not in BLOCK_TAGS: + raise ValueError + if from_address is not None and len(from_address) == 20: + from_address = from_address.encode('hex') + if len(to_address) == 20: + to_address = to_address.encode('hex') + obj = {} + obj['to'] = to_address + if from_address is not None: + obj['from'] = from_address + if gas is not None: + obj['gas'] = hex(gas) + if gas_price is not None: + obj['gasPrice'] = clean_hex(gas_price) + if value is not None: + obj['value'] = value + if data is not None: + obj['data'] = data + return self._call('eth_call', [obj, default_block]) + + def eth_estimateGas(self, to_address=None, from_address=None, gas=None, gas_price=None, value=None, data=None, + default_block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas + + NEEDS TESTING + ''' + if isinstance(default_block, basestring): + if default_block not in BLOCK_TAGS: + raise ValueError + obj = {} + if to_address is not None: + obj['to'] = to_address + if from_address is not None: + obj['from'] = from_address + if gas is not None: + obj['gas'] = hex(gas) + if gas_price is not None: + obj['gasPrice'] = clean_hex(gas_price) + if value is not None: + obj['value'] = value + if data is not None: + obj['data'] = data + return hex_to_dec(self._call('eth_estimateGas', [obj, default_block])) + + def eth_getBlockByHash(self, block_hash, tx_objects=True): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash + + TESTED + ''' + return self._call('eth_getBlockByHash', [block_hash, tx_objects]) + + def eth_getBlockByNumber(self, block=BLOCK_TAG_LATEST, tx_objects=True): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber + + TESTED + ''' + block = validate_block(block) + return self._call('eth_getBlockByNumber', [block, tx_objects]) + + def eth_getTransactionByHash(self, tx_hash): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash + + TESTED + ''' + return self._call('eth_getTransactionByHash', [tx_hash]) + + def eth_getTransactionByBlockHashAndIndex(self, block_hash, index=0): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblockhashandindex + + TESTED + ''' + return self._call('eth_getTransactionByBlockHashAndIndex', [block_hash, hex(index)]) + + def eth_getTransactionByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblocknumberandindex + + TESTED + ''' + block = validate_block(block) + return self._call('eth_getTransactionByBlockNumberAndIndex', [block, hex(index)]) + + def eth_getTransactionReceipt(self, tx_hash): + # type: (string) -> dict + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt + + TESTED + ''' + return self._call('eth_getTransactionReceipt', [str(tx_hash)]) + + def eth_getUncleByBlockHashAndIndex(self, block_hash, index=0): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblockhashandindex + + TESTED + ''' + return self._call('eth_getUncleByBlockHashAndIndex', [block_hash, hex(index)]) + + def eth_getUncleByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblocknumberandindex + + TESTED + ''' + block = validate_block(block) + return self._call('eth_getUncleByBlockNumberAndIndex', [block, hex(index)]) + + def eth_getCompilers(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcompilers + + TESTED + ''' + return self._call('eth_getCompilers') + + def eth_compileSolidity(self, code): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilesolidity + + TESTED + ''' + return self._call('eth_compileSolidity', [code]) + + def eth_compileLLL(self, code): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilelll + + N/A + ''' + return self._call('eth_compileLLL', [code]) + + def eth_compileSerpent(self, code): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compileserpent + + N/A + ''' + return self._call('eth_compileSerpent', [code]) + + def eth_newFilter(self, from_block=BLOCK_TAG_LATEST, to_block=BLOCK_TAG_LATEST, address=None, topics=None): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter + + NEEDS TESTING + ''' + _filter = { + 'fromBlock': from_block, + 'toBlock': to_block, + 'address': address, + 'topics': topics, + } + return self._call('eth_newFilter', [_filter]) + + def eth_newBlockFilter(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter + + TESTED + ''' + return self._call('eth_newBlockFilter') + + def eth_newPendingTransactionFilter(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter + + TESTED + ''' + return hex_to_dec(self._call('eth_newPendingTransactionFilter')) + + def eth_uninstallFilter(self, filter_id): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter + + NEEDS TESTING + ''' + return self._call('eth_uninstallFilter', [filter_id]) + + def eth_getFilterChanges(self, filter_id): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges + + NEEDS TESTING + ''' + return self._call('eth_getFilterChanges', [filter_id]) + + def eth_getFilterLogs(self, filter_id): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs + + NEEDS TESTING + ''' + return self._call('eth_getFilterLogs', [filter_id]) + + def eth_getLogs(self, filter_object): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs + + NEEDS TESTING + ''' + return self._call('eth_getLogs', [filter_object]) + + def eth_getWork(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getwork + + TESTED + ''' + return self._call('eth_getWork') + + def eth_submitWork(self, nonce, header, mix_digest): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submitwork + + NEEDS TESTING + ''' + return self._call('eth_submitWork', [nonce, header, mix_digest]) + + def eth_submitHashrate(self, hash_rate, client_id): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submithashrate + + TESTED + ''' + return self._call('eth_submitHashrate', [hex(hash_rate), client_id]) + + def db_putString(self, db_name, key, value): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#db_putstring + + TESTED + ''' + warnings.warn('deprecated', DeprecationWarning) + return self._call('db_putString', [db_name, key, value]) + + def db_getString(self, db_name, key): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#db_getstring + + TESTED + ''' + warnings.warn('deprecated', DeprecationWarning) + return self._call('db_getString', [db_name, key]) + + def db_putHex(self, db_name, key, value): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#db_puthex + + TESTED + ''' + if not value.startswith('0x'): + value = '0x{}'.format(value) + warnings.warn('deprecated', DeprecationWarning) + return self._call('db_putHex', [db_name, key, value]) + + def db_getHex(self, db_name, key): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#db_gethex + + TESTED + ''' + warnings.warn('deprecated', DeprecationWarning) + return self._call('db_getHex', [db_name, key]) + + def shh_version(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version + + N/A + ''' + return self._call('shh_version') + + def shh_post(self, topics, payload, priority, ttl, from_=None, to=None): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post + + NEEDS TESTING + ''' + whisper_object = { + 'from': from_, + 'to': to, + 'topics': topics, + 'payload': payload, + 'priority': hex(priority), + 'ttl': hex(ttl), + } + return self._call('shh_post', [whisper_object]) + + def shh_newIdentity(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newidentity + + N/A + ''' + return self._call('shh_newIdentity') + + def shh_hasIdentity(self, address): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_hasidentity + + NEEDS TESTING + ''' + return self._call('shh_hasIdentity', [address]) + + def shh_newGroup(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newgroup + + N/A + ''' + return self._call('shh_newGroup') + + def shh_addToGroup(self): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_addtogroup + + NEEDS TESTING + ''' + return self._call('shh_addToGroup') + + def shh_newFilter(self, to, topics): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newfilter + + NEEDS TESTING + ''' + _filter = { + 'to': to, + 'topics': topics, + } + return self._call('shh_newFilter', [_filter]) + + def shh_uninstallFilter(self, filter_id): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_uninstallfilter + + NEEDS TESTING + ''' + return self._call('shh_uninstallFilter', [filter_id]) + + def shh_getFilterChanges(self, filter_id): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges + + NEEDS TESTING + ''' + return self._call('shh_getFilterChanges', [filter_id]) + + def shh_getMessages(self, filter_id): + ''' + https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getmessages + + NEEDS TESTING + ''' + return self._call('shh_getMessages', [filter_id]) + + +class ParityEthJsonRpc(EthJsonRpc): + ''' + EthJsonRpc subclass for Parity-specific methods + ''' + + def __init__(self, host='localhost', port=PARITY_DEFAULT_RPC_PORT, tls=False): + EthJsonRpc.__init__(self, host=host, port=port, tls=tls) + + def trace_filter(self, from_block=None, to_block=None, from_addresses=None, to_addresses=None): + ''' + https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_filter + + TESTED + ''' + params = {} + if from_block is not None: + from_block = validate_block(from_block) + params['fromBlock'] = from_block + if to_block is not None: + to_block = validate_block(to_block) + params['toBlock'] = to_block + if from_addresses is not None: + if not isinstance(from_addresses, list): + from_addresses = [from_addresses] + params['fromAddress'] = from_addresses + if to_addresses is not None: + if not isinstance(to_addresses, list): + to_addresses = [to_addresses] + params['toAddress'] = to_addresses + return self._call('trace_filter', [params]) + + def trace_get(self, tx_hash, positions): + ''' + https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_get + + NEEDS TESTING + ''' + if not isinstance(positions, list): + positions = [positions] + return self._call('trace_get', [tx_hash, positions]) + + def trace_transaction(self, tx_hash): + ''' + https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_transaction + + TESTED + ''' + return self._call('trace_transaction', [tx_hash]) + + def trace_block(self, block=BLOCK_TAG_LATEST): + ''' + https://github.com/ethcore/parity/wiki/JSONRPC-trace-module#trace_block + + TESTED + ''' + block = validate_block(block) + return self._call('trace_block', [block]) \ No newline at end of file diff --git a/tooling/ion.py b/tooling/ion.py new file mode 100644 index 0000000..0da4952 --- /dev/null +++ b/tooling/ion.py @@ -0,0 +1,38 @@ +import click +from .encoder import RLPEncoder + +@click.command(help="Returns an RLP encoded block in hexadecimal format.") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.argument('number', nargs=1, type=int) +def get_encoded_block(rpc_host, rpc_port, number): + rlp_encoder = RLPEncoder(rpc_host, rpc_port) + block = rlp_encoder.get_block(number) + click.echo('0x'+rlp_encoder.encode_block(block).hex()) + +@click.command(help="Returns an RLP encoded block in hexadecimal format.") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.argument('number', nargs=1, type=int) +def get_block_hash(rpc_host, rpc_port, number): + rlp_encoder = RLPEncoder(rpc_host, rpc_port) + block = rlp_encoder.get_block(number) + click.echo('0x'+rlp_encoder.hash_block_header(block)) + + +@click.command(help="Returns a list of transaction hashes from a specified block") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.argument('number', nargs=1, type=int) +def get_block_transactions(rpc_host, rpc_port, number): + rlp_encoder = RLPEncoder(rpc_host, rpc_port) + block = rlp_encoder.get_block(number) + click.echo(rlp_encoder.get_transactions(block)) + +commands = click.Group('commands') +commands.add_command(get_encoded_block, "encodeblock") +commands.add_command(get_block_hash, "blockhash") +commands.add_command(get_block_transactions, "gettx") + +if __name__ == "__main__": + commands.main() \ No newline at end of file diff --git a/tooling/utils.py b/tooling/utils.py new file mode 100644 index 0000000..f8027a6 --- /dev/null +++ b/tooling/utils.py @@ -0,0 +1,117 @@ +import sys +from base64 import b64encode, b64decode +import binascii +import json + +from rlp.sedes import big_endian_int +from rlp.utils import decode_hex, str_to_bytes + +if sys.version_info.major == 2: + def bytearray_to_bytestr(value): + return bytes(''.join(chr(c) for c in value)) +else: + def bytearray_to_bytestr(value): + return bytes(value) + + +TT256 = 2 ** 256 + + +safe_ord = ord if sys.version_info.major == 2 else lambda x: x if isinstance(x, int) else ord(x) + +bytes_to_int = lambda x: reduce(lambda o, b: (o << 8) + safe_ord(b), [0] + list(x)) + + +bit_clear = lambda n, b: n ^ (1<<(b-1)) if n & 1<<(b-1) else n + +bit_set = lambda n, b: n | (1<<(b-1)) + +bit_test = lambda n, b: 0 != (n & (1<<(b-1))) + + +def packl(lnum): + assert lnum >= 0 + if lnum == 0: + return b'\0' + s = hex(lnum)[2:].rstrip('L') + if len(s) & 1: + s = '0' + s + return binascii.unhexlify(s) + +int_to_big_endian = packl + + +def big_endian_to_int(x): return big_endian_int.deserialize( + str_to_bytes(x).lstrip(b'\x00')) + +zpad = lambda x, l: b'\x00' * max(0, l - len(x)) + x + + +u256be = lambda v: zpad(int_to_big_endian(v), 32) + +flatten = lambda l: [item for sublist in l for item in sublist] + +# Turns a `defaultdict(defaultdict)` into a flat dictionary +dict_dump = lambda diff: {c: dict(d.items()) for c, d in diff.items()} + + +def is_numeric(x): return isinstance(x, (int, long)) + + +def encode_int(v): + """encodes an integer into serialization""" + if not is_numeric(v) or v < 0 or v >= TT256: + raise Exception("Integer invalid or out of range: %r" % v) + return int_to_big_endian(v) + + +def scan_bin(v): + if v[:2] in ('0x', b'0x'): + return decode_hex(v[2:]) + else: + return decode_hex(v) + + +def require(arg, msg=None): + if not arg: + raise RuntimeError(msg or "Requirement failed") + + +class Marshalled(object): + def tojson(self): + return tojson(self) + + def marshal(self): + return marshal(list(self)) + + @classmethod + def unmarshal(cls, args): + return cls(*map(unmarshal, args)) + + +def tojson(x): + return json.dumps(marshal(x)) + + +def marshal(x): + if isinstance(x, (int, long, type(None))): + return x + if isinstance(x, (str, bytes, unicode)): + return b64encode(x) + if isinstance(x, (tuple, list)): + return map(marshal, x) + if isinstance(x, Marshalled): + return x.marshal() + raise ValueError("Cannot marshal type: %r - %r" % (type(x), x)) + + +def unmarshal(x): + if x is None or isinstance(x, (int, long)): + return x + if isinstance(x, (str, bytes, unicode)): + return b64decode(x) + if isinstance(x, (tuple, list)): + return map(unmarshal, x) + if isinstance(x, Marshalled): + return x.unmarshal(x) + raise ValueError("Cannot unmarshal type: %r - %r" % (type(x), x)) \ No newline at end of file From 454b92f5f18578251940702feebba133326f3bd2 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 15 Jun 2018 17:11:08 +0100 Subject: [PATCH 003/203] Added updated contract skeletons. Added deploy script, updated package.json, updated ion.py --- contracts/ERC20Interface.sol | 17 +++++++++++++++++ contracts/ERC223Interface.sol | 21 +++++++++++++++++++++ contracts/EventConsumable.sol | 8 +++++--- contracts/EventConsuming.sol | 20 +++++++++++++++++--- contracts/Function.sol | 5 ++--- contracts/IonCompatible.sol | 7 +++++-- migrations/2_deploy_contracts.js | 12 +++--------- package.json | 1 + tooling/ion.py | 2 +- 9 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 contracts/ERC20Interface.sol create mode 100644 contracts/ERC223Interface.sol diff --git a/contracts/ERC20Interface.sol b/contracts/ERC20Interface.sol new file mode 100644 index 0000000..0b5487e --- /dev/null +++ b/contracts/ERC20Interface.sol @@ -0,0 +1,17 @@ +// Copyright (c) 2017-2018 Clearmatics Technologies Ltd + +// SPDX-License-Identifier: LGPL-3.0+ + +pragma solidity 0.4.23; + + +contract ERC20Interface { + function transferFrom(address from, address to, uint256 value) public returns (bool); + function approve(address spender, uint256 value) public returns (bool); + function increaseApproval(address spender, uint addedValue) public returns (bool); + function decreaseApproval(address spender, uint subtractedValue) public returns (bool); + function allowance(address owner, address spender) public view returns (uint256); + + event Transfer(address indexed from, address indexed to, uint value); + event Approval(address indexed owner, address indexed spender, uint256 value); +} diff --git a/contracts/ERC223Interface.sol b/contracts/ERC223Interface.sol new file mode 100644 index 0000000..a935759 --- /dev/null +++ b/contracts/ERC223Interface.sol @@ -0,0 +1,21 @@ +// Copyright (c) 2017-2018 Clearmatics Technologies Ltd + +// SPDX-License-Identifier: LGPL-3.0+ + +pragma solidity 0.4.23; + + +contract ERC223Interface { + function name() public view returns (string); + function symbol() public view returns (string); + function decimals() public view returns (uint8); + function totalSupply() public view returns (uint256); + function balanceOf(address addr) public view returns (uint); + + function transfer(address to, uint value) public returns (bool); + function transfer(address to, uint value, bytes data) public returns (bool); + function transfer(address to, uint value, bytes data, string customFallback) public returns (bool); + + // solhint-disable-next-line no-simple-event-func-name + event Transfer(address from, address to, uint value, bytes data); +} diff --git a/contracts/EventConsumable.sol b/contracts/EventConsumable.sol index 0004fb2..0ab6de3 100644 --- a/contracts/EventConsumable.sol +++ b/contracts/EventConsumable.sol @@ -1,7 +1,9 @@ pragma solidity ^0.4.0; contract EventConsumable { - function EventConsumable(){ - - } + event IonCompatibleEvent( + bytes32 originChain, + bytes32[] destinationChain, + address emittedFromContract, + uint256 nonce); } diff --git a/contracts/EventConsuming.sol b/contracts/EventConsuming.sol index fe9885b..dfea2b0 100644 --- a/contracts/EventConsuming.sol +++ b/contracts/EventConsuming.sol @@ -1,7 +1,21 @@ -pragma solidity ^0.4.0; +pragma solidity ^0.4.23; contract EventConsuming { - function EventConsuming(){ + uint256[] consumedNonces; + address ionCompatible; + constructor(address _ionCompAddress) public { + ionCompatible = _ionCompAddress; } -} + + modifier IonCompatibleOnly(){ + require( msg.sender == ionCompatible, + "Caller is not IonCompatible contract." + ); + _; + } + + function consumeEvent(uint256 nonce) internal { + consumedNonces.push(nonce); + } +} \ No newline at end of file diff --git a/contracts/Function.sol b/contracts/Function.sol index 85132e7..c69ddbb 100644 --- a/contracts/Function.sol +++ b/contracts/Function.sol @@ -1,8 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.4.23; import "./EventConsuming.sol"; -contract FunctionConsumesEvent is EventConsuming { +contract Function is EventConsuming { constructor(address _ionCompAddress) EventConsuming(_ionCompAddress) {} event Executed(); @@ -13,6 +13,5 @@ contract FunctionConsumesEvent is EventConsuming { function CheckReceipt() IonCompatibleOnly { - ion.CheckReceiptProof(); } } diff --git a/contracts/IonCompatible.sol b/contracts/IonCompatible.sol index 2c1a236..3a67d63 100644 --- a/contracts/IonCompatible.sol +++ b/contracts/IonCompatible.sol @@ -1,7 +1,10 @@ pragma solidity ^0.4.0; +import "./Ion.sol"; contract IonCompatible { - function IonCompatible(){ + Ion ion; + constructor(address ionAddr) public { + ion = Ion(ionAddr); } -} +} \ No newline at end of file diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 5317345..db644d2 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,17 +1,11 @@ -const IonLink = artifacts.require("IonLink"); -const IonLock = artifacts.require("IonLock"); -const Token = artifacts.require("Token"); +const Ion = artifacts.require("Ion"); module.exports = async (deployer) => { try { - deployer.deploy(IonLink, 0) - .then(() => IonLink.deployed) - .then(() => deployer.deploy(Token)) - .then(() => Token.deployed) - .then(() => deployer.deploy(IonLock, Token.address, IonLink.address)) + deployer.deploy(Ion, "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") } catch(err) { console.log('ERROR on deploy:',err); } -}; +}; \ No newline at end of file diff --git a/package.json b/package.json index d6640da..30a5981 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", + "rlp": "^2.0.0", "solc": "^0.4.23", "solhint": "^1.1.10", "solidity-coverage": "^0.5.0 " diff --git a/tooling/ion.py b/tooling/ion.py index 0da4952..eab1e79 100644 --- a/tooling/ion.py +++ b/tooling/ion.py @@ -10,7 +10,7 @@ def get_encoded_block(rpc_host, rpc_port, number): block = rlp_encoder.get_block(number) click.echo('0x'+rlp_encoder.encode_block(block).hex()) -@click.command(help="Returns an RLP encoded block in hexadecimal format.") +@click.command(help="Returns block hash in hexadecimal format.") @click.argument('rpc-host', nargs=1, type=str) @click.argument('rpc-port', nargs=1, type=int) @click.argument('number', nargs=1, type=int) From 0961929cb79275077eed3aeb6f7c09c0f7435915 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 18 Jun 2018 11:00:47 +0100 Subject: [PATCH 004/203] Added a requirements.txt file... --- requirements.txt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..591d991 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,27 @@ +asn1crypto==0.24.0 +certifi==2018.4.16 +cffi==1.11.5 +chardet==3.0.4 +click==6.7 +coincurve==7.1.0 +cytoolz==0.9.0.1 +decode==0.4.2 +eth-hash==0.1.4 +eth-utils==1.0.3 +ethereum==2.3.1 +future==0.16.0 +idna==2.7 +pbkdf2==1.3 +pkg-resources==0.0.0 +py-ecc==1.4.2 +pycparser==2.18 +pycryptodome==3.6.1 +pyethash==0.1.27 +pysha3==1.0.2 +PyYAML==3.12 +repoze.lru==0.7 +requests==2.19.1 +rlp==0.6.0 +scrypt==0.8.6 +toolz==0.9.0 +urllib3==1.23 From 540f89510331444db91de9c2422d9ea62dfced35 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 25 Jun 2018 11:50:42 +0100 Subject: [PATCH 005/203] One test is failing but I understand why, this is the repo containing the new golang cli --- abi/ECVerify.abi | 1 + abi/ECVerify.bin | 1 + abi/Migrations.abi | 1 + abi/Migrations.bin | 1 + abi/Recover.abi | 1 + abi/Recover.bin | 1 + abi/Validation.abi | 1 + abi/Validation.bin | 1 + contracts/ECVerify.sol | 18 +- contracts/Recover.sol | 129 + contracts/Validation.sol | 122 + ion-cli/Makefile | 36 + ion-cli/Validation/Validation.go | 591 +++ ion-cli/block.json | 22 + ion-cli/cli/cli.go | 153 + ion-cli/cli/cli_test.go | 29 + ion-cli/cli/rpc.go | 162 + ion-cli/cli/rpc_test.go | 19 + ion-cli/config/config.go | 31 + ion-cli/config/config_test.go | 30 + ion-cli/main.go | 29 + ion-cli/setup.json | 9 + migrations/2_deploy_contracts.js | 15 +- package-lock.json | 3940 ++++++++--------- package.json | 27 +- poa-network/accounts.txt | 2 + poa-network/boot.key | 1 + poa-network/genesis.json | 33 + ...--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 1 + poa-network/node1/password.txt | 1 + ...--8671e5e08d74f338ee1c462340842346d797afd3 | 1 + poa-network/node2/password.txt | 1 + test/signature.js | 286 ++ test/validation.js | 455 ++ truffle.js | 27 +- 35 files changed, 4140 insertions(+), 2038 deletions(-) create mode 100644 abi/ECVerify.abi create mode 100644 abi/ECVerify.bin create mode 100644 abi/Migrations.abi create mode 100644 abi/Migrations.bin create mode 100644 abi/Recover.abi create mode 100644 abi/Recover.bin create mode 100644 abi/Validation.abi create mode 100644 abi/Validation.bin create mode 100644 contracts/Recover.sol create mode 100644 contracts/Validation.sol create mode 100644 ion-cli/Makefile create mode 100644 ion-cli/Validation/Validation.go create mode 100644 ion-cli/block.json create mode 100644 ion-cli/cli/cli.go create mode 100644 ion-cli/cli/cli_test.go create mode 100644 ion-cli/cli/rpc.go create mode 100644 ion-cli/cli/rpc_test.go create mode 100644 ion-cli/config/config.go create mode 100644 ion-cli/config/config_test.go create mode 100644 ion-cli/main.go create mode 100644 ion-cli/setup.json create mode 100644 poa-network/accounts.txt create mode 100644 poa-network/boot.key create mode 100644 poa-network/genesis.json create mode 100644 poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d create mode 100644 poa-network/node1/password.txt create mode 100644 poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 create mode 100644 poa-network/node2/password.txt create mode 100644 test/signature.js create mode 100644 test/validation.js diff --git a/abi/ECVerify.abi b/abi/ECVerify.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/abi/ECVerify.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/abi/ECVerify.bin b/abi/ECVerify.bin new file mode 100644 index 0000000..56887c3 --- /dev/null +++ b/abi/ECVerify.bin @@ -0,0 +1 @@ +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820acb6e646edaf05c92bfe7c53e47edcf3f96a2d5cf3d55019662508f330c1d89f0029 \ No newline at end of file diff --git a/abi/Migrations.abi b/abi/Migrations.abi new file mode 100644 index 0000000..79cea67 --- /dev/null +++ b/abi/Migrations.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"new_address","type":"address"}],"name":"upgrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"last_completed_migration","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"completed","type":"uint256"}],"name":"setCompleted","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] \ No newline at end of file diff --git a/abi/Migrations.bin b/abi/Migrations.bin new file mode 100644 index 0000000..34c63b9 --- /dev/null +++ b/abi/Migrations.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f8806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100aa5780638da5cb5b146100d5578063fdacd5761461012c575b600080fd5b34801561007357600080fd5b506100a8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610159565b005b3480156100b657600080fd5b506100bf610241565b6040518082815260200191505060405180910390f35b3480156100e157600080fd5b506100ea610247565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561013857600080fd5b506101576004803603810190808035906020019092919050505061026c565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023d578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561022457600080fd5b505af1158015610238573d6000803e3d6000fd5b505050505b5050565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102c957806001819055505b505600a165627a7a7230582090db59736857b6a69a78d054d092a30ff8e90f10f6f3bca8afc3d994c885eedd0029 \ No newline at end of file diff --git a/abi/Recover.abi b/abi/Recover.abi new file mode 100644 index 0000000..49fac10 --- /dev/null +++ b/abi/Recover.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ExtractHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"sig","type":"bytes"}],"name":"VerifyBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"data","type":"bytes32"},{"name":"sig","type":"bytes"}],"name":"VerifyHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"}],"name":"test","type":"event"}] \ No newline at end of file diff --git a/abi/Recover.bin b/abi/Recover.bin new file mode 100644 index 0000000..183887f --- /dev/null +++ b/abi/Recover.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b11806100606000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b0e7308f1461005c578063d09ca90414610151578063fdace1be14610200575b600080fd5b34801561006857600080fd5b5061014f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610277565b005b34801561015d57600080fd5b506101fe600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061055e565b005b34801561020c57600080fd5b506102756004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610840565b005b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156102bf578051825260208201915060208101905060208303925061029a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156103635781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f19166020018201604052801561039a5781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156103d15781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156104085781602001602082028038833980820191505090505b509350610419878d60008a516108b6565b600260218801600260208e016004610bb8fa5061043c868d608c8c0389516108b6565b600160208701600160208d016004610bb8fa5061045f848d602a8c0387516108b6565b61046a878786610971565b9250826040518082805190602001908083835b6020831015156104a2578051825260208201915060208101905060208303925061047d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506104e1858d606b8c0388516108b6565b6104eb8286610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b600080606080856040518082805190602001908083835b60208310151561059a5780518252602082019150602081019050602083039250610575565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093506105d38486610a1d565b925060206040519080825280601f01601f1916602001820160405280156106095781602001602082028038833980820191505090505b50915060206040519080825280601f01601f1916602001820160405280156106405781602001602082028038833980820191505090505b5090506106518287600460206108b6565b61065f8187605b60206108b6565b7f8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c786838360405180806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106cb5780820151818401526020810190506106b0565b50505050905090810190601f1680156106f85780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b83811015610731578082015181840152602081019050610716565b50505050905090810190601f16801561075e5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b8381101561079757808201518184015260208101905061077c565b50505050905090810190601f1680156107c45780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a17fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a583604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b600061084c8383610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b60008090505b8181101561096a57838184018151811015156108d457fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561092d57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506108bc565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109d85781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a3357600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a5e57601b810190505b601b8160ff161480610a735750601c8160ff16145b1515610a7e57600080fd5b610a8a86828585610a95565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610ad857600080fd5b80925050509493505050505600a165627a7a7230582084747b0b9ea8d1285e7c7714b82fb8ff314f3245d9b3e8132f7679cf08b7ca2b0029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi new file mode 100644 index 0000000..0388fd3 --- /dev/null +++ b/abi/Validation.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] diff --git a/abi/Validation.bin b/abi/Validation.bin new file mode 100644 index 0000000..3513650 --- /dev/null +++ b/abi/Validation.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506040516109d73803806109d7833981018060405281019080805182019291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b815181101561017c576001828281518110151561009357fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160026000848481518110151561011457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550808060010191505061007a565b505061084a8061018d6000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063aae933e414610051578063d405af3d14610146575b600080fd5b34801561005d57600080fd5b50610144600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101b2565b005b34801561015257600080fd5b5061015b610561565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019e578082015181840152602081019050610183565b505050509050019250505060405180910390f35b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156101fa57805182526020820191506020810190506020830392506101d5565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561029e5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156102d55781602001602082028038833980820191505090505b50955060416040519080825280601f01601f19166020018201604052801561030c5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156103435781602001602082028038833980820191505090505b509350610354878d60008a516105ef565b600260218801600260208e016004610bb8fa50610377868d608c8c0389516105ef565b600160208701600160208d016004610bb8fa5061039a848d602a8c0387516105ef565b6103a58787866106aa565b9250826040518082805190602001908083835b6020831015156103dd57805182526020820191506020810190506020830392506103b8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020915061041c858d606b8c0388516105ef565b6104268286610756565b905060011515600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151415156104f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156105e557602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161059b575b5050505050905090565b60008090505b818110156106a3578381840181518110151561060d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561066657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506105f5565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156107115781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561076c57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561079757601b810190505b601b8160ff1614806107ac5750601c8160ff16145b15156107b757600080fd5b6107c3868285856107ce565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561081157600080fd5b80925050509493505050505600a165627a7a72305820bfdda3defd1a9101b13153fe900905c379572f205ad37b4197c70cdd78be35e20029 \ No newline at end of file diff --git a/contracts/ECVerify.sol b/contracts/ECVerify.sol index 622dd6b..288da23 100644 --- a/contracts/ECVerify.sol +++ b/contracts/ECVerify.sol @@ -1,5 +1,3 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.18; // @@ -25,11 +23,7 @@ pragma solidity ^0.4.18; library ECVerify { // Duplicate Solidity's ecrecover, but catching the CALL return value - function safer_ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) - constant - internal - returns (address) - { + function safer_ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) constant internal returns (address) { // We do our own memory management here. Solidity uses memory offset // 0x40 to store the current end of memory. We write past it (as // writes are memory extensions), but don't update the offset so @@ -49,7 +43,7 @@ library ECVerify { // NOTE: we can reuse the request memory because we deal with // the return code - ret := call(3000, 1, 0, size, 128, size, 32) + ret := staticcall(3000, 1, size, 128, size, 32) addr := mload(size) } @@ -75,12 +69,12 @@ library ECVerify { // Here we are loading the last 32 bytes. We exploit the fact that // 'mload' will pad with zeroes if we overread. // There is no 'mload8' to do this, but that would be nicer. - /* v := byte(0, mload(add(sig, 96))) */ + v := byte(0, mload(add(sig, 96))) // Alternative solution: // 'byte' is not working due to the Solidity parser, so lets // use the second best option, 'and' - v := and(mload(add(sig, 65)), 255) + // v := and(mload(add(sig, 65)), 255) } // albeit non-transactional signatures are not specified by the YP, one would expect it @@ -96,8 +90,8 @@ library ECVerify { /* prefix might be needed for geth only * https://github.com/ethereum/go-ethereum/issues/3731 */ - bytes memory prefix = "\x19Ethereum Signed Message:\n32"; - hash = keccak256(prefix, hash); + /* bytes memory prefix = "\x19Ethereum Signed Message:\n32"; + hash = keccak256(prefix, hash); */ /* hash = sha3(prefix, hash); */ return safer_ecrecover(hash, v, r, s); diff --git a/contracts/Recover.sol b/contracts/Recover.sol new file mode 100644 index 0000000..c788240 --- /dev/null +++ b/contracts/Recover.sol @@ -0,0 +1,129 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +import "./ECVerify.sol"; + +contract Recover { + address Owner; + + event broadcastSig(address owner); + event broadcastHashData(bytes header, bytes parentHash, bytes rootHash); + /* event test(bytes start, bytes data); */ + event broadcastHash(bytes32 blockHash); + event test(bytes header); + + constructor () public { + Owner = msg.sender; + } + + /* + * @param data data that has been signed + * @param sig signature of data + */ + function VerifyHash(bytes32 data, bytes sig) public { + address sig_addr = ECVerify.ecrecovery(data, sig); + + emit broadcastSig(sig_addr); + } + + /* + * @param header header rlp encoded, with extraData signatures removed + * @param sig extraData signatures + */ + function VerifyBlock(bytes header, bytes sig) public { + bytes32 hashData = keccak256(header); + address sig_addr = ECVerify.ecrecovery(hashData, sig); + + bytes memory parentHash = new bytes(32); + bytes memory rootHash = new bytes(32); + + // get parentHash and rootHash + extractData(parentHash, header, 4, 32); + extractData(rootHash, header, 91, 32); + + emit broadcastHashData(header, parentHash, rootHash); + emit broadcastSig(sig_addr); + } + + /* + * @param header header rlp encoded, with extraData signatures removed + * @param prefixHeader the new prefix for the signed hash header + * @param prefixExtraData the new prefix for the extraData field + */ + function ExtractHash(bytes header, bytes prefixHeader, bytes prefixExtraData) public { + uint256 length = header.length; + bytes32 blockHash = keccak256(header); + + emit broadcastHash(blockHash); + + bytes memory headerStart = new bytes(length - 141); + bytes memory extraData = new bytes(31); + bytes memory extraDataSig = new bytes(65); + bytes memory headerEnd = new bytes(42); + + // Extract the start of the header and replace the length + extractData(headerStart, header, 0, headerStart.length); + assembly { + let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) + } + + // Extract the real extra data and create the signed hash + extractData(extraData, header, length-140, extraData.length); + assembly { + let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) + } + + // Extract the end of the header + extractData(headerEnd, header, length-42, headerEnd.length); + bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); + + bytes32 hashData = keccak256(newHeader); + + // Extract the signature of the hash create above + extractData(extraDataSig, header, length-107, extraDataSig.length); + + address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); + + emit broadcastSig(sig_addr); + + } + + function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { + // Get the lengths sorted because they're needed later... + uint256 headerStartLength = headerStart.length; + uint256 extraDataLength = extraData.length; + uint256 extraDataStart = headerStartLength + 32; + uint256 headerEndLength = headerEnd.length; + uint256 headerEndStart = extraDataLength + headerStartLength + 32 + 2; + uint256 newLength = headerStartLength + extraDataLength + headerEndLength + 2; // extra two is for the prefix + bytes memory header = new bytes(newLength); + + + // Add in the first part of the header + assembly { + let ret := staticcall(3000, 4, add(headerStart, 32), headerStartLength, add(header, 32), headerStartLength) + } + assembly { + let ret := staticcall(3000, 4, add(extraData, 32), extraDataLength, add(header, extraDataStart), extraDataLength) + } + assembly { + let ret := staticcall(3000, 4, add(headerEnd, 32), headerEndLength, add(header, headerEndStart), headerEndLength) + } + + output = header; + } + + /* + * @param data memory allocation for the data you need to extract + * @param sig array from which the data should be extracted + * @param start index which the data starts within the byte array + * @param length total length of the data to be extracted + */ + function extractData(bytes data, bytes input, uint start, uint length) private pure { + for (uint i=0; i BlockHeader) public m_blockheaders; + mapping( address => bool ) m_validators; + + /* + * @param _validators list of validators at block 0 + */ + constructor (address[] _validators) public { + Owner = msg.sender; + for (uint i = 0; i < _validators.length; i++) { + validators.push(_validators[i]); + m_validators[_validators[i]] = true; + } + } + + /* + * Returns the validators array + */ + function GetValidators() public view returns (address[] _validators) { + return validators; + } + + /* + * @param header header rlp encoded, with extraData signatures removed + * @param prefixHeader the new prefix for the signed hash header + * @param prefixExtraData the new prefix for the extraData field + */ + function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public { + uint256 length = header.length; + bytes32 blockHash = keccak256(header); + + emit broadcastHash(blockHash); + + bytes memory headerStart = new bytes(length - 141); + bytes memory extraData = new bytes(31); + bytes memory extraDataSig = new bytes(65); + bytes memory headerEnd = new bytes(42); + + // Extract the start of the header and replace the length + extractData(headerStart, header, 0, headerStart.length); + assembly { + let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) + } + + // Extract the real extra data and create the signed hash + extractData(extraData, header, length-140, extraData.length); + assembly { + let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) + } + + // Extract the end of the header + extractData(headerEnd, header, length-42, headerEnd.length); + bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); + + bytes32 hashData = keccak256(newHeader); + + // Extract the signature of the hash create above + extractData(extraDataSig, header, length-107, extraDataSig.length); + + address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); + require(m_validators[sig_addr]==true, "Signer not a validator!"); + + emit broadcastSig(sig_addr); + + } + + function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { + // Get the lengths sorted because they're needed later... + uint256 headerStartLength = headerStart.length; + uint256 extraDataLength = extraData.length; + uint256 extraDataStart = headerStartLength + 32; + uint256 headerEndLength = headerEnd.length; + uint256 headerEndStart = extraDataLength + headerStartLength + 32 + 2; + uint256 newLength = headerStartLength + extraDataLength + headerEndLength + 2; // extra two is for the prefix + bytes memory header = new bytes(newLength); + + + // Add in the first part of the header + assembly { + let ret := staticcall(3000, 4, add(headerStart, 32), headerStartLength, add(header, 32), headerStartLength) + } + assembly { + let ret := staticcall(3000, 4, add(extraData, 32), extraDataLength, add(header, extraDataStart), extraDataLength) + } + assembly { + let ret := staticcall(3000, 4, add(headerEnd, 32), headerEndLength, add(header, headerEndStart), headerEndLength) + } + + output = header; + } + + /* + * @param data memory allocation for the data you need to extract + * @param sig array from which the data should be extracted + * @param start index which the data starts within the byte array + * @param length total length of the data to be extracted + */ + function extractData(bytes data, bytes input, uint start, uint length) private pure { + for (uint i=0; i coverage-all.out + $(foreach pkg,$(PACKAGES),\ + go test -coverprofile=coverage.out -covermode=count $(pkg);\ + tail -n +2 coverage.out >> coverage-all.out;) + go tool cover -html=coverage-all.out + +build: + @go build -o ion-cli . + +check: + @if [ -n "$(shell gofmt -l ${GOFILES_NOVENDOR})" ]; then \ + echo 1>&2 'The following files need to be formatted:'; \ + gofmt -l .; \ + exit 1; \ + fi + +vet: + @go vet ${GOFILES_NOVENDOR} + +lint: + @golint ${GOFILES_NOVENDOR} diff --git a/ion-cli/Validation/Validation.go b/ion-cli/Validation/Validation.go new file mode 100644 index 0000000..18e9228 --- /dev/null +++ b/ion-cli/Validation/Validation.go @@ -0,0 +1,591 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package Validation + +import ( + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// ValidationABI is the input ABI used to generate the binding from. +const ValidationABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" + +// ValidationBin is the compiled bytecode used for deploying new contracts. +const ValidationBin = `608060405234801561001057600080fd5b506040516109d73803806109d7833981018060405281019080805182019291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b815181101561017c576001828281518110151561009357fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160026000848481518110151561011457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550808060010191505061007a565b505061084a8061018d6000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063aae933e414610051578063d405af3d14610146575b600080fd5b34801561005d57600080fd5b50610144600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101b2565b005b34801561015257600080fd5b5061015b610561565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019e578082015181840152602081019050610183565b505050509050019250505060405180910390f35b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156101fa57805182526020820191506020810190506020830392506101d5565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561029e5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156102d55781602001602082028038833980820191505090505b50955060416040519080825280601f01601f19166020018201604052801561030c5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156103435781602001602082028038833980820191505090505b509350610354878d60008a516105ef565b600260218801600260208e016004610bb8fa50610377868d608c8c0389516105ef565b600160208701600160208d016004610bb8fa5061039a848d602a8c0387516105ef565b6103a58787866106aa565b9250826040518082805190602001908083835b6020831015156103dd57805182526020820191506020810190506020830392506103b8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020915061041c858d606b8c0388516105ef565b6104268286610756565b905060011515600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151415156104f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156105e557602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161059b575b5050505050905090565b60008090505b818110156106a3578381840181518110151561060d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561066657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506105f5565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156107115781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561076c57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561079757601b810190505b601b8160ff1614806107ac5750601c8160ff16145b15156107b757600080fd5b6107c3868285856107ce565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561081157600080fd5b80925050509493505050505600a165627a7a72305820bfdda3defd1a9101b13153fe900905c379572f205ad37b4197c70cdd78be35e20029` + +// DeployValidation deploys a new Ethereum contract, binding an instance of Validation to it. +func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address) (common.Address, *types.Transaction, *Validation, error) { + parsed, err := abi.JSON(strings.NewReader(ValidationABI)) + if err != nil { + return common.Address{}, nil, nil, err + } + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ValidationBin), backend, _validators) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Validation{ValidationCaller: ValidationCaller{contract: contract}, ValidationTransactor: ValidationTransactor{contract: contract}, ValidationFilterer: ValidationFilterer{contract: contract}}, nil +} + +// Validation is an auto generated Go binding around an Ethereum contract. +type Validation struct { + ValidationCaller // Read-only binding to the contract + ValidationTransactor // Write-only binding to the contract + ValidationFilterer // Log filterer for contract events +} + +// ValidationCaller is an auto generated read-only Go binding around an Ethereum contract. +type ValidationCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidationTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ValidationTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidationFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ValidationFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidationSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ValidationSession struct { + Contract *Validation // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ValidationCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ValidationCallerSession struct { + Contract *ValidationCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ValidationTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ValidationTransactorSession struct { + Contract *ValidationTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ValidationRaw is an auto generated low-level Go binding around an Ethereum contract. +type ValidationRaw struct { + Contract *Validation // Generic contract binding to access the raw methods on +} + +// ValidationCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ValidationCallerRaw struct { + Contract *ValidationCaller // Generic read-only contract binding to access the raw methods on +} + +// ValidationTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ValidationTransactorRaw struct { + Contract *ValidationTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewValidation creates a new instance of Validation, bound to a specific deployed contract. +func NewValidation(address common.Address, backend bind.ContractBackend) (*Validation, error) { + contract, err := bindValidation(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Validation{ValidationCaller: ValidationCaller{contract: contract}, ValidationTransactor: ValidationTransactor{contract: contract}, ValidationFilterer: ValidationFilterer{contract: contract}}, nil +} + +// NewValidationCaller creates a new read-only instance of Validation, bound to a specific deployed contract. +func NewValidationCaller(address common.Address, caller bind.ContractCaller) (*ValidationCaller, error) { + contract, err := bindValidation(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ValidationCaller{contract: contract}, nil +} + +// NewValidationTransactor creates a new write-only instance of Validation, bound to a specific deployed contract. +func NewValidationTransactor(address common.Address, transactor bind.ContractTransactor) (*ValidationTransactor, error) { + contract, err := bindValidation(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ValidationTransactor{contract: contract}, nil +} + +// NewValidationFilterer creates a new log filterer instance of Validation, bound to a specific deployed contract. +func NewValidationFilterer(address common.Address, filterer bind.ContractFilterer) (*ValidationFilterer, error) { + contract, err := bindValidation(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ValidationFilterer{contract: contract}, nil +} + +// bindValidation binds a generic wrapper to an already deployed contract. +func bindValidation(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ValidationABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Validation *ValidationRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Validation.Contract.ValidationCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Validation *ValidationRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Validation.Contract.ValidationTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Validation *ValidationRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Validation.Contract.ValidationTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Validation *ValidationCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Validation.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Validation *ValidationTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Validation.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Validation *ValidationTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Validation.Contract.contract.Transact(opts, method, params...) +} + +// GetValidators is a free data retrieval call binding the contract method 0xd405af3d. +// +// Solidity: function GetValidators() constant returns(_validators address[]) +func (_Validation *ValidationCaller) GetValidators(opts *bind.CallOpts) ([]common.Address, error) { + var ( + ret0 = new([]common.Address) + ) + out := ret0 + err := _Validation.contract.Call(opts, out, "GetValidators") + return *ret0, err +} + +// GetValidators is a free data retrieval call binding the contract method 0xd405af3d. +// +// Solidity: function GetValidators() constant returns(_validators address[]) +func (_Validation *ValidationSession) GetValidators() ([]common.Address, error) { + return _Validation.Contract.GetValidators(&_Validation.CallOpts) +} + +// GetValidators is a free data retrieval call binding the contract method 0xd405af3d. +// +// Solidity: function GetValidators() constant returns(_validators address[]) +func (_Validation *ValidationCallerSession) GetValidators() ([]common.Address, error) { + return _Validation.Contract.GetValidators(&_Validation.CallOpts) +} + +// ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. +// +// Solidity: function ValidateBlock(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactor) ValidateBlock(opts *bind.TransactOpts, header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.contract.Transact(opts, "ValidateBlock", header, prefixHeader, prefixExtraData) +} + +// ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. +// +// Solidity: function ValidateBlock(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationSession) ValidateBlock(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +} + +// ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. +// +// Solidity: function ValidateBlock(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactorSession) ValidateBlock(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +} + +// ValidationBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Validation contract. +type ValidationBroadcastHashIterator struct { + Event *ValidationBroadcastHash // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ValidationBroadcastHashIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastHash) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastHash) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ValidationBroadcastHashIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ValidationBroadcastHashIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ValidationBroadcastHash represents a BroadcastHash event raised by the Validation contract. +type ValidationBroadcastHash struct { + BlockHash [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBroadcastHash is a free log retrieval operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. +// +// Solidity: event broadcastHash(blockHash bytes32) +func (_Validation *ValidationFilterer) FilterBroadcastHash(opts *bind.FilterOpts) (*ValidationBroadcastHashIterator, error) { + + logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastHash") + if err != nil { + return nil, err + } + return &ValidationBroadcastHashIterator{contract: _Validation.contract, event: "broadcastHash", logs: logs, sub: sub}, nil +} + +// WatchBroadcastHash is a free log subscription operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. +// +// Solidity: event broadcastHash(blockHash bytes32) +func (_Validation *ValidationFilterer) WatchBroadcastHash(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastHash) (event.Subscription, error) { + + logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastHash") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ValidationBroadcastHash) + if err := _Validation.contract.UnpackLog(event, "broadcastHash", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ValidationBroadcastHashDataIterator is returned from FilterBroadcastHashData and is used to iterate over the raw logs and unpacked data for BroadcastHashData events raised by the Validation contract. +type ValidationBroadcastHashDataIterator struct { + Event *ValidationBroadcastHashData // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ValidationBroadcastHashDataIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastHashData) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastHashData) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ValidationBroadcastHashDataIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ValidationBroadcastHashDataIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ValidationBroadcastHashData represents a BroadcastHashData event raised by the Validation contract. +type ValidationBroadcastHashData struct { + Header []byte + ParentHash []byte + RootHash []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBroadcastHashData is a free log retrieval operation binding the contract event 0x8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c7. +// +// Solidity: event broadcastHashData(header bytes, parentHash bytes, rootHash bytes) +func (_Validation *ValidationFilterer) FilterBroadcastHashData(opts *bind.FilterOpts) (*ValidationBroadcastHashDataIterator, error) { + + logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastHashData") + if err != nil { + return nil, err + } + return &ValidationBroadcastHashDataIterator{contract: _Validation.contract, event: "broadcastHashData", logs: logs, sub: sub}, nil +} + +// WatchBroadcastHashData is a free log subscription operation binding the contract event 0x8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c7. +// +// Solidity: event broadcastHashData(header bytes, parentHash bytes, rootHash bytes) +func (_Validation *ValidationFilterer) WatchBroadcastHashData(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastHashData) (event.Subscription, error) { + + logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastHashData") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ValidationBroadcastHashData) + if err := _Validation.contract.UnpackLog(event, "broadcastHashData", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ValidationBroadcastSigIterator is returned from FilterBroadcastSig and is used to iterate over the raw logs and unpacked data for BroadcastSig events raised by the Validation contract. +type ValidationBroadcastSigIterator struct { + Event *ValidationBroadcastSig // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ValidationBroadcastSigIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastSig) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastSig) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ValidationBroadcastSigIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ValidationBroadcastSigIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ValidationBroadcastSig represents a BroadcastSig event raised by the Validation contract. +type ValidationBroadcastSig struct { + Owner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBroadcastSig is a free log retrieval operation binding the contract event 0xba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5. +// +// Solidity: event broadcastSig(owner address) +func (_Validation *ValidationFilterer) FilterBroadcastSig(opts *bind.FilterOpts) (*ValidationBroadcastSigIterator, error) { + + logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastSig") + if err != nil { + return nil, err + } + return &ValidationBroadcastSigIterator{contract: _Validation.contract, event: "broadcastSig", logs: logs, sub: sub}, nil +} + +// WatchBroadcastSig is a free log subscription operation binding the contract event 0xba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5. +// +// Solidity: event broadcastSig(owner address) +func (_Validation *ValidationFilterer) WatchBroadcastSig(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastSig) (event.Subscription, error) { + + logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastSig") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ValidationBroadcastSig) + if err := _Validation.contract.UnpackLog(event, "broadcastSig", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} diff --git a/ion-cli/block.json b/ion-cli/block.json new file mode 100644 index 0000000..6bf6cd4 --- /dev/null +++ b/ion-cli/block.json @@ -0,0 +1,22 @@ +{ + "parentHash": "0xad34f0f919e4b06b18b0c674b8b9f6738a4878c76e837c8f31a2079f21dced1c", + "difficulty": "2", + "extraData": "0xd78301080a846765746887676f312e392e33856c696e75780000000000000000e0ac79c5577889dfb5745ace9c5dfebe1a11bb19ced9b98b427e7bd4c85765ce17154e658440915743ec442fb64756483bc592616754d13a3c62fce5a56ac9f501", + "gasLimit": "16614106", + "gasUsed": "0", + "hash": "0xd1d7abeb1345861e0103a24a239c178ccf930b069e50f2697d82fdd3496746ab", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "10", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "606", + "stateRoot": "0xdb37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dc", + "timestamp": "1529396972", + "totalDifficulty": "21", + "transactions": [], + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] +} diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go new file mode 100644 index 0000000..5fc704b --- /dev/null +++ b/ion-cli/cli/cli.go @@ -0,0 +1,153 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package cli + +import ( + "fmt" + "log" + "strconv" + + "github.com/abiosoft/ishell" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + + "github.com/ion/ion-cli/Validation" + "github.com/ion/ion-cli/config" +) + +// Launch - definition of commands and creates the iterface +func Launch(setup config.Setup) { + // by default, new shell includes 'exit', 'help' and 'clear' commands. + shell := ishell.New() + + // Connect to the RPC Client + client, err := ethclient.Dial("http://" + setup.AddrTo + ":" + setup.PortTo) + if err != nil { + log.Fatalf("could not create RPC client: %v", err) + } + + // Initialise the contract + address := common.HexToAddress(setup.Ion) + validation, err := Validation.NewValidation(address, client) + if err != nil { + log.Fatal(err) + } + + printInfo(setup) + + // Get the latest block number + shell.AddCmd(&ishell.Cmd{ + Name: "latestBlock", + Help: "Returns latest block number, arguments: latestBlock", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Get latest block number:") + latestBlock(client) + c.Println("===============================================================") + }, + }) + + // Get block N + shell.AddCmd(&ishell.Cmd{ + Name: "getBlock", + Help: "Returns a block header, arguments: getBlock [integer]", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + if len(c.Args) == 0 { + c.Println("Input argument required, e.g.: getBlock 10") + } else if len(c.Args) > 1 { + c.Println("Only enter single argument") + } else { + getBlock(client, c.Args[0]) + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "getValidators", + Help: "Queries the validator contract for the whitelist of validators", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + result, err := validation.GetValidators(&bind.CallOpts{}) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + c.Println("Validators Whitelist:") + c.Printf("%x\n", result) + + c.Println("===============================================================") + }, + }) + + // Get block N and spew out the RLP encoded block + shell.AddCmd(&ishell.Cmd{ + Name: "rlpBlock", + Help: "Returns RLP encoded block header, arguments: rlpBlock [integer]", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + if len(c.Args) == 0 { + c.Println("Input argument required, e.g.: rlpBlock 10") + } else if len(c.Args) > 1 { + c.Println("Only enter single argument") + } else { + c.Println("RLP encode block: " + c.Args[0]) + rlpEncodeBlock(client, c.Args[0]) + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "submitRlpBlock", + Help: "Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract, arguments: submitRlpBlock [integer]", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + if len(c.Args) == 0 { + c.Println("Choose a block.") + } else if len(c.Args) > 1 { + c.Println("Too many arguments entered.") + } else { + c.Println("RLP encode block: " + c.Args[0]) + encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) + res, err := validation.ValidateBlock(&bind.TransactOpts{}, encodedBlock, prefixBlock, prefixExtra) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("Error: %s", res) + } + c.Println("===============================================================") + }, + }) + + // run shell + shell.Run() +} + +func printInfo(setup config.Setup) { + // display welcome info. + fmt.Println("===============================================================") + fmt.Println("Ion Command Line Interface\n") + fmt.Println("RPC Client [to]:") + fmt.Println("Listening on: " + setup.AddrTo + ":" + setup.PortTo) + fmt.Println("User Account: " + setup.AccountTo) + fmt.Println("Ion Contract: " + setup.Ion) + fmt.Println("\nRPC Client [from]: ") + fmt.Println("Listening on: " + setup.AddrFrom + ":" + setup.PortFrom) + fmt.Println("User Account: " + setup.AccountFrom) + fmt.Println("===============================================================") +} + +func strToHex(input string) (output string) { + val, err := strconv.Atoi(input) + if err != nil { + fmt.Println("please input decimal:", err) + return + } + output = strconv.FormatInt(int64(val), 16) + + return "0x" + output +} diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go new file mode 100644 index 0000000..3485c9d --- /dev/null +++ b/ion-cli/cli/cli_test.go @@ -0,0 +1,29 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package cli_test + +import ( + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ion/ion-cli/config" +) + +func Test_Read_ValidSetupJson(t *testing.T) { + path := findPath() + "../setup.json" + setup := config.Read(path) + + assert.Equal(t, "8501", setup.PortTo) + assert.Equal(t, "127.0.0.1", setup.AddrTo) + assert.Equal(t, "8502", setup.PortFrom) + assert.Equal(t, "127.0.0.1", setup.AddrFrom) +} + +func findPath() string { + _, path, _, _ := runtime.Caller(0) + pathSlice := strings.Split(path, "/") + return strings.Trim(path, pathSlice[len(pathSlice)-1]) +} diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go new file mode 100644 index 0000000..9a16103 --- /dev/null +++ b/ion-cli/cli/rpc.go @@ -0,0 +1,162 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package cli + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "reflect" + + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rlp" +) + +type Header struct { + ParentHash string `json:"parentHash"` + UncleHash string `json:"sha3Uncles"` + Coinbase string `json:"miner"` + Root string `json:"stateRoot"` + TxHash string `json:"transactionsRoot"` + ReceiptHash string `json:"receiptsRoot"` + Bloom string `json:"logsBloom"` + Difficulty string `json:"difficulty"` + Number string `json:"number"` + GasLimit string `json:"gasLimit"` + GasUsed string `json:"gasUsed"` + Time string `json:"timestamp"` + Extra string `json:"extraData"` + MixDigest string `json:"mixHash"` + Nonce string `json:"nonce"` +} + +func latestBlock(client *ethclient.Client) { + // var lastBlock Block + lastBlock, err := client.HeaderByNumber(context.Background(), nil) + if err != nil { + fmt.Println("can't get latest block:", err) + return + } + // Print events from the subscription as they arrive. + fmt.Printf("latest block: %v\n", lastBlock.Number) +} + +func getBlock(client *ethclient.Client, block string) { + // var blockHeader Header + blockNum := new(big.Int) + blockNum.SetString(block, 10) + + lastBlock, err := client.HeaderByNumber(context.Background(), blockNum) + if err != nil { + fmt.Println("can't get requested block:", err) + return + } + // Marshal into a JSON + b, err := json.MarshalIndent(lastBlock, "", " ") + if err != nil { + fmt.Printf("Error: %s", err) + return + } + fmt.Println("Block:", block) + fmt.Println(string(b)) +} + +// func rlpEncodeBlock(client *rpc.Client, block string) { +func rlpEncodeBlock(client *ethclient.Client, block string) { + var blockHeader Header + blockNum := new(big.Int) + blockNum.SetString(block, 10) + + lastBlock, err := client.HeaderByNumber(context.Background(), blockNum) + if err != nil { + fmt.Println("can't get requested block:", err) + return + } + + // Marshal into a JSON + b, err := json.MarshalIndent(lastBlock, "", " ") + if err != nil { + fmt.Printf("Error: %s", err) + return + } + err = json.Unmarshal([]byte(b), &blockHeader) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + + // fmt.Printf("%+v\n", blockHeader) + blockInterface := GenerateInterface(blockHeader) + encodedBlock := EncodeBlock(blockInterface) + fmt.Printf("%+x\n", encodedBlock) +} + +// func calculateRlpEncoding(client *ethclient.Client, block string) { +func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []byte, prefixBlock []byte, prefixExtra []byte) { + var blockHeader Header + blockNum := new(big.Int) + blockNum.SetString(block, 10) + + lastBlock, err := client.HeaderByNumber(context.Background(), blockNum) + if err != nil { + fmt.Println("can't get requested block:", err) + return + } + + // Marshal into a JSON + b, err := json.MarshalIndent(lastBlock, "", " ") + if err != nil { + fmt.Printf("Error: %s", err) + return + } + err = json.Unmarshal([]byte(b), &blockHeader) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + + // Generate an interface to encode the standard block header + blockInterface := GenerateInterface(blockHeader) + encodedBlock := EncodeBlock(blockInterface) + fmt.Printf("\n%+x\n", encodedBlock) + + // Generate an interface to encode the blockheader without the signature in the extraData + blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] + blockInterface = GenerateInterface(blockHeader) + encodedBlock = EncodeBlock(blockInterface) + prefixBlock = encodedBlock[1:3] + fmt.Printf("\n%+x\n", prefixBlock) + + // Generate an interface to encode the blockheader without the signature in the extraData + encExtra, _ := hex.DecodeString(blockHeader.Extra[2:]) + encodedBlock = EncodeBlock(encExtra) + prefixExtra = encodedBlock[0:1] + fmt.Printf("\n%+x\n", prefixExtra) + + return encodedBlock, prefixBlock, prefixExtra + +} + +// Creates an interface for a block +func GenerateInterface(blockHeader Header) (rest interface{}) { + blockInterface := []interface{}{} + s := reflect.ValueOf(&blockHeader).Elem() + + // Append items into the interface + for i := 0; i < s.NumField(); i++ { + f := s.Field(i).String() + element, _ := hex.DecodeString(f[2:]) + blockInterface = append(blockInterface, element) + } + + return blockInterface +} + +// Encodes a block +func EncodeBlock(blockInterface interface{}) (h []byte) { + h, _ = rlp.EncodeToBytes(blockInterface) + + return h +} diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go new file mode 100644 index 0000000..6ec7ebf --- /dev/null +++ b/ion-cli/cli/rpc_test.go @@ -0,0 +1,19 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package cli_test + +// func Test_EncodeBlock(t *testing.T) { +// // read a fake block +// raw, _ := ioutil.ReadFile("../block.json") +// +// const expectedRlpHex = "f90256a0ad34f0f919e4b06b18b0c674b8b9f6738a4878c76e837c8f31a2079f21dced1ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0db37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a83fd82da80845b28beecb861d78301080a846765746887676f312e392e33856c696e75780000000000000000e0ac79c5577889dfb5745ace9c5dfebe1a11bb19ced9b98b427e7bd4c85765ce17154e658440915743ec442fb64756483bc592616754d13a3c62fce5a56ac9f501a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +// +// var marshalledBlock cli.Header +// json.Unmarshal(raw, &marshalledBlock) +// +// // Now RLP encode the block +// blockInterface := cli.GenerateInterface(marshalledBlock) +// fmt.Printf("%+v\n", marshalledBlock.Extra) +// hash := cli.EncodeBlock(blockInterface) +// assert.Equal(t, expectedRlpHex, hex.EncodeToString(hash)) +// } diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go new file mode 100644 index 0000000..5c777af --- /dev/null +++ b/ion-cli/config/config.go @@ -0,0 +1,31 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package config + +import ( + "encoding/json" + "fmt" + "io/ioutil" +) + +// Settings +type Setup struct { + PortTo string `json:"rpc-port-to"` + AddrTo string `json:"rpc-addr-to"` + AccountTo string `json:"account-to"` + PortFrom string `json:"rpc-port-from"` + AddrFrom string `json:"rpc-addr-from"` + AccountFrom string `json:"account-from"` + Ion string `json:"ion-addr"` +} + +func Read(config string) (setup Setup) { + raw, err := ioutil.ReadFile(config) + if err != nil { + fmt.Print(err, "\n") + } + + err = json.Unmarshal(raw, &setup) + + return setup +} diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go new file mode 100644 index 0000000..2e620fc --- /dev/null +++ b/ion-cli/config/config_test.go @@ -0,0 +1,30 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package config_test + +import ( + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ion/ion-cli/config" +) + +func Test_Read_ValidSetupJson(t *testing.T) { + path := findPath() + "../setup.json" + setup := config.Read(path) + + assert.Equal(t, "8501", setup.PortTo) + assert.Equal(t, "127.0.0.1", setup.AddrTo) + assert.Equal(t, "8502", setup.PortFrom) + assert.Equal(t, "127.0.0.1", setup.AddrFrom) + assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) +} + +func findPath() string { + _, path, _, _ := runtime.Caller(0) + pathSlice := strings.Split(path, "/") + return strings.Trim(path, pathSlice[len(pathSlice)-1]) +} diff --git a/ion-cli/main.go b/ion-cli/main.go new file mode 100644 index 0000000..8c29cf6 --- /dev/null +++ b/ion-cli/main.go @@ -0,0 +1,29 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/ion/ion-cli/cli" + "github.com/ion/ion-cli/config" +) + +var configFile = flag.String("config", "setup.json", "Description:\n path to the configuration file") + +func main() { + flag.Parse() + + if *configFile != "" { + setup := config.Read(*configFile) + + // Launch the CLI + cli.Launch(setup) + } else { + fmt.Print("Error: empty config!\n") + os.Exit(3) + } + +} diff --git a/ion-cli/setup.json b/ion-cli/setup.json new file mode 100644 index 0000000..9ab7dff --- /dev/null +++ b/ion-cli/setup.json @@ -0,0 +1,9 @@ +{ + "rpc-addr-to":"127.0.0.1", + "rpc-port-to":"8501", + "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "rpc-addr-from":"127.0.0.1", + "rpc-port-from":"8502", + "account-from":"0x8671e5e08d74f338ee1c462340842346d797afd3", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f" +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 5317345..a3d8abd 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,15 +1,12 @@ -const IonLink = artifacts.require("IonLink"); -const IonLock = artifacts.require("IonLock"); -const Token = artifacts.require("Token"); +const Recover = artifacts.require("Recover"); +const Validation = artifacts.require("Validation"); module.exports = async (deployer) => { try { - deployer.deploy(IonLink, 0) - .then(() => IonLink.deployed) - .then(() => deployer.deploy(Token)) - .then(() => Token.deployed) - .then(() => deployer.deploy(IonLock, Token.address, IonLink.address)) - + deployer.deploy(Recover) + .then(() => Recover.deployed) + .then(() => deployer.deploy(Validation, ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"])) + .then(() => Validation.deployed) } catch(err) { console.log('ERROR on deploy:',err); } diff --git a/package-lock.json b/package-lock.json index d2de8a8..4ee3f0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,30 +7,46 @@ "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", - "dev": true + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" }, "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, "requires": { "mime-types": "2.1.18", "negotiator": "0.6.1" } }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.1.0", @@ -38,11 +54,15 @@ "json-schema-traverse": "0.3.1" } }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" + }, "align-text": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, "requires": { "kind-of": "3.2.2", "longest": "1.0.1", @@ -52,52 +72,45 @@ "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "ansi-escapes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", - "dev": true + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } }, + "antlr4": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.0.tgz", + "integrity": "sha1-KX+VbdwG+DOX/AmQ7PLgzyC/u+4=" + }, "any-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", - "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=", - "dev": true + "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=" }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" - } + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "1.0.3" } @@ -106,7 +119,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, "requires": { "arr-flatten": "1.1.0" } @@ -114,26 +126,22 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, "requires": { "array-uniq": "1.0.3" } @@ -141,118 +149,67 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "4.11.6", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "ast-types": { "version": "0.11.3", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", - "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==", - "dev": true + "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==" }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true, - "optional": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true - }, - "babel-cli": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", - "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", - "dev": true, - "requires": { - "babel-core": "6.26.0", - "babel-polyfill": "6.26.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "chokidar": "1.7.0", - "commander": "2.15.1", - "convert-source-map": "1.5.1", - "fs-readdir-recursive": "1.1.0", - "glob": "7.1.2", - "lodash": "4.17.5", - "output-file-sync": "1.1.2", - "path-is-absolute": "1.0.1", - "slash": "1.0.0", - "source-map": "0.5.7", - "v8flags": "2.1.1" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, "babel-code-frame": { "version": "6.26.0", @@ -305,7 +262,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-generator": "6.26.1", @@ -331,14 +287,12 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -346,7 +300,6 @@ "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, "requires": { "babel-messages": "6.23.0", "babel-runtime": "6.26.0", @@ -361,14 +314,12 @@ "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -376,7 +327,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -387,7 +337,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, "requires": { "babel-helper-explode-assignable-expression": "6.24.1", "babel-runtime": "6.26.0", @@ -398,7 +347,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -410,7 +358,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -422,7 +369,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -433,7 +379,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, "requires": { "babel-helper-bindify-decorators": "6.24.1", "babel-runtime": "6.26.0", @@ -445,7 +390,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, "requires": { "babel-helper-get-function-arity": "6.24.1", "babel-runtime": "6.26.0", @@ -458,7 +402,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -468,7 +411,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -478,7 +420,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -488,7 +429,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -499,7 +439,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -512,7 +451,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, "requires": { "babel-helper-optimise-call-expression": "6.24.1", "babel-messages": "6.23.0", @@ -526,7 +464,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -544,7 +481,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -552,62 +488,52 @@ "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" }, "babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" }, "babel-plugin-syntax-class-properties": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" }, "babel-plugin-syntax-decorators": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" }, "babel-plugin-syntax-export-extensions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" }, "babel-plugin-syntax-flow": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" }, "babel-plugin-syntax-trailing-function-commas": { "version": "6.22.0", @@ -618,7 +544,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-generators": "6.13.0", @@ -629,7 +554,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-functions": "6.13.0", @@ -640,7 +564,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, "requires": { "babel-plugin-syntax-class-constructor-call": "6.18.0", "babel-runtime": "6.26.0", @@ -651,7 +574,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-plugin-syntax-class-properties": "6.13.0", @@ -663,7 +585,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, "requires": { "babel-helper-explode-class": "6.24.1", "babel-plugin-syntax-decorators": "6.13.0", @@ -676,7 +597,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -685,7 +605,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -694,7 +613,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0", @@ -707,7 +625,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, "requires": { "babel-helper-define-map": "6.26.0", "babel-helper-function-name": "6.24.1", @@ -724,7 +641,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -734,7 +650,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -743,7 +658,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -753,7 +667,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -762,7 +675,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -773,7 +685,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -782,7 +693,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, "requires": { "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", "babel-runtime": "6.26.0", @@ -804,7 +714,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -815,7 +724,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, "requires": { "babel-plugin-transform-es2015-modules-amd": "6.24.1", "babel-runtime": "6.26.0", @@ -826,7 +734,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, "requires": { "babel-helper-replace-supers": "6.24.1", "babel-runtime": "6.26.0" @@ -836,7 +743,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, "requires": { "babel-helper-call-delegate": "6.24.1", "babel-helper-get-function-arity": "6.24.1", @@ -850,7 +756,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -860,7 +765,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -869,7 +773,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -880,7 +783,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -889,7 +791,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -898,7 +799,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -909,7 +809,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, "requires": { "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", "babel-plugin-syntax-exponentiation-operator": "6.13.0", @@ -920,7 +819,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, "requires": { "babel-plugin-syntax-export-extensions": "6.13.0", "babel-runtime": "6.26.0" @@ -930,7 +828,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, "requires": { "babel-plugin-syntax-flow": "6.18.0", "babel-runtime": "6.26.0" @@ -940,7 +837,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, "requires": { "babel-plugin-syntax-object-rest-spread": "6.13.0", "babel-runtime": "6.26.0" @@ -950,7 +846,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, "requires": { "regenerator-transform": "0.10.1" } @@ -964,68 +859,10 @@ "babel-types": "6.26.0" } }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "core-js": "2.5.3", - "regenerator-runtime": "0.10.5" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", - "dev": true - } - } - }, - "babel-preset-env": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0", - "browserslist": "2.11.3", - "invariant": "2.2.4", - "semver": "5.5.0" - } - }, "babel-preset-es2015": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", "babel-plugin-transform-es2015-arrow-functions": "6.22.0", @@ -1066,7 +903,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, "requires": { "babel-plugin-transform-class-constructor-call": "6.24.1", "babel-plugin-transform-export-extensions": "6.22.0", @@ -1077,7 +913,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, "requires": { "babel-plugin-syntax-dynamic-import": "6.18.0", "babel-plugin-transform-class-properties": "6.24.1", @@ -1089,7 +924,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, "requires": { "babel-plugin-syntax-trailing-function-commas": "6.22.0", "babel-plugin-transform-async-generator-functions": "6.24.1", @@ -1102,7 +936,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, "requires": { "babel-core": "6.26.0", "babel-runtime": "6.26.0", @@ -1116,14 +949,12 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, "requires": { "source-map": "0.5.7" } @@ -1195,20 +1026,17 @@ "babylon": { "version": "7.0.0-beta.42", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz", - "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==", - "dev": true + "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==" }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "bcrypt-pbkdf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, "optional": true, "requires": { "tweetnacl": "0.14.5" @@ -1217,43 +1045,38 @@ "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, "bignumber.js": { - "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "dev": true - }, - "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true, - "optional": true + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" }, "binaryextensions": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", - "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==", - "dev": true + "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "dev": true + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "5.1.1" + } }, "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" }, "body-parser": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, "requires": { "bytes": "3.0.0", "content-type": "1.0.4", @@ -1271,7 +1094,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, "requires": { "hoek": "4.2.1" } @@ -1280,7 +1102,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -1290,7 +1111,6 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", @@ -1300,57 +1120,106 @@ "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "1.2.0", + "browserify-des": "1.0.1", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", + "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "4.11.6", + "randombytes": "2.0.6" + } }, "browserify-sha3": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", - "dev": true, "requires": { "js-sha3": "0.3.1" } }, - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "dev": true, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "requires": { - "caniuse-lite": "1.0.30000823", - "electron-to-chromium": "1.3.42" + "bn.js": "4.11.6", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" } }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, "buffer-to-arraybuffer": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", - "dev": true + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "dev": true, "requires": { "clone-response": "1.0.2", "get-stream": "3.0.0", @@ -1361,69 +1230,43 @@ "responselike": "1.0.2" } }, - "camelcase": { + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, + "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30000823", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000823.tgz", - "integrity": "sha512-3rrhqUxwBgrwNlWVUEwIJfqdZNwLPX18eTo7MGXb3gueDpbOFW6w5OXyHscdBd6IJcu9wnKmKVd7nSl+r7fmgw==", - "dev": true + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4", "lazy-cache": "1.0.4" } }, - "chai": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", - "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", - "dev": true, - "requires": { - "assertion-error": "1.1.0", - "check-error": "1.0.2", - "deep-eql": "3.0.1", - "get-func-name": "2.0.0", - "pathval": "1.1.0", - "type-detect": "4.0.8" - } - }, - "chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "dev": true, - "requires": { - "check-error": "1.0.2" - } - }, - "chai-bignumber": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/chai-bignumber/-/chai-bignumber-2.0.2.tgz", - "integrity": "sha512-BIdRNjRaoRj4bMsZLKbIZPMNKqmwnzNiyxqBYDSs6dFOCs9w8OHPuUE8e1bH60i1IhOzT0NjLtCD+lKEWB1KTQ==", - "dev": true - }, "chalk": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -1433,38 +1276,26 @@ "chardet": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "optional": true, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.2.3", - "glob-parent": "2.0.0", "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "safe-buffer": "5.1.1" } }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, "requires": { "restore-cursor": "2.0.0" } @@ -1472,14 +1303,12 @@ "cli-spinners": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", - "dev": true + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" }, "cli-table": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "dev": true, "requires": { "colors": "1.0.3" }, @@ -1487,8 +1316,7 @@ "colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" } } }, @@ -1496,7 +1324,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "dev": true, "requires": { "slice-ansi": "0.0.4", "string-width": "1.0.2" @@ -1505,14 +1332,12 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -1521,7 +1346,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -1532,7 +1356,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -1542,14 +1365,12 @@ "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", - "dev": true, "requires": { "string-width": "2.1.1", "strip-ansi": "4.0.0", @@ -1559,20 +1380,17 @@ "clone": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=" }, "clone-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "1.0.0" } @@ -1580,14 +1398,12 @@ "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" }, "cloneable-readable": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, "requires": { "inherits": "2.0.3", "process-nextick-args": "2.0.0", @@ -1597,20 +1413,17 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -1618,71 +1431,71 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", - "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==", - "dev": true + "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==" }, "combined-stream": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, "requires": { "delayed-stream": "1.0.0" } }, "commander": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", - "dev": true + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "typedarray": "0.0.6" + } }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "convert-source-map": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "core-js": { "version": "2.5.3", @@ -1692,24 +1505,55 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cors": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", - "dev": true, "requires": { "object-assign": "4.1.1", "vary": "1.1.2" } }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.1", + "sha.js": "2.4.11" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, "requires": { "nice-try": "1.0.4", "path-key": "2.0.1", @@ -1722,7 +1566,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, "requires": { "boom": "5.2.0" }, @@ -1731,30 +1574,44 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, "requires": { "hoek": "4.2.1" } } } }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.3", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" + } + }, "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=", - "dev": true + "version": "3.1.9-1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", + "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" }, "dargs": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=", - "dev": true + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "requires": { "assert-plus": "1.0.0" } @@ -1762,20 +1619,17 @@ "date-fns": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", - "dev": true + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" }, "death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", - "dev": true + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" }, "debug": { "version": "2.6.9", @@ -1788,74 +1642,98 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, "requires": { "mimic-response": "1.0.0" } }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.2.8" + }, + "dependencies": { + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "detect-conflict": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", - "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=", - "dev": true + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, "requires": { "repeating": "2.0.1" } @@ -1863,26 +1741,50 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "4.11.6", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "2.0.2" + } }, "dom-walk": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", - "dev": true + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "create-hmac": "1.1.7" + } }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, "optional": true, "requires": { "jsbn": "0.1.1" @@ -1891,38 +1793,27 @@ "editions": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", - "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", - "dev": true + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "ejs": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.42", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz", - "integrity": "sha1-lcM78B0MxAVVauyJn+Yf1NduoPk=", - "dev": true + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, "requires": { "bn.js": "4.11.6", "brorand": "1.1.0", @@ -1936,20 +1827,17 @@ "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "enhanced-resolve": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", - "dev": true, "requires": { "graceful-fs": "4.1.11", "memory-fs": "0.4.1", @@ -1960,7 +1848,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, "requires": { "prr": "1.0.1" } @@ -1969,7 +1856,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, "requires": { "string-template": "0.2.1", "xtend": "4.0.1" @@ -1979,7 +1865,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, "requires": { "is-arrayish": "0.2.1" } @@ -1987,8 +1872,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", @@ -1999,7 +1883,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, "requires": { "esprima": "2.7.3", "estraverse": "1.9.3", @@ -2011,14 +1894,17 @@ "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, "optional": true, "requires": { "amdefine": "1.0.1" @@ -2026,17 +1912,145 @@ } } }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.2", + "concat-stream": "1.6.2", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "3.3.10", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.5", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.2", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.5", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "3.0.1" + } + }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { "version": "2.0.2", @@ -2046,14 +2060,12 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "eth-lib": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", - "dev": true, "requires": { "bn.js": "4.11.6", "elliptic": "6.4.0", @@ -2068,27 +2080,61 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.2.tgz", "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", - "dev": true, "requires": { "source-map-support": "0.5.4", "webpack-cli": "2.0.12" } }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.6", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.1", + "secp256k1": "3.5.0" + } + }, "ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "dev": true, "requires": { "bn.js": "4.11.6", "number-to-bn": "1.7.0" } }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, "requires": { "cross-spawn": "5.1.0", "get-stream": "3.0.0", @@ -2103,7 +2149,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, "requires": { "lru-cache": "4.1.2", "shebang-command": "1.2.0", @@ -2115,14 +2160,12 @@ "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -2131,7 +2174,6 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, "requires": { "fill-range": "2.2.3" } @@ -2140,7 +2182,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, "requires": { "homedir-polyfill": "1.0.1" } @@ -2149,7 +2190,6 @@ "version": "4.16.3", "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", - "dev": true, "requires": { "accepts": "1.3.5", "array-flatten": "1.1.1", @@ -2186,22 +2226,19 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" } } }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "external-editor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", - "dev": true, "requires": { "chardet": "0.4.2", "iconv-lite": "0.4.19", @@ -2212,7 +2249,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -2220,47 +2256,49 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5" } }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -2273,7 +2311,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "1.0.2", @@ -2288,7 +2325,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, "requires": { "locate-path": "2.0.0" } @@ -2297,22 +2333,30 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "dev": true, "requires": { "readable-stream": "2.3.5" } }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, "flow-parser": { "version": "0.68.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.68.0.tgz", - "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=", - "dev": true + "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=" }, "for-each": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", - "dev": true, "requires": { "is-function": "1.0.1" } @@ -2320,14 +2364,12 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, "requires": { "for-in": "1.0.2" } @@ -2335,14 +2377,12 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, "requires": { "asynckit": "0.4.0", "combined-stream": "1.0.6", @@ -2352,20 +2392,17 @@ "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.5" @@ -2375,7 +2412,6 @@ "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "jsonfile": "2.4.0", @@ -2384,546 +2420,15 @@ "rimraf": "2.2.8" } }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fsevents": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.3.tgz", - "integrity": "sha512-X+57O5YkDTiEQGiw8i7wYc2nQgweIekqkepI8Q3y4wVlurgBt2SuwxTeYUYMZIGpLZH3r/TsMjczCMXE5ZOt7Q==", - "dev": true, - "optional": true, - "requires": { - "nan": "2.10.0", - "node-pre-gyp": "0.9.1" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.9.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.0", - "nopt": "4.0.1", - "npm-packlist": "1.1.10", - "npmlog": "4.1.2", - "rc": "1.2.6", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "4.4.1" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.2.4", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "ganache-cli": { "version": "6.1.0", @@ -2938,26 +2443,17 @@ "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, "requires": { "assert-plus": "1.0.0" } @@ -2966,7 +2462,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", - "dev": true, "requires": { "got": "7.1.0", "is-plain-obj": "1.1.0" @@ -2976,7 +2471,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, "requires": { "decompress-response": "3.3.0", "duplexer3": "0.1.4", @@ -2997,14 +2491,12 @@ "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" }, "p-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, "requires": { "p-finally": "1.0.0" } @@ -3012,14 +2504,12 @@ "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, "requires": { "prepend-http": "1.0.4" } @@ -3030,7 +2520,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", - "dev": true, "requires": { "gh-got": "6.0.0" } @@ -3039,7 +2528,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -3053,7 +2541,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", - "dev": true, "requires": { "glob": "7.1.2", "yargs": "1.2.6" @@ -3063,7 +2550,6 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", - "dev": true, "requires": { "minimist": "0.1.0" } @@ -3074,7 +2560,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" @@ -3084,7 +2569,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, "requires": { "is-glob": "2.0.1" } @@ -3093,7 +2577,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, "requires": { "min-document": "2.19.0", "process": "0.5.2" @@ -3103,7 +2586,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, "requires": { "global-prefix": "1.0.2", "is-windows": "1.0.2", @@ -3114,7 +2596,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, "requires": { "expand-tilde": "2.0.2", "homedir-polyfill": "1.0.1", @@ -3132,7 +2613,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, "requires": { "array-union": "1.0.2", "glob": "7.1.2", @@ -3144,8 +2624,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -3153,7 +2632,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/got/-/got-8.3.0.tgz", "integrity": "sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==", - "dev": true, "requires": { "@sindresorhus/is": "0.7.0", "cacheable-request": "2.1.4", @@ -3177,8 +2655,7 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graceful-readlink": { "version": "1.0.1", @@ -3190,7 +2667,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", - "dev": true, "requires": { "lodash": "4.17.5" } @@ -3205,7 +2681,6 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, "requires": { "async": "1.5.2", "optimist": "0.6.1", @@ -3217,7 +2692,6 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, "requires": { "amdefine": "1.0.1" } @@ -3227,14 +2701,12 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, "requires": { "ajv": "5.5.2", "har-schema": "2.0.0" @@ -3258,35 +2730,39 @@ "has-color": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" }, "has-to-string-tag-x": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, "requires": { - "has-symbol-support-x": "1.4.2" + "has-symbol-support-x": "1.4.2" + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" } }, "hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, "requires": { "inherits": "2.0.3", "minimalistic-assert": "1.0.0" @@ -3296,7 +2772,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", @@ -3307,14 +2782,12 @@ "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, "requires": { "hash.js": "1.1.3", "minimalistic-assert": "1.0.0", @@ -3324,14 +2797,12 @@ "hoek": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" @@ -3341,7 +2812,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, "requires": { "parse-passwd": "1.0.0" } @@ -3349,20 +2819,17 @@ "hosted-git-info": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", - "dev": true + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" }, "http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, "requires": { "depd": "1.1.1", "inherits": "2.0.3", @@ -3373,16 +2840,19 @@ "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" } } }, + "http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", @@ -3392,20 +2862,22 @@ "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, "requires": { "repeating": "2.0.1" } @@ -3414,7 +2886,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -3423,20 +2894,17 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.1.0.tgz", "integrity": "sha512-kn7N70US1MSZHZHSGJLiZ7iCwwncc7b0gc68YtlX29OjI3Mp0tSVV+snVXpZ1G+ONS3Ac9zd1m6hve2ibLDYfA==", - "dev": true, "requires": { "ansi-escapes": "3.0.0", "chalk": "2.3.2", @@ -3456,14 +2924,12 @@ "interpret": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" }, "into-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, "requires": { "from2": "2.3.0", "p-is-promise": "1.1.0" @@ -3480,42 +2946,27 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", - "dev": true + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "1.11.0" - } + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, "requires": { "builtin-modules": "1.1.1" } @@ -3523,14 +2974,12 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, "requires": { "is-primitive": "2.0.0" } @@ -3538,20 +2987,17 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -3559,20 +3005,17 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-function": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", - "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=", - "dev": true + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -3580,14 +3023,12 @@ "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", - "dev": true + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -3595,14 +3036,12 @@ "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" }, "is-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz", "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", - "dev": true, "requires": { "symbol-observable": "0.2.4" }, @@ -3610,46 +3049,65 @@ "symbol-observable": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", - "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", - "dev": true + "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=" } } }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "1.0.2" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" }, "is-scoped": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", - "dev": true, "requires": { "scoped-regex": "1.0.0" } @@ -3657,44 +3115,37 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -3702,14 +3153,12 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, "requires": { "abbrev": "1.0.9", "async": "1.5.2", @@ -3717,7 +3166,7 @@ "esprima": "2.7.3", "glob": "5.0.15", "handlebars": "4.0.11", - "js-yaml": "3.11.0", + "js-yaml": "3.12.0", "mkdirp": "0.5.1", "nopt": "3.0.6", "once": "1.4.0", @@ -3730,14 +3179,12 @@ "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, "requires": { "inflight": "1.0.6", "inherits": "2.0.3", @@ -3749,20 +3196,17 @@ "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" }, "supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, "requires": { "has-flag": "1.0.0" } @@ -3773,7 +3217,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true, "requires": { "binaryextensions": "2.1.1", "editions": "1.3.4", @@ -3784,41 +3227,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, "requires": { "has-to-string-tag-x": "1.4.1", "is-object": "1.0.1" } }, - "jade": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, - "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", - "dev": true - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", - "dev": true - } - } - }, "js-sha3": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", - "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=", - "dev": true + "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" }, "js-tokens": { "version": "3.0.2", @@ -3826,10 +3243,9 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "dev": true, + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "requires": { "argparse": "1.0.10", "esprima": "4.0.0" @@ -3839,14 +3255,12 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, "optional": true }, "jscodeshift": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.0.tgz", "integrity": "sha512-JAcQINNMFpdzzpKJN8k5xXjF3XDuckB1/48uScSzcnNyK199iWEc9AxKL9OoX5144M2w5zEx9Qs4/E/eBZZUlw==", - "dev": true, "requires": { "babel-plugin-transform-flow-strip-types": "6.22.0", "babel-preset-es2015": "6.24.1", @@ -3868,8 +3282,7 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" }, "json-bigint-string": { "version": "1.0.0", @@ -3880,32 +3293,32 @@ "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, "json-parse-better-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", - "dev": true + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==" }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json3": { "version": "3.3.2", @@ -3916,14 +3329,12 @@ "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, "requires": { "graceful-fs": "4.1.11" } @@ -3932,7 +3343,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -3940,11 +3350,21 @@ "verror": "1.10.0" } }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "1.3.0", + "inherits": "2.0.3", + "nan": "2.10.0", + "safe-buffer": "5.1.1" + } + }, "keccakjs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", - "dev": true, "requires": { "browserify-sha3": "0.0.1", "sha3": "1.2.0" @@ -3954,7 +3374,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, "requires": { "json-buffer": "3.0.0" } @@ -3963,7 +3382,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -3972,7 +3390,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, "requires": { "graceful-fs": "4.1.11" } @@ -3981,14 +3398,12 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, "optional": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "1.0.0" } @@ -3997,7 +3412,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "1.1.2", "type-check": "0.3.2" @@ -4007,7 +3421,6 @@ "version": "0.13.0", "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz", "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-truncate": "0.2.1", @@ -4031,20 +3444,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -4057,7 +3467,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4067,7 +3476,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, "requires": { "chalk": "1.1.3" } @@ -4076,7 +3484,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4084,22 +3491,19 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, "listr-silent-renderer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" }, "listr-update-renderer": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-truncate": "0.2.1", @@ -4114,20 +3518,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -4140,7 +3541,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4149,14 +3549,12 @@ "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" }, "log-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, "requires": { "chalk": "1.1.3" } @@ -4165,7 +3563,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4173,8 +3570,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, @@ -4182,7 +3578,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-cursor": "1.0.2", @@ -4193,20 +3588,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -4219,7 +3611,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -4228,7 +3619,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4237,14 +3627,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -4254,7 +3642,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4262,8 +3649,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, @@ -4271,7 +3657,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "4.0.0", @@ -4282,8 +3667,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" } } }, @@ -4291,7 +3675,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, "requires": { "big.js": "3.2.0", "emojis-list": "2.1.0", @@ -4302,7 +3685,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, "requires": { "p-locate": "2.0.0", "path-exists": "3.0.0" @@ -4350,8 +3732,7 @@ "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" }, "lodash.create": { "version": "3.1.1", @@ -4391,7 +3772,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, "requires": { "chalk": "2.3.2" } @@ -4400,7 +3780,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", - "dev": true, "requires": { "ansi-escapes": "1.4.0", "cli-cursor": "1.0.2" @@ -4409,14 +3788,12 @@ "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, "cli-cursor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -4424,14 +3801,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -4442,8 +3817,7 @@ "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, "loose-envify": { "version": "1.3.1", @@ -4456,14 +3830,12 @@ "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" }, "lru-cache": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "dev": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" @@ -4473,22 +3845,28 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", - "dev": true, "requires": { "pify": "3.0.0" } }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -4497,7 +3875,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", - "dev": true, "requires": { "through2": "2.0.3", "vinyl": "1.2.0", @@ -4508,7 +3885,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-3.0.2.tgz", "integrity": "sha1-3Qpuryu4prN3QAZ6pUnrUwEFr58=", - "dev": true, "requires": { "commondir": "1.0.1", "deep-extend": "0.4.2", @@ -4525,26 +3901,22 @@ "clone": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" }, "clone-stats": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" }, "replace-ext": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" }, "vinyl": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, "requires": { "clone": "2.1.1", "clone-buffer": "1.0.0", @@ -4560,7 +3932,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, "requires": { "errno": "0.1.7", "readable-stream": "2.3.5" @@ -4569,26 +3940,22 @@ "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", - "dev": true + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -4605,23 +3972,29 @@ "regex-cache": "0.4.4" } }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "4.11.6", + "brorand": "1.1.0" + } + }, "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" }, "mime-types": { "version": "2.1.18", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true, "requires": { "mime-db": "1.33.0" } @@ -4629,20 +4002,17 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, "mimic-response": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", - "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", - "dev": true + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" }, "min-document": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, "requires": { "dom-walk": "0.1.1" } @@ -4650,20 +4020,17 @@ "minimalistic-assert": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", - "dev": true + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "1.1.11" } @@ -4671,14 +4038,12 @@ "minimist": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", - "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=", - "dev": true + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -4686,8 +4051,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, @@ -4775,7 +4139,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, "requires": { "array-differ": "1.0.0", "array-union": "1.0.2", @@ -4786,50 +4149,47 @@ "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "nan": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "nano-json-stream-parser": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", - "dev": true + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "neo-async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", - "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==", - "dev": true + "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==" }, "nice-try": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", - "dev": true + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" }, "node-dir": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", - "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=", - "dev": true + "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" }, "nomnom": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "dev": true, "requires": { "chalk": "0.4.0", "underscore": "1.6.0" @@ -4838,14 +4198,12 @@ "ansi-styles": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" }, "chalk": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, "requires": { "ansi-styles": "1.0.0", "has-color": "0.1.7", @@ -4855,8 +4213,7 @@ "strip-ansi": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" } } }, @@ -4864,7 +4221,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, "requires": { "abbrev": "1.0.9" } @@ -4873,7 +4229,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, "requires": { "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", @@ -4885,7 +4240,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, "requires": { "remove-trailing-separator": "1.1.0" } @@ -4894,7 +4248,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, "requires": { "prepend-http": "2.0.0", "query-string": "5.1.1", @@ -4905,7 +4258,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, "requires": { "path-key": "2.0.1" } @@ -4913,14 +4265,12 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "dev": true, "requires": { "bn.js": "4.11.6", "strip-hex-prefix": "1.0.0" @@ -4929,30 +4279,34 @@ "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" } }, + "oboe": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", + "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", + "requires": { + "http-https": "1.0.0" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, "requires": { "ee-first": "1.1.1" } @@ -4961,7 +4315,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1.0.2" } @@ -4970,7 +4323,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -4979,7 +4331,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, "requires": { "minimist": "0.0.10", "wordwrap": "0.0.3" @@ -4988,14 +4339,12 @@ "minimist": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" } } }, @@ -5003,7 +4352,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, "requires": { "deep-is": "0.1.3", "fast-levenshtein": "2.0.6", @@ -5017,7 +4365,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-cursor": "1.0.2", @@ -5028,20 +4375,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -5054,7 +4398,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -5062,14 +4405,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -5079,7 +4420,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -5087,8 +4427,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, @@ -5101,14 +4440,12 @@ "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, "requires": { "execa": "0.7.0", "lcid": "1.0.0", @@ -5118,31 +4455,17 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "output-file-sync": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", - "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "object-assign": "4.1.1" - } + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "p-cancelable": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.0.tgz", - "integrity": "sha512-/AodqPe1y/GYbhSlnMjxukLGQfQIgsmjSy2CXCNB96kg4ozKvmlovuHEKICToOO/yS3LLWgrWI1dFtFfrePS1g==", - "dev": true + "integrity": "sha512-/AodqPe1y/GYbhSlnMjxukLGQfQIgsmjSy2CXCNB96kg4ozKvmlovuHEKICToOO/yS3LLWgrWI1dFtFfrePS1g==" }, "p-each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", - "dev": true, "requires": { "p-reduce": "1.0.0" } @@ -5150,26 +4473,22 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-is-promise": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" }, "p-lazy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", - "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=", - "dev": true + "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" }, "p-limit": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "dev": true, "requires": { "p-try": "1.0.0" } @@ -5178,7 +4497,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, "requires": { "p-limit": "1.2.0" } @@ -5186,20 +4504,17 @@ "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, "requires": { "p-finally": "1.0.0" } @@ -5207,14 +4522,24 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" + } }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", @@ -5226,7 +4551,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", - "dev": true, "requires": { "for-each": "0.3.2", "trim": "0.0.1" @@ -5236,7 +4560,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, "requires": { "error-ex": "1.3.1", "json-parse-better-errors": "1.0.1" @@ -5245,146 +4568,145 @@ "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, "requires": { "pify": "3.0.0" } }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "requires": { + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.1", + "sha.js": "2.4.11" + } }, "pegjs": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", - "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=", - "dev": true + "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "2.0.4" } }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "prettier": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz", - "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==", - "dev": true + "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==" }, "pretty-bytes": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" }, "proxy-addr": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", - "dev": true, "requires": { "forwarded": "0.1.2", "ipaddr.js": "1.6.0" @@ -5393,32 +4715,39 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "requires": { + "bn.js": "4.11.6", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "query-string": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, "requires": { "decode-uri-component": "0.2.0", "object-assign": "4.1.1", @@ -5429,7 +4758,6 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -5439,7 +4767,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -5448,7 +4775,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -5459,30 +4785,43 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "1.1.6" } } } }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, "randomhex": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", - "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=", - "dev": true + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, "requires": { "bytes": "3.0.0", "http-errors": "1.6.2", @@ -5494,7 +4833,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", - "dev": true, "requires": { "pify": "3.0.0", "safe-buffer": "5.1.1" @@ -5504,7 +4842,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, "requires": { "load-json-file": "4.0.0", "normalize-package-data": "2.4.0", @@ -5515,7 +4852,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, "requires": { "find-up": "2.1.0", "read-pkg": "3.0.0" @@ -5525,7 +4861,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", - "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -5536,24 +4871,10 @@ "util-deprecate": "1.0.2" } }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.5", - "set-immediate-shim": "1.0.1" - } - }, "recast": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.5.tgz", "integrity": "sha512-GNFQGQrqW1R8w9XhhgYIN8H7ePPp088D+svHlb7DdP5DCqNDqTwH7lt378EouM+L18kCwkmqpAz1unLqpPhHmw==", - "dev": true, "requires": { "ast-types": "0.11.3", "esprima": "4.0.0", @@ -5565,7 +4886,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, "requires": { "resolve": "1.5.0" } @@ -5573,8 +4893,7 @@ "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", - "dev": true + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" }, "regenerator-runtime": { "version": "0.11.1", @@ -5585,7 +4904,6 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -5596,16 +4914,19 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, "requires": { "is-equal-shallow": "0.1.3" } }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==" + }, "regexpu-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, "requires": { "regenerate": "1.3.3", "regjsgen": "0.2.0", @@ -5615,14 +4936,12 @@ "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" }, "regjsparser": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, "requires": { "jsesc": "0.5.0" } @@ -5630,26 +4949,22 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, "requires": { "is-finite": "1.0.2" } @@ -5657,14 +4972,12 @@ "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" }, "req-cwd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", - "dev": true, "requires": { "req-from": "1.0.1" } @@ -5673,7 +4986,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", - "dev": true, "requires": { "resolve-from": "2.0.0" }, @@ -5681,8 +4993,7 @@ "resolve-from": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" } } }, @@ -5690,7 +5001,6 @@ "version": "2.85.0", "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", - "dev": true, "requires": { "aws-sign2": "0.7.0", "aws4": "1.6.0", @@ -5719,26 +5029,38 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-from-string": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", - "dev": true + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + } + } }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, "requires": { "path-parse": "1.0.5" } @@ -5747,7 +5069,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, "requires": { "resolve-from": "3.0.0" } @@ -5756,7 +5077,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, "requires": { "expand-tilde": "2.0.2", "global-modules": "1.0.0" @@ -5765,14 +5085,12 @@ "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, "requires": { "lowercase-keys": "1.0.0" } @@ -5781,7 +5099,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, "requires": { "onetime": "2.0.1", "signal-exit": "3.0.2" @@ -5791,7 +5108,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4" @@ -5800,14 +5116,26 @@ "rimraf": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "rlp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.0.0.tgz", + "integrity": "sha1-nbOE/0uJqPYVY9kjldhiWxjzr7A=" }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, "requires": { "is-promise": "2.1.0" } @@ -5815,14 +5143,12 @@ "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" }, "rx-lite-aggregates": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, "requires": { "rx-lite": "4.0.8" } @@ -5831,7 +5157,6 @@ "version": "5.5.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", "integrity": "sha512-Hxo2ac8gRQjwjtKgukMIwBRbq5+KAeEV5hXM4obYBOAghev41bDQWgFH4svYiU9UnQ5kNww2LgfyBdevCd2HXA==", - "dev": true, "requires": { "symbol-observable": "1.0.1" } @@ -5839,26 +5164,62 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "scoped-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", - "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=", - "dev": true + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" + }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "requires": { + "nan": "2.10.0" + } + }, + "scrypt.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", + "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", + "requires": { + "scrypt": "6.0.3", + "scryptsy": "1.2.1" + } + }, + "scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "requires": { + "pbkdf2": "3.0.16" + } + }, + "secp256k1": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.0.tgz", + "integrity": "sha512-e5QIJl8W7Y4tT6LHffVcZAxJjvpgE5Owawv6/XCYPQljE9aP2NFFddQ8OYMKhdLshNu88FfL3qCN3/xYkXGRsA==", + "requires": { + "bindings": "1.3.0", + "bip66": "1.1.5", + "bn.js": "4.11.6", + "create-hash": "1.2.0", + "drbg.js": "1.0.1", + "elliptic": "6.4.0", + "nan": "2.10.0", + "safe-buffer": "5.1.1" + } }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, "requires": { "debug": "2.6.9", "depd": "1.1.2", @@ -5879,7 +5240,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, "requires": { "encodeurl": "1.0.2", "escape-html": "1.0.3", @@ -5891,7 +5251,6 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", - "dev": true, "requires": { "body-parser": "1.18.2", "cors": "2.8.4", @@ -5903,27 +5262,26 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true, - "optional": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } }, "sha3": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.0.tgz", "integrity": "sha1-aYnxtwpJhwWHajc+LGKs6WqpOZo=", - "dev": true, "requires": { "nan": "2.10.0" } @@ -5932,7 +5290,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, "requires": { "shebang-regex": "1.0.0" } @@ -5940,43 +5297,32 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "shelljs": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", - "dev": true, "requires": { "glob": "7.1.2", "interpret": "1.1.0", "rechoir": "0.6.2" } }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "simple-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", - "dev": true + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" }, "simple-get": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz", "integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==", - "dev": true, "requires": { "decompress-response": "3.3.0", "once": "1.4.0", @@ -5986,26 +5332,22 @@ "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" }, "slide": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" }, "sntp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, "requires": { "hoek": "4.2.1" } @@ -6013,14 +5355,12 @@ "sol-explore": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", - "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=", - "dev": true + "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=" }, "solc": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.23.tgz", "integrity": "sha512-AT7anLHY6uIRg2It6N0UlCHeZ7YeecIkUhnlirrCgCPCUevtnoN48BxvgigN/4jJTRljv5oFhAJtI6gvHzT5DQ==", - "dev": true, "requires": { "fs-extra": "0.30.0", "memorystream": "0.3.1", @@ -6032,20 +5372,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1", @@ -6056,7 +5393,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, "requires": { "path-exists": "2.1.0", "pinkie-promise": "2.0.1" @@ -6066,7 +5402,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -6075,7 +5410,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", @@ -6088,7 +5422,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, "requires": { "lcid": "1.0.0" } @@ -6097,7 +5430,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, "requires": { "error-ex": "1.3.1" } @@ -6106,7 +5438,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, "requires": { "pinkie-promise": "2.0.1" } @@ -6115,7 +5446,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -6125,14 +5455,12 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, "requires": { "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", @@ -6143,7 +5471,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, "requires": { "find-up": "1.1.2", "read-pkg": "1.1.0" @@ -6153,7 +5480,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -6164,7 +5490,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -6172,20 +5497,17 @@ "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" }, "yargs": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, "requires": { "cliui": "3.2.0", "decamelize": "1.2.0", @@ -6207,7 +5529,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, "requires": { "camelcase": "3.0.0", "lodash.assign": "4.2.0" @@ -6215,11 +5536,30 @@ } } }, + "solhint": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.2.1.tgz", + "integrity": "sha512-3B0ydhkOlicyyTmKnwJC6kiwdJUXvbbDYXcy8m7rznoQPgzzkmSOsJgb9BAe+KBQP5BD3PLgcoOQ84t3FSxqsQ==", + "requires": { + "antlr4": "4.7.0", + "commander": "2.11.0", + "eslint": "4.19.1", + "glob": "7.1.2", + "ignore": "3.3.10", + "lodash": "4.17.10" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } + } + }, "solidity-coverage": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.4.14.tgz", - "integrity": "sha512-4IizUjKsBpdIe5cVB/jfjuwO9On91JLxxCyID9poSW9owaQaXRHGlQltWUFbLlAbzb0dBsPscRnv2byDbKYQTA==", - "dev": true, + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.5.4.tgz", + "integrity": "sha512-UvjLBgUJiLvufU6K9xmf/gPIU7DhWcDmBA6iTJ0dZI7LsvU+vugN1/ByZojU54kWLpaODx0A+P4cIT0jcRVNNw==", "requires": { "death": "1.1.0", "ethereumjs-testrpc-sc": "6.1.2", @@ -6228,30 +5568,46 @@ "req-cwd": "1.0.1", "shelljs": "0.7.8", "sol-explore": "1.6.2", - "solidity-parser-sc": "0.4.6", + "solidity-parser-sc": "0.4.10", + "tree-kill": "1.2.0", "web3": "0.18.4" }, "dependencies": { + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + }, "shelljs": { "version": "0.7.8", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, "requires": { "glob": "7.1.2", "interpret": "1.1.0", "rechoir": "0.6.2" } + }, + "web3": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", + "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } } } }, "solidity-parser-sc": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.6.tgz", - "integrity": "sha512-+fu+4L4XomonLf/BvG0hv/otIpWr7wFB0X/QHzfQP68ER+FrQ8vou11/OPsOqc7yHWhowi0oe4JcKFZgAEUThw==", - "dev": true, + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.10.tgz", + "integrity": "sha512-oGgFpeX4OzvOfku/Bnw3/yrOmcVJTgXa994HjZwWXA/kHVZ4L1ml9BcbWHRAziJYm3ObHCXlKumfMCBXBt9K8Q==", "requires": { - "mocha": "2.5.3", + "mocha": "4.1.0", "pegjs": "0.10.0", "yargs": "4.8.1" }, @@ -6259,20 +5615,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1", @@ -6280,51 +5633,41 @@ } }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { - "ms": "0.7.1" + "ms": "2.0.0" } }, - "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", - "dev": true + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, "requires": { "path-exists": "2.1.0", "pinkie-promise": "2.0.1" } }, - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimatch": "0.3.0" - } + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -6333,7 +5676,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", @@ -6342,51 +5684,27 @@ "strip-bom": "2.0.0" } }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - }, "mocha": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", - "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", "requires": { - "commander": "2.3.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", - "growl": "1.9.2", - "jade": "0.26.3", + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" + "supports-color": "4.4.0" } }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, "requires": { "lcid": "1.0.0" } @@ -6395,7 +5713,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, "requires": { "error-ex": "1.3.1" } @@ -6404,7 +5721,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, "requires": { "pinkie-promise": "2.0.1" } @@ -6413,7 +5729,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -6423,14 +5738,12 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, "requires": { "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", @@ -6441,7 +5754,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, "requires": { "find-up": "1.1.2", "read-pkg": "1.1.0" @@ -6451,7 +5763,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -6462,34 +5773,32 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } }, "supports-color": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", - "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", - "dev": true + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "2.0.0" + } }, "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" }, "yargs": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, "requires": { "cliui": "3.2.0", "decamelize": "1.2.0", @@ -6511,7 +5820,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, "requires": { "camelcase": "3.0.0", "lodash.assign": "4.2.0" @@ -6523,7 +5831,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, "requires": { "is-plain-obj": "1.1.0" } @@ -6531,14 +5838,12 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", - "dev": true, "requires": { "source-map": "0.6.1" } @@ -6547,7 +5852,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, "requires": { "spdx-expression-parse": "3.0.0", "spdx-license-ids": "3.0.0" @@ -6556,14 +5860,12 @@ "spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "2.1.0", "spdx-license-ids": "3.0.0" @@ -6572,20 +5874,17 @@ "spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", - "dev": true, "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", @@ -6600,14 +5899,12 @@ "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" }, "stream-to-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", - "dev": true, "requires": { "any-observable": "0.2.0" } @@ -6615,20 +5912,17 @@ "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" @@ -6638,7 +5932,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -6646,14 +5939,12 @@ "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "3.0.0" } @@ -6662,7 +5953,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, "requires": { "is-utf8": "0.2.1" } @@ -6671,7 +5961,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", - "dev": true, "requires": { "first-chunk-stream": "2.0.0", "strip-bom": "2.0.0" @@ -6680,23 +5969,25 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "dev": true, "requires": { "is-hex-prefixed": "1.0.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, "supports-color": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -6704,20 +5995,40 @@ "symbol-observable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.2", + "lodash": "4.17.5", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + } + } }, "tapable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "dev": true, "requires": { "os-tmpdir": "1.0.2", "rimraf": "2.2.8" @@ -6726,26 +6037,22 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "textextensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", - "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==", - "dev": true + "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, "requires": { "readable-stream": "2.3.5", "xtend": "4.0.1" @@ -6754,14 +6061,12 @@ "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "requires": { "os-tmpdir": "1.0.2" } @@ -6771,32 +6076,28 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" }, - "to-iso-string": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", - "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", - "dev": true - }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, "requires": { "punycode": "1.4.1" } }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" + }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, "truffle": { "version": "4.1.7", @@ -6813,7 +6114,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -6822,39 +6122,42 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, "optional": true }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "1.1.2" } }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "2.1.18" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "1.0.0" + } + }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, "optional": true, "requires": { "source-map": "0.5.7", @@ -6866,14 +6169,12 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, "optional": true }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, "optional": true, "requires": { "center-align": "0.1.3", @@ -6885,21 +6186,18 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, "optional": true }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, "optional": true }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, "optional": true, "requires": { "camelcase": "1.2.1", @@ -6914,38 +6212,32 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, "optional": true }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "untildify": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz", - "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", - "dev": true + "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=" }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, "requires": { "prepend-http": "2.0.0" } @@ -6953,65 +6245,42 @@ "url-set-query": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", - "dev": true + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" }, "url-to-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, "utf8": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", - "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=", - "dev": true + "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, "v8-compile-cache": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz", - "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } + "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==" }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true, "requires": { "spdx-correct": "3.0.0", "spdx-expression-parse": "3.0.0" @@ -7020,14 +6289,12 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "requires": { "assert-plus": "1.0.0", "core-util-is": "1.0.2", @@ -7038,7 +6305,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, "requires": { "clone": "1.0.3", "clone-stats": "0.0.1", @@ -7049,7 +6315,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -7062,40 +6327,355 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "web3": { + "version": "github:ethereum/web3.js#59aae306c1c31ef6a65b9196e7f03af74c69e059", + "requires": { + "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" + }, + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + } + } + }, + "web3-core": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.34.tgz", + "integrity": "sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4=", + "requires": { + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-core-requestmanager": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.33", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.33.tgz", + "integrity": "sha1-Kvcz5QTbBefDZIwdrPV3sOwV3EM=", + "dev": true, + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.33", + "web3-utils": "1.0.0-beta.33" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", "dev": true } } }, - "web3": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", - "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", - "dev": true, - "requires": { - "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "crypto-js": "3.1.8", - "utf8": "2.1.2", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - } - }, - "web3-core-helpers": { - "version": "1.0.0-beta.33", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.33.tgz", - "integrity": "sha1-Kvcz5QTbBefDZIwdrPV3sOwV3EM=", - "dev": true, + "web3-core-method": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz", + "integrity": "sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-promievent": "1.0.0-beta.34", + "web3-core-subscriptions": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz", + "integrity": "sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw=", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz", + "integrity": "sha1-Afj2zyrmtvC3DDi64e90G1urIVw=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-providers-http": "1.0.0-beta.34", + "web3-providers-ipc": "1.0.0-beta.34", + "web3-providers-ws": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz", + "integrity": "sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4=", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-eth": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.34.tgz", + "integrity": "sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg=", "requires": { "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.33", - "web3-utils": "1.0.0-beta.33" + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-core-subscriptions": "1.0.0-beta.34", + "web3-eth-abi": "1.0.0-beta.34", + "web3-eth-accounts": "1.0.0-beta.34", + "web3-eth-contract": "1.0.0-beta.34", + "web3-eth-iban": "1.0.0-beta.34", + "web3-eth-personal": "1.0.0-beta.34", + "web3-net": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" }, "dependencies": { "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", + "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", + "requires": { + "bn.js": "4.11.6", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } } } }, @@ -7119,6 +6699,170 @@ } } }, + "web3-eth-accounts": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz", + "integrity": "sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM=", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + }, + "dependencies": { + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + } + } + } + } + }, + "web3-eth-contract": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz", + "integrity": "sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY=", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-core-promievent": "1.0.0-beta.34", + "web3-core-subscriptions": "1.0.0-beta.34", + "web3-eth-abi": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", + "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", + "requires": { + "bn.js": "4.11.6", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, "web3-eth-iban": { "version": "1.0.0-beta.33", "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.33.tgz", @@ -7129,6 +6873,263 @@ "web3-utils": "1.0.0-beta.33" } }, + "web3-eth-personal": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz", + "integrity": "sha1-mvuhZzQuveVCC81YlcP2w0OI8gU=", + "requires": { + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-net": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-net": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.34.tgz", + "integrity": "sha1-QnzqL0MYgUScjjjVIykPFz+f9j0=", + "requires": { + "web3-core": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz", + "integrity": "sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno=", + "requires": { + "web3-core-helpers": "1.0.0-beta.34", + "xhr2": "0.1.4" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz", + "integrity": "sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao=", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz", + "integrity": "sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, "web3-utils": { "version": "1.0.0-beta.33", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.33.tgz", @@ -7162,7 +7163,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", - "dev": true, "requires": { "jscodeshift": "0.4.1" }, @@ -7170,20 +7170,17 @@ "ast-types": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", - "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==", - "dev": true + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" }, "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, "jscodeshift": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", - "dev": true, "requires": { "async": "1.5.2", "babel-plugin-transform-flow-strip-types": "6.22.0", @@ -7206,7 +7203,6 @@ "version": "0.12.9", "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", - "dev": true, "requires": { "ast-types": "0.10.1", "core-js": "2.5.3", @@ -7221,7 +7217,6 @@ "version": "2.0.12", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.12.tgz", "integrity": "sha512-kMi6NquWwUhmQok2IFrtAEIbaVvujzYvtDGb5WElkwylbLboDsCgizv8IjSi/Q6SQRJ8Crayl1JCBnIJ3rU4Rg==", - "dev": true, "requires": { "chalk": "2.3.2", "cross-spawn": "6.0.5", @@ -7250,11 +7245,19 @@ "yeoman-generator": "2.0.3" } }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "requires": { + "debug": "2.6.9", + "nan": "2.10.0", + "typedarray-to-buffer": "3.1.5", + "yaeti": "0.0.6" + } + }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, "requires": { "isexe": "2.0.0" } @@ -7262,27 +7265,23 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, "optional": true }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1" @@ -7291,14 +7290,12 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -7307,7 +7304,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -7318,7 +7314,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -7328,14 +7323,20 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "0.5.1" + } }, "write-file-atomic": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "imurmurhash": "0.1.4", @@ -7346,7 +7347,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, "requires": { "async-limiter": "1.0.0", "safe-buffer": "5.1.1", @@ -7357,7 +7357,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.1.tgz", "integrity": "sha512-pAIU5vBr9Hiy5cpFIbPnwf0C18ZF86DBsZKrlsf87N5De/JbA6RJ83UP/cv+aljl4S40iRVMqP4pr4sF9Dnj0A==", - "dev": true, "requires": { "global": "4.3.2", "is-function": "1.0.1", @@ -7369,7 +7368,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "dev": true, "requires": { "buffer-to-arraybuffer": "0.0.5", "object-assign": "4.1.1", @@ -7384,7 +7382,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", - "dev": true, "requires": { "xhr-request": "1.1.0" } @@ -7392,38 +7389,37 @@ "xhr2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", - "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=", - "dev": true + "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" }, "xmlhttprequest": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", - "dev": true + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", - "dev": true, "requires": { "cliui": "4.0.0", "decamelize": "1.2.0", @@ -7443,7 +7439,6 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, "requires": { "camelcase": "4.1.0" } @@ -7452,7 +7447,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.0.5.tgz", "integrity": "sha512-6/W7/B54OPHJXob0n0+pmkwFsirC8cokuQkPSmT/D0lCcSxkKtg/BA6ZnjUBIwjuGqmw3DTrT4en++htaUju5g==", - "dev": true, "requires": { "chalk": "2.3.2", "debug": "3.1.0", @@ -7473,7 +7467,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -7482,7 +7475,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, "requires": { "ansi-escapes": "3.0.0", "chalk": "2.3.2", @@ -7506,7 +7498,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.3.tgz", "integrity": "sha512-mODmrZ26a94djmGZZuIiomSGlN4wULdou29ZwcySupb2e9FdvoCl7Ps2FqHFjEHio3kOl/iBeaNqrnx3C3NwWg==", - "dev": true, "requires": { "async": "2.6.0", "chalk": "2.3.2", @@ -7539,7 +7530,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, "requires": { "lodash": "4.17.5" } @@ -7548,7 +7538,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, "requires": { "lru-cache": "4.1.2", "shebang-command": "1.2.0", @@ -7559,7 +7548,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -7567,14 +7555,12 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "7.1.2" } diff --git a/package.json b/package.json index d6640da..ff0734c 100644 --- a/package.json +++ b/package.json @@ -8,20 +8,19 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", + "crypto-js": "^3.1.9-1", + "elliptic": "^6.4.0", + "ethereumjs-util": "^5.2.0", + "ethjs-util": "^0.1.6", + "rlp": "^2.0.0", "solc": "^0.4.23", "solhint": "^1.1.10", - "solidity-coverage": "^0.5.0 " + "solidity-coverage": "^0.5.0 ", + "web3": "github:ethereum/web3.js", + "web3-eth": "^1.0.0-beta.34", + "web3-eth-accounts": "^1.0.0-beta.34" }, "devDependencies": { - "babel-cli": "^6.26.0", - "babel-polyfill": "^6.26.0", - "babel-preset-env": "^1.6.1", - "babel-preset-es2015": "^6.24.1", - "babel-register": "^6.26.0", - "bluebird": "^3.5.1", - "chai": "^4.1.2", - "chai-as-promised": "^7.1.1", - "chai-bignumber": "^2.0.2", "ganache-cli": "^6.0.0", "json-bigint-string": "^1.0.0", "solidity-coverage": "^0.4.0", @@ -30,14 +29,10 @@ "web3-utils": "^1.0.0-beta.33" }, "scripts": { - "testrpc": "ganache-cli --gasLimit 0xFFFFFFF --gasPrice 0 --network-id 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", - "testrpca": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", - "testrpcb": "ganache-cli --port 8546 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 5678 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", "deploy": "truffle deploy", - "deploya": "truffle deploy --network testrpca", - "deployb": "truffle deploy --network testrpcb", - "test": "truffle test", + "test": "truffle test --network development", "coverage": "solidity-coverage", "lint": "solhint contracts/**/*.sol" } diff --git a/poa-network/accounts.txt b/poa-network/accounts.txt new file mode 100644 index 0000000..f349749 --- /dev/null +++ b/poa-network/accounts.txt @@ -0,0 +1,2 @@ +2be5ab0e43b6dc2908d5321cf318f35b80d0c10d +8671e5e08d74f338ee1c462340842346d797afd3 diff --git a/poa-network/boot.key b/poa-network/boot.key new file mode 100644 index 0000000..d94de32 --- /dev/null +++ b/poa-network/boot.key @@ -0,0 +1 @@ +8f7dc7dc11a16dcdbbe201b224116c69b00fe547f3b7cb728492994f7d871dcf \ No newline at end of file diff --git a/poa-network/genesis.json b/poa-network/genesis.json new file mode 100644 index 0000000..8dd1dbb --- /dev/null +++ b/poa-network/genesis.json @@ -0,0 +1,33 @@ +{ + "config": { + "chainId": 1515, + "homesteadBlock": 1, + "eip150Block": 2, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 3, + "eip158Block": 3, + "byzantiumBlock": 4, + "clique": { + "period": 1, + "epoch": 30000 + } + }, + "nonce": "0x0", + "timestamp": "0x5b165989", + "extraData": "0x00000000000000000000000000000000000000000000000000000000000000002be5ab0e43b6dc2908d5321cf318f35b80d0c10d8671e5e08d74f338ee1c462340842346d797afd30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0xFFFFFF", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "2be5ab0e43b6dc2908d5321cf318f35b80d0c10d": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "8671e5e08d74f338ee1c462340842346d797afd3": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d new file mode 100644 index 0000000..0d2f3cc --- /dev/null +++ b/poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d @@ -0,0 +1 @@ +{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3} \ No newline at end of file diff --git a/poa-network/node1/password.txt b/poa-network/node1/password.txt new file mode 100644 index 0000000..4b93364 --- /dev/null +++ b/poa-network/node1/password.txt @@ -0,0 +1 @@ +password1 diff --git a/poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 b/poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 new file mode 100644 index 0000000..a3b0cbe --- /dev/null +++ b/poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 @@ -0,0 +1 @@ +{"address":"8671e5e08d74f338ee1c462340842346d797afd3","crypto":{"cipher":"aes-128-ctr","ciphertext":"8e132192c0603d01c60ae60c806903d2c2efe7475ba4269620b45203070c8d20","cipherparams":{"iv":"2711ec3033e13c5510dee3b202006307"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"26129bdcf528ce669072b8881a665037388b438495523bc3c29e0b48824fa078"},"mac":"1803bdb38057ecf32870a014307ea380156755f5aa2736ca92fbac7a24c80266"},"id":"a26c0645-090f-440a-9e2b-31f65d0720b2","version":3} \ No newline at end of file diff --git a/poa-network/node2/password.txt b/poa-network/node2/password.txt new file mode 100644 index 0000000..1a4ccc7 --- /dev/null +++ b/poa-network/node2/password.txt @@ -0,0 +1 @@ +password2 diff --git a/test/signature.js b/test/signature.js new file mode 100644 index 0000000..fc46b3c --- /dev/null +++ b/test/signature.js @@ -0,0 +1,286 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Web3 = require('web3'); +const Web3Utils = require('web3-utils'); +const Web3Abi = require('web3-eth-abi'); +const Web3Accounts = require('web3-eth-accounts'); +const rlp = require('rlp'); + +const Recover = artifacts.require("Recover"); + + +const web3 = new Web3(); + +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); + +function hexToBytes(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + +function bytesToHex(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(""); +} + +contract('signatures.js', (accounts) => { + const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join('') + + it('Test: VerifyBlockHash()', async () => { + const recover = await Recover.new(); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraData, + mixHash, + nonce + ]; + + const encodedHeader = rlp.encode(header); + + const headerHash = Web3Utils.sha3(encodedHeader); + assert.equal(block.hash, headerHash); + }) + + it('Test: VerifySignedHash()', async () => { + const recover = await Recover.new(); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Remove last 65 Bytes of extraData + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + const encodedHeader = rlp.encode(header); + + const headerHash = Web3Utils.sha3(encodedHeader); + + const ecrecoveryReceipt = await recover.VerifyHash(headerHash, extraDataSignature); + const ecrecoveryExpected = ecrecoveryReceipt.logs[0].args['owner']; + assert.equal(ecrecoveryExpected, signer); + }) + + it('Test: VerifyBlock()', async () => { + const recover = await Recover.new(); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Remove last 65 Bytes of extraData + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const headerHash = Web3Utils.sha3(encodedHeader); + + const ecrecoveryReceipt = await recover.VerifyBlock(encodedHeader, extraDataSignature); + const recoveredParentHash = ecrecoveryReceipt.logs[0].args['parentHash'] + const recoveredRootHash = ecrecoveryReceipt.logs[0].args['rootHash'] + const ecrecoveryExpected = ecrecoveryReceipt.logs[1].args['owner']; + assert.equal(recoveredParentHash, parentHash); + assert.equal(recoveredRootHash, root); + assert.equal(ecrecoveryExpected, signer); + }) + + it('Test: ExtractSignature()', async () => { + const recover = await Recover.new(); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Remove last 65 Bytes of extraData + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + const blockHeader = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraData, + mixHash, + nonce + ]; + + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + const encodedBlockHeader = '0x' + rlp.encode(blockHeader).toString('hex'); + const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + assert.equal(block.hash, blockHeaderHash); + + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const headerHash = Web3Utils.sha3(encodedHeader); + + // The new prefixes should be calculated off chain + const prefixHeader = '0x0214'; + const prefixExtraData = '0xa0'; + + const ecrecoveryReceipt = await recover.ExtractHash(encodedBlockHeader, prefixHeader, prefixExtraData); + const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; + const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; + assert.equal(block.hash, recoveredBlockHash) + assert.equal(recoveredSignature, signer); + }) +}); diff --git a/test/validation.js b/test/validation.js new file mode 100644 index 0000000..f6074fa --- /dev/null +++ b/test/validation.js @@ -0,0 +1,455 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Util = require('ethereumjs-util'); +const Web3 = require('web3'); +const Web3Utils = require('web3-utils'); +const Web3Abi = require('web3-eth-abi'); +const Web3Accounts = require('web3-eth-accounts'); +const rlp = require('rlp'); + +const Validation = artifacts.require("Validation"); +const Recover = artifacts.require("Recover"); + +const web3 = new Web3(); + +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); + +function hexToBytes(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + +function bytesToHex(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(""); +} + +contract('validation.js', (accounts) => { + const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); + + const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); + + const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; + + it('Test: GetValidators()', async () => { + const validation = await Validation.new(validators); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + const validatorsReceipt = await validation.GetValidators(); + assert.equal(validators[0], validatorsReceipt[0]) + }) + + it('Test: Authentic Submission - ValidateBlock()', async () => { + const validation = await Validation.new(validators); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Remove last 65 Bytes of extraData + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + const blockHeader = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraData, + mixHash, + nonce + ]; + + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + const encodedBlockHeader = '0x' + rlp.encode(blockHeader).toString('hex'); + const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + assert.equal(block.hash, blockHeaderHash); + + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const headerHash = Web3Utils.sha3(encodedHeader); + + // The new prefixes should be calculated off chain + const prefixHeader = '0x0214'; + const prefixExtraData = '0xa0'; + + const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); + const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; + const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; + assert.equal(block.hash, recoveredBlockHash) + assert.equal(recoveredSignature, signer); + + }) + + it('Test: Authentic Submission Off-Chain - ValidateBlock()', async () => { + const validation = await Validation.new(validators); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Create new signed hash + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + // Make some changes to the block + const newTxHash = Web3Utils.sha3("Test Data"); + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + // Encode and sign the new header + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const headerHash = Util.sha3(encodedHeader); + + const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + + const sig = Util.ecsign(headerHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = Util.pubToAddress(pubKey); + const addr = Util.bufferToHex(addrBuf); + + const vPseudo = new Buffer(0); + const newSigBytes = Buffer.concat([sig.r, sig.s]); + const newSig = newSigBytes.toString('hex') + '00'; + + // Append signature to the end of extraData + const sigBytes = hexToBytes(newSig.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + bytesToHex(newExtraDataBytes); + + const newBlockHeader = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + newExtraData, + mixHash, + nonce + ]; + + const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); + const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + assert.equal(block.hash, blockHeaderHash); + + // The new prefixes should be calculated off chain + const prefixHeader = '0x0214'; + const prefixExtraData = '0xa0'; + + const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); + const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; + const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; + assert.equal(block.hash, recoveredBlockHash) + assert.equal(recoveredSignature, signer); + }) + + it('Test: Inauthentic Block Submission Off-Chain - ValidateBlock()', async () => { + const validation = await Validation.new(validators); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Create new signed hash + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + // Make some changes to the block + const newTxHash = Web3Utils.sha3("Test Data"); + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + newTxHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + // Encode and sign the new header + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const headerHash = Util.sha3(encodedHeader); + + const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + + const sig = Util.ecsign(headerHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = Util.pubToAddress(pubKey); + const addr = Util.bufferToHex(addrBuf); + + const vPseudo = new Buffer(0); + const newSigBytes = Buffer.concat([sig.r, sig.s]); + const newSig = newSigBytes.toString('hex') + '00'; + + // Append signature to the end of extraData + const sigBytes = hexToBytes(newSig.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + bytesToHex(newExtraDataBytes); + + const newBlockHeader = [ + parentHash, + sha3Uncles, + coinbase, + root, + newTxHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + newExtraData, + mixHash, + nonce + ]; + + const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); + const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + + // The new prefixes should be calculated off chain + const prefixHeader = '0x0214'; + const prefixExtraData = '0xa0'; + + const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); + const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; + const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; + assert.equal(recoveredSignature, signer); + }) + + it('Test: Authentic Block Unkown Validator Submission - ValidateBlock()', async () => { + const validation = await Validation.new(validators); + const accounts = web3.eth.accounts; + const signer = accounts[0]; + + // Get a single block + const block = web3.eth.getBlock(10); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Create new signed hash + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + // Make some changes to the block + const newTxHash = Web3Utils.sha3("Test Data"); + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + newTxHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + // Encode and sign the new header + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const headerHash = Util.sha3(encodedHeader); + + const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') + + const sig = Util.ecsign(headerHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = Util.pubToAddress(pubKey); + const addr = Util.bufferToHex(addrBuf); + + const vPseudo = new Buffer(0); + const newSigBytes = Buffer.concat([sig.r, sig.s]); + const newSig = newSigBytes.toString('hex') + '00'; + + // Append signature to the end of extraData + const sigBytes = hexToBytes(newSig.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + bytesToHex(newExtraDataBytes); + + const newBlockHeader = [ + parentHash, + sha3Uncles, + coinbase, + root, + newTxHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + newExtraData, + mixHash, + nonce + ]; + + const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); + const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + + // The new prefixes should be calculated off chain + const prefixHeader = '0x0214'; + const prefixExtraData = '0xa0'; + + try { + const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); + } catch (err) { + assert.isDefined(err, "transaction should have thrown"); + } + }) + +}); diff --git a/truffle.js b/truffle.js index 2566b29..264bfe3 100644 --- a/truffle.js +++ b/truffle.js @@ -2,30 +2,9 @@ module.exports = { networks: { development: { host: "localhost", - port: 8545, - network_id: "*" // Match any network id - }, - ci: { - host: "localhost", - port: 8545, - network_id: "*" // Match any network id - }, - coverage: { - host: "localhost", - port: 8555, - network_id: "*", // Match any network id - gas: 0xFFFFFFF, - gasprice: 0x1 - }, - testrpca: { - host: "localhost", - port: 8545, - network_id: "*" // Match any network id - }, - testrpcb: { - host: "localhost", - port: 8546, - network_id: "*" // Match any network id + port: 8501, + network_id: "*", + gas: 4600000 } }, mocha: { From 8de861deef052e6eddfef6a35672e16254a12781 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 25 Jun 2018 11:52:49 +0100 Subject: [PATCH 006/203] Improved the readme --- README.md | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/README.md b/README.md index df897b3..a9904c8 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,126 @@ The Ion Interoperability Protocol provides mechanisms to perform atomic swaps and currency transfers across multiple turing-complete blockchains. + +## Block Validation Scheme +Block validation scheme is a set of smart contract which aim to be able to ensure that block headers submitted to the contract are sealed by an approved partie(s). The motivation behind this is to update the state of a Clique PoA or Istanbul PBFT chain onto any other blockchain. To do this we first need to know which blocks are valid - dependent on the definition of a valid by the underlying consensus algorithm. + +At this stage a Clique PoA chain is launched and then the block headers updated to the smart contract which is deployed on itself. However in the near future this will be extended to update the Clique header onto any other chain. For a full description and roadmap of the project please refer to the Clearmatics [Ion-Stage-2 Wiki](https://github.com/clearmatics/ion/wiki/Ion-Stage-2---Proposal#validation). + +## Running the Project +This project contains a number of components: + * Validation smart contract and tests + * Clique _proof of authority_ test network + * Command Line Interface for interacting with the smart contract + +In order to use the smart contracts and run the tests it is necessary to first initialise the test network. + +***Note:*** that as the contract searches for specific parts of the block header that only exist in Clique, Ganache or Ethash chains cannot be used. + +### Initialise the Test Network +The instructions are based on the tutorial of [Salanfe](https://hackernoon.com/setup-your-own-private-proof-of-authority-ethereum-network-with-geth-9a0a3750cda8) but has the more complicated parts already initialised. + +First install an instance of [geth](https://geth.ethereum.org/downloads/) and clone the repo. + +Having cloned and entered the repo: +``` +$ git clone git@github.com:maxrobot/validation.git +$ cd /path/to/validation +``` + +Now run the command: +``` +$ tree -L 1 +``` + +Which hopefully returns this: +``` +├── abi +├── build +├── contracts +├── migrations +├── package.json +├── poa-network +├── README.md +├── src +├── test +└── truffle.js +``` + +#### Initialise Nodes +Network files are found in the `/path/to/validation/poa-network` directory. Enter the poa-network directory and initialise the two nodes which will be sealing blocks: +``` +$ cd /path/to/validation/poa-network +$ geth --datadir node1/ init genesis.json +$ geth --datadir node2/ init genesis.json +``` + +#### Launch the Bootnode +The boot node tells the peers how to connect with each other. In another terminal instance run: +``` +$ bootnode -nodekey boot.key -verbosity 9 -addr :30310 +$ INFO [06-07|12:16:21] UDP listener up self=enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@[::]:30310 +``` +As the peers communicate this terminal should fill with logs. + +***Note:*** bootnode may not be found if go-ethereum/geth is not installed fully. + +#### Start and Attach to the Nodes +Each node must be launched either as a background operation or on separate terminal instances. Thus from the poa-network directory for node 1 run: +``` +$ geth --datadir node1/ --syncmode 'full' --port 30311 --rpc --rpcaddr 'localhost' --rpcport 8501 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '1' -unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password node1/password.txt --mine +``` +then attach: +``` +$ geth attach node1/geth.ipc +``` + and again for node 2: +``` +$ geth --datadir node2/ --syncmode 'full' --port 30312 --rpc --rpcaddr 'localhost' --rpcport 8502 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '0' -unlock '0x8671e5e08d74f338ee1c462340842346d797afd3' --password node2/password.txt --mine +``` +attaching: +``` +$ geth attach node2/geth.ipc +``` +***Note:*** that IPC has been used to attach to the nodes, this allows the clique module to be used. + +### Testing Contracts +After launching the network, from the root of the repository: +``` +$ npm install +$ truffle test +``` + +### Ion Command Line Interface +The Ion CLI is a tool for handling the passing of block headers between to blockchains written in Golang to leverage the extensive ethereum libraries. It is not a critical part of the Ion infrastructure rather is just an open utility that people can extend and use as they see fit. + +In its current form the Ion CLI allows the user to connect to two separate blockchains, via RPC, and submit block headers to a validation contract. + +#### Running the CLI +As mentioned in the project description this simple implementation of the validation contract is active only on a single blockchain, however the CLI is simulating the passing of the headers to and from as if it were between separate chains. + +Having followed the instructions on how to setup a Clique blockchain, which is hosted on `127.0.0.1:8502`, and running another chain on `127.0.0.1:8501` we can attach the CLI. + +``` +$ cd /path/to/validation/src +$ make build +``` +Assuming a successful build the tool can be run, +``` +$ ./ion-cli [/path/to/setup.json] +=============================================================== +Ion Command Line Interface + +RPC Client [to]: +Listening on: 127.0.0.1:8501 +User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d +Ion Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f + +RPC Client [from]: +Listening on: 127.0.0.1:8502 +User Account: 0x8671e5e08d74f338ee1c462340842346d797afd3 +=============================================================== +>>> +``` + + From 07625ecd94c1bcc6c097b90290738556dbcc88c0 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Jun 2018 12:59:22 +0100 Subject: [PATCH 007/203] Use relative import paths instead of absolute, ignore resulting binary --- ion-cli/.gitignore | 1 + ion-cli/cli/cli.go | 4 ++-- ion-cli/cli/cli_test.go | 2 +- ion-cli/config/config_test.go | 2 +- ion-cli/main.go | 4 ++-- 5 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 ion-cli/.gitignore diff --git a/ion-cli/.gitignore b/ion-cli/.gitignore new file mode 100644 index 0000000..8d335a8 --- /dev/null +++ b/ion-cli/.gitignore @@ -0,0 +1 @@ +ion-cli diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 5fc704b..5f4897c 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -12,8 +12,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ion/ion-cli/Validation" - "github.com/ion/ion-cli/config" + "../Validation" + "../config" ) // Launch - definition of commands and creates the iterface diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index 3485c9d..70e50b1 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ion/ion-cli/config" + "../config" ) func Test_Read_ValidSetupJson(t *testing.T) { diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 2e620fc..2dfad76 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ion/ion-cli/config" + "./config" ) func Test_Read_ValidSetupJson(t *testing.T) { diff --git a/ion-cli/main.go b/ion-cli/main.go index 8c29cf6..fbb7c4e 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -7,8 +7,8 @@ import ( "fmt" "os" - "github.com/ion/ion-cli/cli" - "github.com/ion/ion-cli/config" + "./cli" + "./config" ) var configFile = flag.String("config", "setup.json", "Description:\n path to the configuration file") From 561d886da309d196775e77a1332040682f0af05e Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 25 Jun 2018 14:47:38 +0100 Subject: [PATCH 008/203] Added a little test for the keystore --- ion-cli/cli/cli.go | 25 +++++++++++++++++++++++-- ion-cli/cli/cli_test.go | 2 +- ion-cli/config/config.go | 32 ++++++++++++++++++++++++-------- ion-cli/config/config_test.go | 12 +++++++++++- ion-cli/main.go | 2 +- ion-cli/setup.json | 4 +++- 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 5fc704b..12bd06e 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -3,9 +3,12 @@ package cli import ( + "context" "fmt" "log" + "math/big" "strconv" + "strings" "github.com/abiosoft/ishell" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -16,6 +19,8 @@ import ( "github.com/ion/ion-cli/config" ) +const key = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` + // Launch - definition of commands and creates the iterface func Launch(setup config.Setup) { // by default, new shell includes 'exit', 'help' and 'clear' commands. @@ -34,6 +39,22 @@ func Launch(setup config.Setup) { log.Fatal(err) } + // Get a suggested gas price + gasPrice, err := client.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatal(err) + } + + // Create an authorized transactor and spend 1 unicorn + keyTo := config.ReadString(setup.KeystoreTo) + auth, err := bind.NewTransactor(strings.NewReader(keyTo), "password1") + if err != nil { + log.Fatalf("Failed to create authorized transactor: %v", err) + } + auth.Value = big.NewInt(0) // in wei + auth.GasLimit = uint64(300000) // in units + auth.GasPrice = gasPrice + printInfo(setup) // Get the latest block number @@ -112,12 +133,12 @@ func Launch(setup config.Setup) { } else { c.Println("RLP encode block: " + c.Args[0]) encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) - res, err := validation.ValidateBlock(&bind.TransactOpts{}, encodedBlock, prefixBlock, prefixExtra) + res, err := validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) if err != nil { c.Printf("Error: %s", err) return } - c.Printf("Error: %s", res) + c.Printf("Transaction Hash: 0x%x\n", res.Hash()) } c.Println("===============================================================") }, diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index 3485c9d..9d81dff 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -14,7 +14,7 @@ import ( func Test_Read_ValidSetupJson(t *testing.T) { path := findPath() + "../setup.json" - setup := config.Read(path) + setup := config.ReadSetup(path) assert.Equal(t, "8501", setup.PortTo) assert.Equal(t, "127.0.0.1", setup.AddrTo) diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 5c777af..52c7587 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -10,16 +10,19 @@ import ( // Settings type Setup struct { - PortTo string `json:"rpc-port-to"` - AddrTo string `json:"rpc-addr-to"` - AccountTo string `json:"account-to"` - PortFrom string `json:"rpc-port-from"` - AddrFrom string `json:"rpc-addr-from"` - AccountFrom string `json:"account-from"` - Ion string `json:"ion-addr"` + PortTo string `json:"rpc-port-to"` + AddrTo string `json:"rpc-addr-to"` + AccountTo string `json:"account-to"` + KeystoreTo string `json:"keystore-to"` + PortFrom string `json:"rpc-port-from"` + AddrFrom string `json:"rpc-addr-from"` + AccountFrom string `json:"account-from"` + KeystoreFrom string `json:"keystore-from"` + Ion string `json:"ion-addr"` } -func Read(config string) (setup Setup) { +// Takes path to a JSON and returns a struct of the contents +func ReadSetup(config string) (setup Setup) { raw, err := ioutil.ReadFile(config) if err != nil { fmt.Print(err, "\n") @@ -29,3 +32,16 @@ func Read(config string) (setup Setup) { return setup } + +// Takes path to a JSON and returns a string of the contents +func ReadString(path string) (contents string) { + raw, err := ioutil.ReadFile(path) + if err != nil { + fmt.Print(err, "\n") + } + + contents = string(raw) + + return + +} diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 2e620fc..2d00728 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -14,7 +14,7 @@ import ( func Test_Read_ValidSetupJson(t *testing.T) { path := findPath() + "../setup.json" - setup := config.Read(path) + setup := config.ReadSetup(path) assert.Equal(t, "8501", setup.PortTo) assert.Equal(t, "127.0.0.1", setup.AddrTo) @@ -23,6 +23,16 @@ func Test_Read_ValidSetupJson(t *testing.T) { assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) } +func Test_Read_ValidKeystore(t *testing.T) { + path := findPath() + "../../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + contents := config.ReadString(path) + + const val = "{\"address\":\"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa\",\"cipherparams\":{\"iv\":\"4aa66b789ee2d98cf77272a72eeeaa50\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e\"},\"mac\":\"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3\"},\"id\":\"a3cc1eae-3e36-4659-b759-6cf416216e72\",\"version\":3}" + + assert.Equal(t, val, contents) + +} + func findPath() string { _, path, _, _ := runtime.Caller(0) pathSlice := strings.Split(path, "/") diff --git a/ion-cli/main.go b/ion-cli/main.go index 8c29cf6..ffec2ab 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -17,7 +17,7 @@ func main() { flag.Parse() if *configFile != "" { - setup := config.Read(*configFile) + setup := config.ReadSetup(*configFile) // Launch the CLI cli.Launch(setup) diff --git a/ion-cli/setup.json b/ion-cli/setup.json index 9ab7dff..0c55e28 100644 --- a/ion-cli/setup.json +++ b/ion-cli/setup.json @@ -2,8 +2,10 @@ "rpc-addr-to":"127.0.0.1", "rpc-port-to":"8501", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", "rpc-addr-from":"127.0.0.1", "rpc-port-from":"8502", "account-from":"0x8671e5e08d74f338ee1c462340842346d797afd3", - "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f" + "keystore-from":"../poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3" } From 6b95f418db7a4c67b65abbffdf5763a972576027 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 25 Jun 2018 16:44:10 +0100 Subject: [PATCH 009/203] Given up on the vendoring lets focus on the stuff we like ie the contract --- ion-cli/cli/cli.go | 8 +++----- ion-cli/cli/cli_test.go | 2 +- ion-cli/cli/rpc.go | 6 +++--- ion-cli/config/config_test.go | 2 +- ion-cli/main.go | 4 ++-- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index a09cb88..93066ec 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -15,12 +15,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "../Validation" - "../config" + "github.com/ion/ion-cli/Validation" + "github.com/ion/ion-cli/config" ) -const key = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` - // Launch - definition of commands and creates the iterface func Launch(setup config.Setup) { // by default, new shell includes 'exit', 'help' and 'clear' commands. @@ -138,7 +136,7 @@ func Launch(setup config.Setup) { c.Printf("Error: %s", err) return } - c.Printf("Transaction Hash: 0x%x\n", res.Hash()) + c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) } c.Println("===============================================================") }, diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index e4c4cbe..9d81dff 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "../config" + "github.com/ion/ion-cli/config" ) func Test_Read_ValidSetupJson(t *testing.T) { diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 9a16103..583f430 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -120,20 +120,20 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by // Generate an interface to encode the standard block header blockInterface := GenerateInterface(blockHeader) encodedBlock := EncodeBlock(blockInterface) - fmt.Printf("\n%+x\n", encodedBlock) + fmt.Printf("\nEncoded Block Header:\n%+x\n", encodedBlock) // Generate an interface to encode the blockheader without the signature in the extraData blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] blockInterface = GenerateInterface(blockHeader) encodedBlock = EncodeBlock(blockInterface) prefixBlock = encodedBlock[1:3] - fmt.Printf("\n%+x\n", prefixBlock) + fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", prefixBlock) // Generate an interface to encode the blockheader without the signature in the extraData encExtra, _ := hex.DecodeString(blockHeader.Extra[2:]) encodedBlock = EncodeBlock(encExtra) prefixExtra = encodedBlock[0:1] - fmt.Printf("\n%+x\n", prefixExtra) + fmt.Printf("\nExtraData Field Prefix:\n%+x\n", prefixExtra) return encodedBlock, prefixBlock, prefixExtra diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 08cf665..aa94156 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "./config" + "github.com/ion/ion-config/config" ) func Test_Read_ValidSetupJson(t *testing.T) { diff --git a/ion-cli/main.go b/ion-cli/main.go index fb8bb13..ffec2ab 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -7,8 +7,8 @@ import ( "fmt" "os" - "./cli" - "./config" + "github.com/ion/ion-cli/cli" + "github.com/ion/ion-cli/config" ) var configFile = flag.String("config", "setup.json", "Description:\n path to the configuration file") From 326a1ceac3768429d9301765e911315258e99395 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 26 Jun 2018 09:22:41 +0100 Subject: [PATCH 010/203] Fixed some signature stuff in the javascript which was implemented naively and debugging the golang submission of blocks --- contracts/Validation.sol | 32 ++++++++++--- ion-cli/Validation/Validation.go | 81 ++++++++++++++++++++++++++++++-- ion-cli/cli/cli.go | 54 ++++++++++++++++++++- ion-cli/cli/rpc.go | 1 + migrations/2_deploy_contracts.js | 2 +- package.json | 5 +- test/validation.js | 29 +++++++----- 7 files changed, 178 insertions(+), 26 deletions(-) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 083c4d8..04d97e8 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -5,30 +5,33 @@ pragma solidity ^0.4.23; import "./ECVerify.sol"; contract Validation { - address Owner; - event broadcastSig(address owner); event broadcastHashData(bytes header, bytes parentHash, bytes rootHash); event broadcastHash(bytes32 blockHash); + address Owner; address[] validators; + bytes32 prevBlockHash; + struct BlockHeader { bytes32 prevBlockHash; } mapping (bytes32 => BlockHeader) public m_blockheaders; - mapping( address => bool ) m_validators; + mapping(address => bool) m_validators; /* * @param _validators list of validators at block 0 */ - constructor (address[] _validators) public { + constructor (address[] _validators, bytes32 genHash) public { Owner = msg.sender; for (uint i = 0; i < _validators.length; i++) { validators.push(_validators[i]); m_validators[_validators[i]] = true; - } + } + + prevBlockHash = genHash; } /* @@ -37,6 +40,13 @@ contract Validation { function GetValidators() public view returns (address[] _validators) { return validators; } + + /* + * Returns the latest block submitted + */ + function LatestBlock() public view returns (bytes32 _latestBlock) { + return prevBlockHash; + } /* * @param header header rlp encoded, with extraData signatures removed @@ -76,12 +86,22 @@ contract Validation { extractData(extraDataSig, header, length-107, extraDataSig.length); address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); - require(m_validators[sig_addr]==true, "Signer not a validator!"); + // require(m_validators[sig_addr]==true, "Signer not a validator!"); + + prevBlockHash = blockHash; emit broadcastSig(sig_addr); } + function ValidationTest(bytes header) public { + bytes32 blockHash = keccak256(header); + + emit broadcastHash(blockHash); + + prevBlockHash = blockHash; + } + function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { // Get the lengths sorted because they're needed later... uint256 headerStartLength = headerStart.length; diff --git a/ion-cli/Validation/Validation.go b/ion-cli/Validation/Validation.go index 18e9228..919b2b9 100644 --- a/ion-cli/Validation/Validation.go +++ b/ion-cli/Validation/Validation.go @@ -15,18 +15,18 @@ import ( ) // ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" +const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidationTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. -const ValidationBin = `608060405234801561001057600080fd5b506040516109d73803806109d7833981018060405281019080805182019291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b815181101561017c576001828281518110151561009357fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160026000848481518110151561011457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550808060010191505061007a565b505061084a8061018d6000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063aae933e414610051578063d405af3d14610146575b600080fd5b34801561005d57600080fd5b50610144600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101b2565b005b34801561015257600080fd5b5061015b610561565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019e578082015181840152602081019050610183565b505050509050019250505060405180910390f35b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156101fa57805182526020820191506020810190506020830392506101d5565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561029e5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156102d55781602001602082028038833980820191505090505b50955060416040519080825280601f01601f19166020018201604052801561030c5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156103435781602001602082028038833980820191505090505b509350610354878d60008a516105ef565b600260218801600260208e016004610bb8fa50610377868d608c8c0389516105ef565b600160208701600160208d016004610bb8fa5061039a848d602a8c0387516105ef565b6103a58787866106aa565b9250826040518082805190602001908083835b6020831015156103dd57805182526020820191506020810190506020830392506103b8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020915061041c858d606b8c0388516105ef565b6104268286610756565b905060011515600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151415156104f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156105e557602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161059b575b5050505050905090565b60008090505b818110156106a3578381840181518110151561060d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561066657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506105f5565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156107115781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561076c57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561079757601b810190505b601b8160ff1614806107ac5750601c8160ff16145b15156107b757600080fd5b6107c3868285856107ce565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561081157600080fd5b80925050509493505050505600a165627a7a72305820bfdda3defd1a9101b13153fe900905c379572f205ad37b4197c70cdd78be35e20029` +const ValidationBin = `608060405234801561001057600080fd5b506040516109f13803806109f183398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160046000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816002816000191690555050505061084b806101a66000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063927a32e3146100675780639db7d9f7146100b4578063aae933e4146100e7578063d405af3d146101dc575b600080fd5b34801561007357600080fd5b506100966004803603810190808035600019169060200190929190505050610248565b60405180826000191660001916815260200191505060405180910390f35b3480156100c057600080fd5b506100c9610266565b60405180826000191660001916815260200191505060405180910390f35b3480156100f357600080fd5b506101da600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610270565b005b3480156101e857600080fd5b506101f1610562565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610234578082015181840152602081019050610219565b505050509050019250505060405180910390f35b60036020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156102b85780518252602082019150602081019050602083039250610293565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561035c5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156103935781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156103ca5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156104015781602001602082028038833980820191505090505b509350610412878d60008a516105f0565b600260218801600260208e016004610bb8fa50610435868d608c8c0389516105f0565b600160208701600160208d016004610bb8fa50610458848d602a8c0387516105f0565b6104638787866106ab565b9250826040518082805190602001908083835b60208310151561049b5780518252602082019150602081019050602083039250610476565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506104da858d606b8c0388516105f0565b6104e48286610757565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156105e657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161059c575b5050505050905090565b60008090505b818110156106a4578381840181518110151561060e57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561066757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506105f6565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156107125781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561076d57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561079857601b810190505b601b8160ff1614806107ad5750601c8160ff16145b15156107b857600080fd5b6107c4868285856107cf565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561081257600080fd5b80925050509493505050505600a165627a7a72305820d1ebc40c25f798a40ded32bb082078c894c9d241047b7bb053d9dd09b79be9820029` // DeployValidation deploys a new Ethereum contract, binding an instance of Validation to it. -func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address) (common.Address, *types.Transaction, *Validation, error) { +func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address, genHash [32]byte) (common.Address, *types.Transaction, *Validation, error) { parsed, err := abi.JSON(strings.NewReader(ValidationABI)) if err != nil { return common.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ValidationBin), backend, _validators) + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ValidationBin), backend, _validators, genHash) if err != nil { return common.Address{}, nil, nil, err } @@ -201,6 +201,58 @@ func (_Validation *ValidationCallerSession) GetValidators() ([]common.Address, e return _Validation.Contract.GetValidators(&_Validation.CallOpts) } +// LatestBlock is a free data retrieval call binding the contract method 0x9db7d9f7. +// +// Solidity: function LatestBlock() constant returns(_latestBlock bytes32) +func (_Validation *ValidationCaller) LatestBlock(opts *bind.CallOpts) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Validation.contract.Call(opts, out, "LatestBlock") + return *ret0, err +} + +// LatestBlock is a free data retrieval call binding the contract method 0x9db7d9f7. +// +// Solidity: function LatestBlock() constant returns(_latestBlock bytes32) +func (_Validation *ValidationSession) LatestBlock() ([32]byte, error) { + return _Validation.Contract.LatestBlock(&_Validation.CallOpts) +} + +// LatestBlock is a free data retrieval call binding the contract method 0x9db7d9f7. +// +// Solidity: function LatestBlock() constant returns(_latestBlock bytes32) +func (_Validation *ValidationCallerSession) LatestBlock() ([32]byte, error) { + return _Validation.Contract.LatestBlock(&_Validation.CallOpts) +} + +// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// +// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) +func (_Validation *ValidationCaller) MBlockheaders(opts *bind.CallOpts, arg0 [32]byte) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Validation.contract.Call(opts, out, "m_blockheaders", arg0) + return *ret0, err +} + +// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// +// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) +func (_Validation *ValidationSession) MBlockheaders(arg0 [32]byte) ([32]byte, error) { + return _Validation.Contract.MBlockheaders(&_Validation.CallOpts, arg0) +} + +// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// +// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) +func (_Validation *ValidationCallerSession) MBlockheaders(arg0 [32]byte) ([32]byte, error) { + return _Validation.Contract.MBlockheaders(&_Validation.CallOpts, arg0) +} + // ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. // // Solidity: function ValidateBlock(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() @@ -222,6 +274,27 @@ func (_Validation *ValidationTransactorSession) ValidateBlock(header []byte, pre return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) } +// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. +// +// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactor) ValidationTest(opts *bind.TransactOpts, header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.contract.Transact(opts, "ValidationTest", header, prefixHeader, prefixExtraData) +} + +// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. +// +// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +} + +// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. +// +// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactorSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +} + // ValidationBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Validation contract. type ValidationBroadcastHashIterator struct { Event *ValidationBroadcastHash // Event containing the contract specifics and raw log diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 93066ec..738bb17 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -86,7 +86,7 @@ func Launch(setup config.Setup) { shell.AddCmd(&ishell.Cmd{ Name: "getValidators", - Help: "Queries the validator contract for the whitelist of validators", + Help: "Queries the validator contract for the whitelist of validators, arguments: getValidatiors", Func: func(c *ishell.Context) { c.Println("===============================================================") result, err := validation.GetValidators(&bind.CallOpts{}) @@ -101,6 +101,23 @@ func Launch(setup config.Setup) { }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "latestBlockSubmitted", + Help: "Queries the validator contract for the last block submitted, arguments: latestBlockSubmitted", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + result, err := validation.LatestBlock(&bind.CallOpts{}) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + c.Println("Last Block Submitted:") + c.Printf("0x%x\n", result) + + c.Println("===============================================================") + }, + }) + // Get block N and spew out the RLP encoded block shell.AddCmd(&ishell.Cmd{ Name: "rlpBlock", @@ -125,12 +142,13 @@ func Launch(setup config.Setup) { Func: func(c *ishell.Context) { c.Println("===============================================================") if len(c.Args) == 0 { - c.Println("Choose a block.") + c.Println("Choose a block") } else if len(c.Args) > 1 { c.Println("Too many arguments entered.") } else { c.Println("RLP encode block: " + c.Args[0]) encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) + c.Printf("\nEncoded Block:\n0x%x\n", encodedBlock) res, err := validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) if err != nil { c.Printf("Error: %s", err) @@ -142,6 +160,38 @@ func Launch(setup config.Setup) { }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "validationTest", + Help: "Gets the latestBlockHash updates the latestBlockSubmitted, arguments: validationTest [integer]", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + if len(c.Args) == 0 { + c.Println("Choose a block") + } else if len(c.Args) > 1 { + c.Println("Too many arguments entered.") + } else { + c.Println("RLP encode block: " + c.Args[0]) + encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) + // bhash := "5cd9f5b157b070a77a9fa2928f5891c9d8ed88805480c9e2736ad749b2439428" + // arr, _ := hex.DecodeString(bhash) + // var test [32]byte + + // copy(test[:], arr) + + // c.Printf("%s\n", bhash) + // c.Printf("%+x\n", arr) + // c.Printf("%+x\n", test) + res, err := validation.ValidationTest(auth, encodedBlock) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) + } + c.Println("===============================================================") + }, + }) + // run shell shell.Run() } diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 583f430..69a77cb 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -113,6 +113,7 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by } err = json.Unmarshal([]byte(b), &blockHeader) if err != nil { + latestBlock(client) fmt.Printf("Error: %s", err) return } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index a3d8abd..e3e568b 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -5,7 +5,7 @@ module.exports = async (deployer) => { try { deployer.deploy(Recover) .then(() => Recover.deployed) - .then(() => deployer.deploy(Validation, ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"])) + .then(() => deployer.deploy(Validation, ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"], "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28")) .then(() => Validation.deployed) } catch(err) { console.log('ERROR on deploy:',err); diff --git a/package.json b/package.json index ff0734c..78b227e 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,9 @@ "deploy": "truffle deploy", "test": "truffle test --network development", "coverage": "solidity-coverage", - "lint": "solhint contracts/**/*.sol" + "lint": "solhint contracts/**/*.sol", + "genbin": "solc --overwrite --bin ./contracts/* -o abi", + "genabi": "solc --overwrite --abi ./contracts/* -o abi", + "abigen": "abigen --bin=abi/Validation.bin --abi=abi/Validation.abi --pkg=Validation --out=Validation.go" } } diff --git a/test/validation.js b/test/validation.js index f6074fa..89d49e7 100644 --- a/test/validation.js +++ b/test/validation.js @@ -29,15 +29,16 @@ function bytesToHex(bytes) { return hex.join(""); } -contract('validation.js', (accounts) => { +contract.only('validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; + const genHash = "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28"; it('Test: GetValidators()', async () => { - const validation = await Validation.new(validators); + const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; const signer = accounts[0]; @@ -45,8 +46,9 @@ contract('validation.js', (accounts) => { assert.equal(validators[0], validatorsReceipt[0]) }) - it('Test: Authentic Submission - ValidateBlock()', async () => { - const validation = await Validation.new(validators); + // This test takes a block and makes no changes to the block and submits it to the contract + it('Test: Authentic Submission Happy Path - ValidateBlock()', async () => { + const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; const signer = accounts[0]; @@ -131,8 +133,9 @@ contract('validation.js', (accounts) => { }) - it('Test: Authentic Submission Off-Chain - ValidateBlock()', async () => { - const validation = await Validation.new(validators); + // Here the block header is signed off chain but by a whitelisted validator + it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { + const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; const signer = accounts[0]; @@ -163,7 +166,6 @@ contract('validation.js', (accounts) => { const extraDataShort = '0x' + bytesToHex(extraBytesShort); // Make some changes to the block - const newTxHash = Web3Utils.sha3("Test Data"); const header = [ parentHash, sha3Uncles, @@ -195,11 +197,13 @@ contract('validation.js', (accounts) => { const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); const addrBuf = Util.pubToAddress(pubKey); - const addr = Util.bufferToHex(addrBuf); - const vPseudo = new Buffer(0); const newSigBytes = Buffer.concat([sig.r, sig.s]); - const newSig = newSigBytes.toString('hex') + '00'; + let newSig; + if (sig.v==28) + newSig = newSigBytes.toString('hex') + '00'; + else (sig.v==27) + newSig = newSigBytes.toString('hex') + '01'; // Append signature to the end of extraData const sigBytes = hexToBytes(newSig.toString('hex')); @@ -235,12 +239,13 @@ contract('validation.js', (accounts) => { const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; + console.log(block.hash, recoveredBlockHash) assert.equal(block.hash, recoveredBlockHash) assert.equal(recoveredSignature, signer); }) it('Test: Inauthentic Block Submission Off-Chain - ValidateBlock()', async () => { - const validation = await Validation.new(validators); + const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; const signer = accounts[0]; @@ -346,7 +351,7 @@ contract('validation.js', (accounts) => { }) it('Test: Authentic Block Unkown Validator Submission - ValidateBlock()', async () => { - const validation = await Validation.new(validators); + const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; const signer = accounts[0]; From 252e88ceab910bd52b258044635197e93c5d99e4 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 26 Jun 2018 11:42:39 +0100 Subject: [PATCH 011/203] So the contracts are working but the bytes added seem to give slightly different results, needs investigation but getting closer --- abi/ECVerify.abi | 1 - abi/ECVerify.bin | 1 - abi/Migrations.abi | 1 - abi/Migrations.bin | 1 - abi/Recover.abi | 1 - abi/Recover.bin | 1 - abi/Validation.abi | 1 - abi/Validation.bin | 1 - contracts/Validation.sol | 22 ++-- ion-cli/Validation/Validation.go | 52 ++++++--- ion-cli/cli/cli.go | 56 ++++++++-- ion-cli/cli/rpc.go | 14 +-- test/test.js | 184 +++++++++++++++++++++++++++++++ test/validation.js | 2 +- 14 files changed, 292 insertions(+), 46 deletions(-) delete mode 100644 abi/ECVerify.abi delete mode 100644 abi/ECVerify.bin delete mode 100644 abi/Migrations.abi delete mode 100644 abi/Migrations.bin delete mode 100644 abi/Recover.abi delete mode 100644 abi/Recover.bin delete mode 100644 abi/Validation.abi delete mode 100644 abi/Validation.bin create mode 100644 test/test.js diff --git a/abi/ECVerify.abi b/abi/ECVerify.abi deleted file mode 100644 index 0637a08..0000000 --- a/abi/ECVerify.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/abi/ECVerify.bin b/abi/ECVerify.bin deleted file mode 100644 index 56887c3..0000000 --- a/abi/ECVerify.bin +++ /dev/null @@ -1 +0,0 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820acb6e646edaf05c92bfe7c53e47edcf3f96a2d5cf3d55019662508f330c1d89f0029 \ No newline at end of file diff --git a/abi/Migrations.abi b/abi/Migrations.abi deleted file mode 100644 index 79cea67..0000000 --- a/abi/Migrations.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"new_address","type":"address"}],"name":"upgrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"last_completed_migration","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"completed","type":"uint256"}],"name":"setCompleted","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] \ No newline at end of file diff --git a/abi/Migrations.bin b/abi/Migrations.bin deleted file mode 100644 index 34c63b9..0000000 --- a/abi/Migrations.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f8806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100aa5780638da5cb5b146100d5578063fdacd5761461012c575b600080fd5b34801561007357600080fd5b506100a8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610159565b005b3480156100b657600080fd5b506100bf610241565b6040518082815260200191505060405180910390f35b3480156100e157600080fd5b506100ea610247565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561013857600080fd5b506101576004803603810190808035906020019092919050505061026c565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023d578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561022457600080fd5b505af1158015610238573d6000803e3d6000fd5b505050505b5050565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102c957806001819055505b505600a165627a7a7230582090db59736857b6a69a78d054d092a30ff8e90f10f6f3bca8afc3d994c885eedd0029 \ No newline at end of file diff --git a/abi/Recover.abi b/abi/Recover.abi deleted file mode 100644 index 49fac10..0000000 --- a/abi/Recover.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ExtractHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"sig","type":"bytes"}],"name":"VerifyBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"data","type":"bytes32"},{"name":"sig","type":"bytes"}],"name":"VerifyHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"}],"name":"test","type":"event"}] \ No newline at end of file diff --git a/abi/Recover.bin b/abi/Recover.bin deleted file mode 100644 index 183887f..0000000 --- a/abi/Recover.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b11806100606000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b0e7308f1461005c578063d09ca90414610151578063fdace1be14610200575b600080fd5b34801561006857600080fd5b5061014f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610277565b005b34801561015d57600080fd5b506101fe600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061055e565b005b34801561020c57600080fd5b506102756004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610840565b005b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156102bf578051825260208201915060208101905060208303925061029a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156103635781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f19166020018201604052801561039a5781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156103d15781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156104085781602001602082028038833980820191505090505b509350610419878d60008a516108b6565b600260218801600260208e016004610bb8fa5061043c868d608c8c0389516108b6565b600160208701600160208d016004610bb8fa5061045f848d602a8c0387516108b6565b61046a878786610971565b9250826040518082805190602001908083835b6020831015156104a2578051825260208201915060208101905060208303925061047d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506104e1858d606b8c0388516108b6565b6104eb8286610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b600080606080856040518082805190602001908083835b60208310151561059a5780518252602082019150602081019050602083039250610575565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093506105d38486610a1d565b925060206040519080825280601f01601f1916602001820160405280156106095781602001602082028038833980820191505090505b50915060206040519080825280601f01601f1916602001820160405280156106405781602001602082028038833980820191505090505b5090506106518287600460206108b6565b61065f8187605b60206108b6565b7f8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c786838360405180806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106cb5780820151818401526020810190506106b0565b50505050905090810190601f1680156106f85780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b83811015610731578082015181840152602081019050610716565b50505050905090810190601f16801561075e5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b8381101561079757808201518184015260208101905061077c565b50505050905090810190601f1680156107c45780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a17fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a583604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b600061084c8383610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b60008090505b8181101561096a57838184018151811015156108d457fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561092d57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506108bc565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109d85781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a3357600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a5e57601b810190505b601b8160ff161480610a735750601c8160ff16145b1515610a7e57600080fd5b610a8a86828585610a95565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610ad857600080fd5b80925050509493505050505600a165627a7a7230582084747b0b9ea8d1285e7c7714b82fb8ff314f3245d9b3e8132f7679cf08b7ca2b0029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi deleted file mode 100644 index 0388fd3..0000000 --- a/abi/Validation.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] diff --git a/abi/Validation.bin b/abi/Validation.bin deleted file mode 100644 index 3513650..0000000 --- a/abi/Validation.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b506040516109d73803806109d7833981018060405281019080805182019291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b815181101561017c576001828281518110151561009357fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160026000848481518110151561011457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550808060010191505061007a565b505061084a8061018d6000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063aae933e414610051578063d405af3d14610146575b600080fd5b34801561005d57600080fd5b50610144600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101b2565b005b34801561015257600080fd5b5061015b610561565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019e578082015181840152602081019050610183565b505050509050019250505060405180910390f35b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156101fa57805182526020820191506020810190506020830392506101d5565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561029e5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156102d55781602001602082028038833980820191505090505b50955060416040519080825280601f01601f19166020018201604052801561030c5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156103435781602001602082028038833980820191505090505b509350610354878d60008a516105ef565b600260218801600260208e016004610bb8fa50610377868d608c8c0389516105ef565b600160208701600160208d016004610bb8fa5061039a848d602a8c0387516105ef565b6103a58787866106aa565b9250826040518082805190602001908083835b6020831015156103dd57805182526020820191506020810190506020830392506103b8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020915061041c858d606b8c0388516105ef565b6104268286610756565b905060011515600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151415156104f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156105e557602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161059b575b5050505050905090565b60008090505b818110156106a3578381840181518110151561060d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561066657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506105f5565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156107115781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561076c57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561079757601b810190505b601b8160ff1614806107ac5750601c8160ff16145b15156107b757600080fd5b6107c3868285856107ce565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561081157600080fd5b80925050509493505050505600a165627a7a72305820bfdda3defd1a9101b13153fe900905c379572f205ad37b4197c70cdd78be35e20029 \ No newline at end of file diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 04d97e8..243f1b5 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -5,21 +5,22 @@ pragma solidity ^0.4.23; import "./ECVerify.sol"; contract Validation { - event broadcastSig(address owner); - event broadcastHashData(bytes header, bytes parentHash, bytes rootHash); - event broadcastHash(bytes32 blockHash); - address Owner; address[] validators; bytes32 prevBlockHash; + bytes someBytes; struct BlockHeader { bytes32 prevBlockHash; } mapping (bytes32 => BlockHeader) public m_blockheaders; - mapping(address => bool) m_validators; + mapping (address => bool) m_validators; + + event broadcastSig(address owner); + event broadcastHashData(bytes header, bytes parentHash, bytes rootHash); + event broadcastHash(bytes32 blockHash); /* * @param _validators list of validators at block 0 @@ -48,6 +49,13 @@ contract Validation { return prevBlockHash; } + /* + * Returns the latest block submitted + */ + function LatestBytes() public view returns (bytes _latestBytes) { + return someBytes; + } + /* * @param header header rlp encoded, with extraData signatures removed * @param prefixHeader the new prefix for the signed hash header @@ -96,9 +104,7 @@ contract Validation { function ValidationTest(bytes header) public { bytes32 blockHash = keccak256(header); - - emit broadcastHash(blockHash); - + someBytes = header; prevBlockHash = blockHash; } diff --git a/ion-cli/Validation/Validation.go b/ion-cli/Validation/Validation.go index 919b2b9..5812145 100644 --- a/ion-cli/Validation/Validation.go +++ b/ion-cli/Validation/Validation.go @@ -15,7 +15,7 @@ import ( ) // ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidationTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" +const ValidationABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"}],\"name\":\"ValidationTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBytes\",\"outputs\":[{\"name\":\"_latestBytes\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. const ValidationBin = `608060405234801561001057600080fd5b506040516109f13803806109f183398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160046000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816002816000191690555050505061084b806101a66000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063927a32e3146100675780639db7d9f7146100b4578063aae933e4146100e7578063d405af3d146101dc575b600080fd5b34801561007357600080fd5b506100966004803603810190808035600019169060200190929190505050610248565b60405180826000191660001916815260200191505060405180910390f35b3480156100c057600080fd5b506100c9610266565b60405180826000191660001916815260200191505060405180910390f35b3480156100f357600080fd5b506101da600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610270565b005b3480156101e857600080fd5b506101f1610562565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610234578082015181840152602081019050610219565b505050509050019250505060405180910390f35b60036020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156102b85780518252602082019150602081019050602083039250610293565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561035c5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156103935781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156103ca5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156104015781602001602082028038833980820191505090505b509350610412878d60008a516105f0565b600260218801600260208e016004610bb8fa50610435868d608c8c0389516105f0565b600160208701600160208d016004610bb8fa50610458848d602a8c0387516105f0565b6104638787866106ab565b9250826040518082805190602001908083835b60208310151561049b5780518252602082019150602081019050602083039250610476565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506104da858d606b8c0388516105f0565b6104e48286610757565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156105e657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161059c575b5050505050905090565b60008090505b818110156106a4578381840181518110151561060e57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561066757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506105f6565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156107125781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561076d57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561079857601b810190505b601b8160ff1614806107ad5750601c8160ff16145b15156107b857600080fd5b6107c4868285856107cf565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561081257600080fd5b80925050509493505050505600a165627a7a72305820d1ebc40c25f798a40ded32bb082078c894c9d241047b7bb053d9dd09b79be9820029` @@ -227,6 +227,32 @@ func (_Validation *ValidationCallerSession) LatestBlock() ([32]byte, error) { return _Validation.Contract.LatestBlock(&_Validation.CallOpts) } +// LatestBytes is a free data retrieval call binding the contract method 0x34174e6c. +// +// Solidity: function LatestBytes() constant returns(_latestBytes bytes) +func (_Validation *ValidationCaller) LatestBytes(opts *bind.CallOpts) ([]byte, error) { + var ( + ret0 = new([]byte) + ) + out := ret0 + err := _Validation.contract.Call(opts, out, "LatestBytes") + return *ret0, err +} + +// LatestBytes is a free data retrieval call binding the contract method 0x34174e6c. +// +// Solidity: function LatestBytes() constant returns(_latestBytes bytes) +func (_Validation *ValidationSession) LatestBytes() ([]byte, error) { + return _Validation.Contract.LatestBytes(&_Validation.CallOpts) +} + +// LatestBytes is a free data retrieval call binding the contract method 0x34174e6c. +// +// Solidity: function LatestBytes() constant returns(_latestBytes bytes) +func (_Validation *ValidationCallerSession) LatestBytes() ([]byte, error) { + return _Validation.Contract.LatestBytes(&_Validation.CallOpts) +} + // MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. // // Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) @@ -274,25 +300,25 @@ func (_Validation *ValidationTransactorSession) ValidateBlock(header []byte, pre return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) } -// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. +// ValidationTest is a paid mutator transaction binding the contract method 0x31404c17. // -// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactor) ValidationTest(opts *bind.TransactOpts, header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.contract.Transact(opts, "ValidationTest", header, prefixHeader, prefixExtraData) +// Solidity: function ValidationTest(header bytes) returns() +func (_Validation *ValidationTransactor) ValidationTest(opts *bind.TransactOpts, header []byte) (*types.Transaction, error) { + return _Validation.contract.Transact(opts, "ValidationTest", header) } -// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. +// ValidationTest is a paid mutator transaction binding the contract method 0x31404c17. // -// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +// Solidity: function ValidationTest(header bytes) returns() +func (_Validation *ValidationSession) ValidationTest(header []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header) } -// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. +// ValidationTest is a paid mutator transaction binding the contract method 0x31404c17. // -// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactorSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +// Solidity: function ValidationTest(header bytes) returns() +func (_Validation *ValidationTransactorSession) ValidationTest(header []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header) } // ValidationBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Validation contract. diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 738bb17..702e791 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -4,6 +4,7 @@ package cli import ( "context" + "encoding/hex" "fmt" "log" "math/big" @@ -118,6 +119,23 @@ func Launch(setup config.Setup) { }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "latestBytesSubmitted", + Help: "Queries the validator contract for the last block submitted, arguments: latestBlockSubmitted", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + result, err := validation.LatestBlock(&bind.CallOpts{}) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + c.Println("Last Block Submitted:") + c.Printf("0x%x\n", result) + + c.Println("===============================================================") + }, + }) + // Get block N and spew out the RLP encoded block shell.AddCmd(&ishell.Cmd{ Name: "rlpBlock", @@ -171,22 +189,42 @@ func Launch(setup config.Setup) { c.Println("Too many arguments entered.") } else { c.Println("RLP encode block: " + c.Args[0]) - encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) - // bhash := "5cd9f5b157b070a77a9fa2928f5891c9d8ed88805480c9e2736ad749b2439428" - // arr, _ := hex.DecodeString(bhash) - // var test [32]byte + // encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) + encodedBlock, _, _ := calculateRlpEncoding(client, c.Args[0]) + bhash := "5cd9f5b157b070a77a9fa2928f5891c9d8ed88805480c9e2736ad749b2439428" + arr, _ := hex.DecodeString(bhash) + var test [32]byte - // copy(test[:], arr) + copy(test[:], arr) - // c.Printf("%s\n", bhash) - // c.Printf("%+x\n", arr) - // c.Printf("%+x\n", test) - res, err := validation.ValidationTest(auth, encodedBlock) + c.Printf("%s\n", bhash) + c.Printf("%+x\n", arr) + c.Printf("%+x\n", test) + c.Println(encodedBlock) + str := hex.EncodeToString(encodedBlock) + testarossa, _ := hex.DecodeString(str) + c.Println(str) + res, err := validation.ValidationTest(auth, testarossa) if err != nil { c.Printf("Error: %s", err) return } c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) + + result, err := validation.LatestBlock(&bind.CallOpts{}) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + c.Println("Last Block Submitted:") + c.Printf("0x%x\n", result) + res2, err := validation.LatestBytes(&bind.CallOpts{}) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + c.Println("Last Bytes Submitted:") + c.Printf("0x%x\n", res2) } c.Println("===============================================================") }, diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 69a77cb..67734a1 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -120,23 +120,23 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by // Generate an interface to encode the standard block header blockInterface := GenerateInterface(blockHeader) - encodedBlock := EncodeBlock(blockInterface) - fmt.Printf("\nEncoded Block Header:\n%+x\n", encodedBlock) + rlpBlock = EncodeBlock(blockInterface) + fmt.Printf("\nEncoded Block Header:\n%+x\n", rlpBlock) // Generate an interface to encode the blockheader without the signature in the extraData blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] blockInterface = GenerateInterface(blockHeader) - encodedBlock = EncodeBlock(blockInterface) - prefixBlock = encodedBlock[1:3] + encodedPrefixBlock := EncodeBlock(blockInterface) + prefixBlock = encodedPrefixBlock[1:3] fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", prefixBlock) // Generate an interface to encode the blockheader without the signature in the extraData encExtra, _ := hex.DecodeString(blockHeader.Extra[2:]) - encodedBlock = EncodeBlock(encExtra) - prefixExtra = encodedBlock[0:1] + encodedExtraData := EncodeBlock(encExtra) + prefixExtra = encodedExtraData[0:1] fmt.Printf("\nExtraData Field Prefix:\n%+x\n", prefixExtra) - return encodedBlock, prefixBlock, prefixExtra + return rlpBlock, prefixBlock, prefixExtra } diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..b14dea2 --- /dev/null +++ b/test/test.js @@ -0,0 +1,184 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Util = require('ethereumjs-util'); +const Web3 = require('web3'); +const Web3Utils = require('web3-utils'); +const Web3Abi = require('web3-eth-abi'); +const Web3Accounts = require('web3-eth-accounts'); +const rlp = require('rlp'); + +const Validation = artifacts.require("Validation"); +const Recover = artifacts.require("Recover"); + +const web3 = new Web3(); + +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); + +function hexToBytes(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + +function bytesToHex(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(""); +} + +contract.only('test.js', (accounts) => { + const blockNum = 22 + const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); + + const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); + + const ionAbi = [{"constant":false,"inputs":[{"name":"header","type":"bytes"}],"name":"ValidationTest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"LatestBytes","outputs":[{"name":"_latestBytes","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}]; + const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; + const genHash = "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28"; + + + // Here the block header is signed off chain but by a whitelisted validator + it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { + const accounts = web3.eth.accounts; + const signer = accounts[0]; + const ValidationContract = web3.eth.contract(ionAbi); + + // instantiate by address + const validation = ValidationContract.at('0xb9fd43a71c076f02d1dbbf473c389f0eacec559f'); + + // Get a single block + const block = web3.eth.getBlock(blockNum); + + // Decompose the values in the block to hash + const parentHash = block.parentHash; + const sha3Uncles = block.sha3Uncles; + const coinbase = block.miner; + const root = block.stateRoot; + const txHash = block.transactionsRoot; + const receiptHash = block.receiptsRoot; + const logsBloom = block.logsBloom; + const difficulty = Web3Utils.toBN(block.difficulty); + const number = Web3Utils.toBN(block.number); + const gasLimit = block.gasLimit; + const gasUsed = block.gasUsed; + const timestamp = Web3Utils.toBN(block.timestamp); + const extraData = block.extraData; + const mixHash = block.mixHash; + const nonce = block.nonce; + + // Create new signed hash + const extraBytes = hexToBytes(extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + bytesToHex(extraBytesShort); + + // Make some changes to the block + const header = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + extraDataShort, + mixHash, + nonce + ]; + + // Encode and sign the new header + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const headerHash = Util.sha3(encodedHeader); + + const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + + const sig = Util.ecsign(headerHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = Util.pubToAddress(pubKey); + + // const sigTest = Util.toRpcSig(sig.v, sig.r, sig.s); + const newSigBytes = Buffer.concat([sig.r, sig.s]); + let newSig = newSigBytes.toString('hex') + '00'; + if (sig.v==27) { + newSig = newSigBytes.toString('hex') + '00'; + } else { + newSig = newSigBytes.toString('hex') + '01'; + } + + // Append signature to the end of extraData + const sigBytes = hexToBytes(newSig.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + bytesToHex(newExtraDataBytes); + + const newBlockHeader = [ + parentHash, + sha3Uncles, + coinbase, + root, + txHash, + receiptHash, + logsBloom, + difficulty, + number, + gasLimit, + gasUsed, + timestamp, + newExtraData, + mixHash, + nonce + ]; + + const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); + const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + assert.equal(block.hash, blockHeaderHash); + + // The new prefixes should be calculated off chain + const prefixHeader = '0x0214'; + const prefixExtraData = '0xa0'; + + console.log("Encoded Block Header:\n", encodedBlockHeader); + const ecrecoveryReceipt = await validation.ValidationTest(encodedBlockHeader, {from: signer, gas: 1000000}); + const latestBlockReceipt = await validation.LatestBlock(); + const latestBytesReceipt = await validation.LatestBytes(); + console.log("Expected Block Hash:\n", block.hash); + console.log("Latest Block Hash:\n", latestBlockReceipt); + console.log("latest Bytes:\n", latestBytesReceipt); + // const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; + // const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; + // console.log(block.hash, recoveredBlockHash) + // assert.equal(block.hash, recoveredBlockHash) + // assert.equal(recoveredSignature, signer); + }) + + // Here the block header is signed off chain but by a whitelisted validator + it('Test: Check the latest data...', async () => { + const accounts = web3.eth.accounts; + const signer = accounts[0]; + const ValidationContract = web3.eth.contract(ionAbi); + + // instantiate by address + const validation = ValidationContract.at('0xb9fd43a71c076f02d1dbbf473c389f0eacec559f'); + + // Get a single block + const block = web3.eth.getBlock(blockNum); + + const latestBlockReceipt = await validation.LatestBlock(); + const latestBytesReceipt = await validation.LatestBytes(); + console.log("Expected Block Hash:\n", block.hash); + console.log("Latest Block Hash:\n", latestBlockReceipt); + console.log("latest Bytes:\n", latestBytesReceipt); + }) + +}); \ No newline at end of file diff --git a/test/validation.js b/test/validation.js index 89d49e7..b18fc1e 100644 --- a/test/validation.js +++ b/test/validation.js @@ -29,7 +29,7 @@ function bytesToHex(bytes) { return hex.join(""); } -contract.only('validation.js', (accounts) => { +contract('validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From 025a0db36fdefa630d8574f4425866614cf236fa Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 26 Jun 2018 14:11:43 +0100 Subject: [PATCH 012/203] Found some problems with the rlp encoding method used, didnt treat single characters properly :) --- ion-cli/cli/cli.go | 35 +++++++---------------------------- ion-cli/cli/rpc.go | 11 ++++++++++- test/test.js | 3 ++- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 702e791..8353387 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -124,12 +124,12 @@ func Launch(setup config.Setup) { Help: "Queries the validator contract for the last block submitted, arguments: latestBlockSubmitted", Func: func(c *ishell.Context) { c.Println("===============================================================") - result, err := validation.LatestBlock(&bind.CallOpts{}) + result, err := validation.LatestBytes(&bind.CallOpts{}) if err != nil { fmt.Printf("Error: %s", err) return } - c.Println("Last Block Submitted:") + c.Println("Last Bytes Submitted:") c.Printf("0x%x\n", result) c.Println("===============================================================") @@ -191,40 +191,19 @@ func Launch(setup config.Setup) { c.Println("RLP encode block: " + c.Args[0]) // encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) encodedBlock, _, _ := calculateRlpEncoding(client, c.Args[0]) - bhash := "5cd9f5b157b070a77a9fa2928f5891c9d8ed88805480c9e2736ad749b2439428" - arr, _ := hex.DecodeString(bhash) - var test [32]byte - copy(test[:], arr) + // Fiddle around because otherwise the formatting is wrong + encodedStr := hex.EncodeToString(encodedBlock) + encodedHex, _ := hex.DecodeString(encodedStr) - c.Printf("%s\n", bhash) - c.Printf("%+x\n", arr) - c.Printf("%+x\n", test) - c.Println(encodedBlock) - str := hex.EncodeToString(encodedBlock) - testarossa, _ := hex.DecodeString(str) - c.Println(str) - res, err := validation.ValidationTest(auth, testarossa) + // Submit to the validation contract + res, err := validation.ValidationTest(auth, encodedHex) if err != nil { c.Printf("Error: %s", err) return } c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) - result, err := validation.LatestBlock(&bind.CallOpts{}) - if err != nil { - fmt.Printf("Error: %s", err) - return - } - c.Println("Last Block Submitted:") - c.Printf("0x%x\n", result) - res2, err := validation.LatestBytes(&bind.CallOpts{}) - if err != nil { - fmt.Printf("Error: %s", err) - return - } - c.Println("Last Bytes Submitted:") - c.Printf("0x%x\n", res2) } c.Println("===============================================================") }, diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 67734a1..421723d 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -148,7 +148,16 @@ func GenerateInterface(blockHeader Header) (rest interface{}) { // Append items into the interface for i := 0; i < s.NumField(); i++ { f := s.Field(i).String() - element, _ := hex.DecodeString(f[2:]) + + // Remove the 0x prefix + f = f[2:] + + // single character then pre-pending a 0 turns it into a byte + if len(f) == 1 { + f = "0" + f + } + + element, _ := hex.DecodeString(f) blockInterface = append(blockInterface, element) } diff --git a/test/test.js b/test/test.js index b14dea2..8418bf2 100644 --- a/test/test.js +++ b/test/test.js @@ -30,7 +30,7 @@ function bytesToHex(bytes) { } contract.only('test.js', (accounts) => { - const blockNum = 22 + const blockNum = 10 const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); @@ -140,6 +140,7 @@ contract.only('test.js', (accounts) => { nonce ]; + console.log(newBlockHeader) const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); assert.equal(block.hash, blockHeaderHash); From c1bdc9d1ba81535cfef76f46005ff106eb3b34d0 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 26 Jun 2018 15:50:08 +0100 Subject: [PATCH 013/203] Fixed the encoding of blocks in golang --- contracts/Validation.sol | 1 + ion-cli/Validation/Validation.go | 2 +- ion-cli/cli/cli.go | 7 +++---- ion-cli/cli/rpc.go | 2 +- test/test.js | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 243f1b5..75bce12 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -104,6 +104,7 @@ contract Validation { function ValidationTest(bytes header) public { bytes32 blockHash = keccak256(header); + someBytes = header; prevBlockHash = blockHash; } diff --git a/ion-cli/Validation/Validation.go b/ion-cli/Validation/Validation.go index 5812145..dca55d9 100644 --- a/ion-cli/Validation/Validation.go +++ b/ion-cli/Validation/Validation.go @@ -18,7 +18,7 @@ import ( const ValidationABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"}],\"name\":\"ValidationTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBytes\",\"outputs\":[{\"name\":\"_latestBytes\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. -const ValidationBin = `608060405234801561001057600080fd5b506040516109f13803806109f183398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160046000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816002816000191690555050505061084b806101a66000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063927a32e3146100675780639db7d9f7146100b4578063aae933e4146100e7578063d405af3d146101dc575b600080fd5b34801561007357600080fd5b506100966004803603810190808035600019169060200190929190505050610248565b60405180826000191660001916815260200191505060405180910390f35b3480156100c057600080fd5b506100c9610266565b60405180826000191660001916815260200191505060405180910390f35b3480156100f357600080fd5b506101da600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610270565b005b3480156101e857600080fd5b506101f1610562565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610234578082015181840152602081019050610219565b505050509050019250505060405180910390f35b60036020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156102b85780518252602082019150602081019050602083039250610293565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561035c5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156103935781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156103ca5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156104015781602001602082028038833980820191505090505b509350610412878d60008a516105f0565b600260218801600260208e016004610bb8fa50610435868d608c8c0389516105f0565b600160208701600160208d016004610bb8fa50610458848d602a8c0387516105f0565b6104638787866106ab565b9250826040518082805190602001908083835b60208310151561049b5780518252602082019150602081019050602083039250610476565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506104da858d606b8c0388516105f0565b6104e48286610757565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156105e657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161059c575b5050505050905090565b60008090505b818110156106a4578381840181518110151561060e57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561066757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506105f6565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156107125781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561076d57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561079857601b810190505b601b8160ff1614806107ad5750601c8160ff16145b15156107b857600080fd5b6107c4868285856107cf565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561081257600080fd5b80925050509493505050505600a165627a7a72305820d1ebc40c25f798a40ded32bb082078c894c9d241047b7bb053d9dd09b79be9820029` +const ValidationBin = `608060405234801561001057600080fd5b50604051610e8f380380610e8f83398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b8160028160001916905550505050610ce9806101a66000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334174e6c1461007d578063927a32e31461010d5780639db7d9f71461015a578063aae933e41461018d578063d405af3d14610282578063ebeafd77146102ee575b600080fd5b34801561008957600080fd5b506100926103e3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100d25780820151818401526020810190506100b7565b50505050905090810190601f1680156100ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011957600080fd5b5061013c6004803603810190808035600019169060200190929190505050610485565b60405180826000191660001916815260200191505060405180910390f35b34801561016657600080fd5b5061016f6104a3565b60405180826000191660001916815260200191505060405180910390f35b34801561019957600080fd5b50610280600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ad565b005b34801561028e57600080fd5b5061029761079f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102da5780820151818401526020810190506102bf565b505050509050019250505060405180910390f35b3480156102fa57600080fd5b506103e1600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061082d565b005b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561047b5780601f106104505761010080835404028352916020019161047b565b820191906000526020600020905b81548152906001019060200180831161045e57829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156104f557805182526020820191506020810190506020830392506104d0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156105995781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105d05781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156106075781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561063e5781602001602082028038833980820191505090505b50935061064f878d60008a516109e9565b600260218801600260208e016004610bb8fa50610672868d608c8c0389516109e9565b600160208701600160208d016004610bb8fa50610695848d602a8c0387516109e9565b6106a0878786610aa4565b9250826040518082805190602001908083835b6020831015156106d857805182526020820191506020810190506020830392506106b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150610717858d606b8c0388516109e9565b6107218286610b50565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561082357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116107d9575b5050505050905090565b60008060608060608088519550886040518082805190602001908083835b602083101515610870578051825260208201915060208101905060208303925061084b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020945088600390805190602001906108b5929190610c18565b5084600281600019169055507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018560405180826000191660001916815260200191505060405180910390a1608d86036040519080825280601f01601f1916602001820160405280156109365781602001602082028038833980820191505090505b509350601f6040519080825280601f01601f19166020018201604052801561096d5781602001602082028038833980820191505090505b50925060416040519080825280601f01601f1916602001820160405280156109a45781602001602082028038833980820191505090505b509150602a6040519080825280601f01601f1916602001820160405280156109db5781602001602082028038833980820191505090505b509050505050505050505050565b60008090505b81811015610a9d5783818401815181101515610a0757fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028582815181101515610a6057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506109ef565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f191660200182016040528015610b0b5781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610b6657600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610b9157601b810190505b601b8160ff161480610ba65750601c8160ff16145b1515610bb157600080fd5b610bbd86828585610bc8565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610c0b57600080fd5b8092505050949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c5957805160ff1916838001178555610c87565b82800160010185558215610c87579182015b82811115610c86578251825591602001919060010190610c6b565b5b509050610c949190610c98565b5090565b610cba91905b80821115610cb6576000816000905550600101610c9e565b5090565b905600a165627a7a7230582009a70c54afc4fb7f922da0ee026dacb18eb44755eb2bc1e8b12424c23f2239b90029` // DeployValidation deploys a new Ethereum contract, binding an instance of Validation to it. func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address, genHash [32]byte) (common.Address, *types.Transaction, *Validation, error) { diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 8353387..95d6201 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -4,7 +4,6 @@ package cli import ( "context" - "encoding/hex" "fmt" "log" "math/big" @@ -193,11 +192,11 @@ func Launch(setup config.Setup) { encodedBlock, _, _ := calculateRlpEncoding(client, c.Args[0]) // Fiddle around because otherwise the formatting is wrong - encodedStr := hex.EncodeToString(encodedBlock) - encodedHex, _ := hex.DecodeString(encodedStr) + // encodedStr := hex.EncodeToString(encodedBlock) + // encodedHex, _ := hex.DecodeString(encodedStr) // Submit to the validation contract - res, err := validation.ValidationTest(auth, encodedHex) + res, err := validation.ValidationTest(auth, encodedBlock) if err != nil { c.Printf("Error: %s", err) return diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 421723d..4f4a9a7 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -153,7 +153,7 @@ func GenerateInterface(blockHeader Header) (rest interface{}) { f = f[2:] // single character then pre-pending a 0 turns it into a byte - if len(f) == 1 { + if len(f)%2 != 0 { f = "0" + f } diff --git a/test/test.js b/test/test.js index 8418bf2..9034b62 100644 --- a/test/test.js +++ b/test/test.js @@ -30,7 +30,7 @@ function bytesToHex(bytes) { } contract.only('test.js', (accounts) => { - const blockNum = 10 + const blockNum = 8 const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From 8ad455441ca58c73ea7bc9b95f36e5018bba798e Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 08:49:43 +0100 Subject: [PATCH 014/203] see previous commit didnt use add correctly... --- contracts/Validation.sol | 2 +- ion-cli/Validation/Validation.go | 26 +++++++++---------- ion-cli/block.json | 36 ++++++++++++-------------- ion-cli/cli/cli.go | 7 +++-- ion-cli/cli/rpc.go | 21 ++++++++++----- ion-cli/cli/rpc_test.go | 44 +++++++++++++++++++++----------- ion-cli/config/config_test.go | 2 +- test/test.js | 6 +++-- 8 files changed, 81 insertions(+), 63 deletions(-) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 75bce12..98757a9 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -102,7 +102,7 @@ contract Validation { } - function ValidationTest(bytes header) public { + function ValidationTest(bytes header, bytes prefixHeader, bytes prefixExtraData) public { bytes32 blockHash = keccak256(header); someBytes = header; diff --git a/ion-cli/Validation/Validation.go b/ion-cli/Validation/Validation.go index dca55d9..3f5b744 100644 --- a/ion-cli/Validation/Validation.go +++ b/ion-cli/Validation/Validation.go @@ -15,7 +15,7 @@ import ( ) // ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"}],\"name\":\"ValidationTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBytes\",\"outputs\":[{\"name\":\"_latestBytes\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" +const ValidationABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"LatestBytes\",\"outputs\":[{\"name\":\"_latestBytes\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidationTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. const ValidationBin = `608060405234801561001057600080fd5b50604051610e8f380380610e8f83398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b8160028160001916905550505050610ce9806101a66000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334174e6c1461007d578063927a32e31461010d5780639db7d9f71461015a578063aae933e41461018d578063d405af3d14610282578063ebeafd77146102ee575b600080fd5b34801561008957600080fd5b506100926103e3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100d25780820151818401526020810190506100b7565b50505050905090810190601f1680156100ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011957600080fd5b5061013c6004803603810190808035600019169060200190929190505050610485565b60405180826000191660001916815260200191505060405180910390f35b34801561016657600080fd5b5061016f6104a3565b60405180826000191660001916815260200191505060405180910390f35b34801561019957600080fd5b50610280600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ad565b005b34801561028e57600080fd5b5061029761079f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102da5780820151818401526020810190506102bf565b505050509050019250505060405180910390f35b3480156102fa57600080fd5b506103e1600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061082d565b005b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561047b5780601f106104505761010080835404028352916020019161047b565b820191906000526020600020905b81548152906001019060200180831161045e57829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156104f557805182526020820191506020810190506020830392506104d0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156105995781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105d05781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156106075781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561063e5781602001602082028038833980820191505090505b50935061064f878d60008a516109e9565b600260218801600260208e016004610bb8fa50610672868d608c8c0389516109e9565b600160208701600160208d016004610bb8fa50610695848d602a8c0387516109e9565b6106a0878786610aa4565b9250826040518082805190602001908083835b6020831015156106d857805182526020820191506020810190506020830392506106b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150610717858d606b8c0388516109e9565b6107218286610b50565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561082357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116107d9575b5050505050905090565b60008060608060608088519550886040518082805190602001908083835b602083101515610870578051825260208201915060208101905060208303925061084b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020945088600390805190602001906108b5929190610c18565b5084600281600019169055507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018560405180826000191660001916815260200191505060405180910390a1608d86036040519080825280601f01601f1916602001820160405280156109365781602001602082028038833980820191505090505b509350601f6040519080825280601f01601f19166020018201604052801561096d5781602001602082028038833980820191505090505b50925060416040519080825280601f01601f1916602001820160405280156109a45781602001602082028038833980820191505090505b509150602a6040519080825280601f01601f1916602001820160405280156109db5781602001602082028038833980820191505090505b509050505050505050505050565b60008090505b81811015610a9d5783818401815181101515610a0757fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028582815181101515610a6057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506109ef565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f191660200182016040528015610b0b5781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610b6657600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610b9157601b810190505b601b8160ff161480610ba65750601c8160ff16145b1515610bb157600080fd5b610bbd86828585610bc8565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610c0b57600080fd5b8092505050949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c5957805160ff1916838001178555610c87565b82800160010185558215610c87579182015b82811115610c86578251825591602001919060010190610c6b565b5b509050610c949190610c98565b5090565b610cba91905b80821115610cb6576000816000905550600101610c9e565b5090565b905600a165627a7a7230582009a70c54afc4fb7f922da0ee026dacb18eb44755eb2bc1e8b12424c23f2239b90029` @@ -300,25 +300,25 @@ func (_Validation *ValidationTransactorSession) ValidateBlock(header []byte, pre return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) } -// ValidationTest is a paid mutator transaction binding the contract method 0x31404c17. +// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. // -// Solidity: function ValidationTest(header bytes) returns() -func (_Validation *ValidationTransactor) ValidationTest(opts *bind.TransactOpts, header []byte) (*types.Transaction, error) { - return _Validation.contract.Transact(opts, "ValidationTest", header) +// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactor) ValidationTest(opts *bind.TransactOpts, header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.contract.Transact(opts, "ValidationTest", header, prefixHeader, prefixExtraData) } -// ValidationTest is a paid mutator transaction binding the contract method 0x31404c17. +// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. // -// Solidity: function ValidationTest(header bytes) returns() -func (_Validation *ValidationSession) ValidationTest(header []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header) +// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) } -// ValidationTest is a paid mutator transaction binding the contract method 0x31404c17. +// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. // -// Solidity: function ValidationTest(header bytes) returns() -func (_Validation *ValidationTransactorSession) ValidationTest(header []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header) +// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactorSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) } // ValidationBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Validation contract. diff --git a/ion-cli/block.json b/ion-cli/block.json index 6bf6cd4..f1ff951 100644 --- a/ion-cli/block.json +++ b/ion-cli/block.json @@ -1,22 +1,18 @@ { - "parentHash": "0xad34f0f919e4b06b18b0c674b8b9f6738a4878c76e837c8f31a2079f21dced1c", - "difficulty": "2", - "extraData": "0xd78301080a846765746887676f312e392e33856c696e75780000000000000000e0ac79c5577889dfb5745ace9c5dfebe1a11bb19ced9b98b427e7bd4c85765ce17154e658440915743ec442fb64756483bc592616754d13a3c62fce5a56ac9f501", - "gasLimit": "16614106", - "gasUsed": "0", - "hash": "0xd1d7abeb1345861e0103a24a239c178ccf930b069e50f2697d82fdd3496746ab", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "10", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "606", - "stateRoot": "0xdb37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dc", - "timestamp": "1529396972", - "totalDifficulty": "21", - "transactions": [], - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncles": [] + "parentHash": "0xb5567eddb3bf1b6d12af53e4f8983ee82684d48ce65afef8aa067bf6c59d801e", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x0000000000000000000000000000000000000000", + "stateRoot": "0xdb37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dc", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x2", + "number": "0x8", + "gasLimit": "0xfe01c8", + "gasUsed": "0x0", + "timestamp": "0x5b3252dc", + "extraData": "0xd78301080a846765746887676f312e392e33856c696e75780000000000000000af64d47b7b33960eff2eaedfd6fae84784e47f13c97df41498c81288c72fe63c2d0429d8692d756d1c7ccb84f68e20acc298465de6b841ee34edc2778b8af3ac00", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xe65c9896678436a46b106b85cdea91a425e7df7c73128163f66125eefb27fa53" } diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 95d6201..c75d7c9 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -165,7 +165,6 @@ func Launch(setup config.Setup) { } else { c.Println("RLP encode block: " + c.Args[0]) encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) - c.Printf("\nEncoded Block:\n0x%x\n", encodedBlock) res, err := validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) if err != nil { c.Printf("Error: %s", err) @@ -188,15 +187,15 @@ func Launch(setup config.Setup) { c.Println("Too many arguments entered.") } else { c.Println("RLP encode block: " + c.Args[0]) - // encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) - encodedBlock, _, _ := calculateRlpEncoding(client, c.Args[0]) + encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) + // encodedBlock, _, _ := calculateRlpEncoding(client, c.Args[0]) // Fiddle around because otherwise the formatting is wrong // encodedStr := hex.EncodeToString(encodedBlock) // encodedHex, _ := hex.DecodeString(encodedStr) // Submit to the validation contract - res, err := validation.ValidationTest(auth, encodedBlock) + res, err := validation.ValidationTest(auth, encodedBlock, prefixBlock, prefixExtra) if err != nil { c.Printf("Error: %s", err) return diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 4f4a9a7..372c52f 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -105,7 +105,15 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by return } - // Marshal into a JSON + // Encode the orginal block header + rlpBlock, err = rlp.EncodeToBytes(&lastBlock) + if err != nil { + fmt.Println("can't RLP encode requested block:", err) + return + } + fmt.Printf("\nEncoded Block Header:\n%+x\n", rlpBlock) + + // Marshal block into a JSON to allow manipulation of specific fields b, err := json.MarshalIndent(lastBlock, "", " ") if err != nil { fmt.Printf("Error: %s", err) @@ -118,14 +126,9 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by return } - // Generate an interface to encode the standard block header - blockInterface := GenerateInterface(blockHeader) - rlpBlock = EncodeBlock(blockInterface) - fmt.Printf("\nEncoded Block Header:\n%+x\n", rlpBlock) - // Generate an interface to encode the blockheader without the signature in the extraData blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] - blockInterface = GenerateInterface(blockHeader) + blockInterface := GenerateInterface(blockHeader) encodedPrefixBlock := EncodeBlock(blockInterface) prefixBlock = encodedPrefixBlock[1:3] fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", prefixBlock) @@ -144,6 +147,7 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by func GenerateInterface(blockHeader Header) (rest interface{}) { blockInterface := []interface{}{} s := reflect.ValueOf(&blockHeader).Elem() + // fmt.Println(s) // Append items into the interface for i := 0; i < s.NumField(); i++ { @@ -158,6 +162,9 @@ func GenerateInterface(blockHeader Header) (rest interface{}) { } element, _ := hex.DecodeString(f) + // fmt.Printf("%+v\n", s.Field(i)) + // fmt.Printf("%+x\n", f) + // fmt.Printf("%+x\n", element) blockInterface = append(blockInterface, element) } diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index 6ec7ebf..012b8d4 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -2,18 +2,32 @@ package cli_test -// func Test_EncodeBlock(t *testing.T) { -// // read a fake block -// raw, _ := ioutil.ReadFile("../block.json") -// -// const expectedRlpHex = "f90256a0ad34f0f919e4b06b18b0c674b8b9f6738a4878c76e837c8f31a2079f21dced1ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0db37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a83fd82da80845b28beecb861d78301080a846765746887676f312e392e33856c696e75780000000000000000e0ac79c5577889dfb5745ace9c5dfebe1a11bb19ced9b98b427e7bd4c85765ce17154e658440915743ec442fb64756483bc592616754d13a3c62fce5a56ac9f501a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" -// -// var marshalledBlock cli.Header -// json.Unmarshal(raw, &marshalledBlock) -// -// // Now RLP encode the block -// blockInterface := cli.GenerateInterface(marshalledBlock) -// fmt.Printf("%+v\n", marshalledBlock.Extra) -// hash := cli.EncodeBlock(blockInterface) -// assert.Equal(t, expectedRlpHex, hex.EncodeToString(hash)) -// } +import ( + "encoding/json" + "fmt" + "io/ioutil" + "testing" + + "github.com/ion/ion-cli/cli" +) + +func Test_EncodeBlock(t *testing.T) { + // read a fake block + raw, _ := ioutil.ReadFile("../block.json") + + const expectedRlpHex = "f90256a0b5567eddb3bf1b6d12af53e4f8983ee82684d48ce65afef8aa067bf6c59d801ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0db37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020883fe01c880845b3252dcb861d78301080a846765746887676f312e392e33856c696e75780000000000000000af64d47b7b33960eff2eaedfd6fae84784e47f13c97df41498c81288c72fe63c2d0429d8692d756d1c7ccb84f68e20acc298465de6b841ee34edc2778b8af3ac00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + const expectedHash = "e65c9896678436a46b106b85cdea91a425e7df7c73128163f66125eefb27fa53" + + var marshalledBlock cli.Header + json.Unmarshal(raw, &marshalledBlock) + + fmt.Printf("%+v\n", marshalledBlock) + + // Now RLP encode the block + blockInterface := cli.GenerateInterface(marshalledBlock) + fmt.Println(blockInterface) + + hash := cli.EncodeBlock(blockInterface) + fmt.Printf("%+v\n", hash) + // assert.Equal(t, expectedRlpHex, hex.EncodeToString(hash)) +} diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index aa94156..2d00728 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ion/ion-config/config" + "github.com/ion/ion-cli/config" ) func Test_Read_ValidSetupJson(t *testing.T) { diff --git a/test/test.js b/test/test.js index 9034b62..9feb8eb 100644 --- a/test/test.js +++ b/test/test.js @@ -35,7 +35,7 @@ contract.only('test.js', (accounts) => { const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); - const ionAbi = [{"constant":false,"inputs":[{"name":"header","type":"bytes"}],"name":"ValidationTest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"LatestBytes","outputs":[{"name":"_latestBytes","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}]; + const ionAbi = [{"constant":true,"inputs":[],"name":"LatestBytes","outputs":[{"name":"_latestBytes","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidationTest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}]; const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; const genHash = "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28"; @@ -141,6 +141,8 @@ contract.only('test.js', (accounts) => { ]; console.log(newBlockHeader) + console.log(gasUsed) + console.log('0x' + rlp.encode(gasUsed).toString('hex')); const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); assert.equal(block.hash, blockHeaderHash); @@ -150,7 +152,7 @@ contract.only('test.js', (accounts) => { const prefixExtraData = '0xa0'; console.log("Encoded Block Header:\n", encodedBlockHeader); - const ecrecoveryReceipt = await validation.ValidationTest(encodedBlockHeader, {from: signer, gas: 1000000}); + const ecrecoveryReceipt = await validation.ValidationTest(encodedBlockHeader, prefixHeader, prefixExtraData, {from: signer, gas: 1000000}); const latestBlockReceipt = await validation.LatestBlock(); const latestBytesReceipt = await validation.LatestBytes(); console.log("Expected Block Hash:\n", block.hash); From 8d013e97f331536ad98bf3fade3fb40679bf3d84 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 09:28:39 +0100 Subject: [PATCH 015/203] Validate Block works correctly other than history of blocks not stored --- contracts/Validation.sol | 9 +- ion-cli/Validation/Validation.go | 23 +--- ion-cli/cli/cli.go | 76 +------------ ion-cli/cli/rpc.go | 34 ------ package.json | 1 + test/test.js | 187 ------------------------------- 6 files changed, 8 insertions(+), 322 deletions(-) delete mode 100644 test/test.js diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 98757a9..1598e6b 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -94,7 +94,7 @@ contract Validation { extractData(extraDataSig, header, length-107, extraDataSig.length); address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); - // require(m_validators[sig_addr]==true, "Signer not a validator!"); + require(m_validators[sig_addr]==true, "Signer not a validator!"); prevBlockHash = blockHash; @@ -102,13 +102,6 @@ contract Validation { } - function ValidationTest(bytes header, bytes prefixHeader, bytes prefixExtraData) public { - bytes32 blockHash = keccak256(header); - - someBytes = header; - prevBlockHash = blockHash; - } - function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { // Get the lengths sorted because they're needed later... uint256 headerStartLength = headerStart.length; diff --git a/ion-cli/Validation/Validation.go b/ion-cli/Validation/Validation.go index 3f5b744..05fa0a2 100644 --- a/ion-cli/Validation/Validation.go +++ b/ion-cli/Validation/Validation.go @@ -15,7 +15,7 @@ import ( ) // ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"LatestBytes\",\"outputs\":[{\"name\":\"_latestBytes\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidationTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" +const ValidationABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"LatestBytes\",\"outputs\":[{\"name\":\"_latestBytes\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. const ValidationBin = `608060405234801561001057600080fd5b50604051610e8f380380610e8f83398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b8160028160001916905550505050610ce9806101a66000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334174e6c1461007d578063927a32e31461010d5780639db7d9f71461015a578063aae933e41461018d578063d405af3d14610282578063ebeafd77146102ee575b600080fd5b34801561008957600080fd5b506100926103e3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100d25780820151818401526020810190506100b7565b50505050905090810190601f1680156100ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011957600080fd5b5061013c6004803603810190808035600019169060200190929190505050610485565b60405180826000191660001916815260200191505060405180910390f35b34801561016657600080fd5b5061016f6104a3565b60405180826000191660001916815260200191505060405180910390f35b34801561019957600080fd5b50610280600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ad565b005b34801561028e57600080fd5b5061029761079f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102da5780820151818401526020810190506102bf565b505050509050019250505060405180910390f35b3480156102fa57600080fd5b506103e1600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061082d565b005b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561047b5780601f106104505761010080835404028352916020019161047b565b820191906000526020600020905b81548152906001019060200180831161045e57829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156104f557805182526020820191506020810190506020830392506104d0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156105995781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105d05781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156106075781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561063e5781602001602082028038833980820191505090505b50935061064f878d60008a516109e9565b600260218801600260208e016004610bb8fa50610672868d608c8c0389516109e9565b600160208701600160208d016004610bb8fa50610695848d602a8c0387516109e9565b6106a0878786610aa4565b9250826040518082805190602001908083835b6020831015156106d857805182526020820191506020810190506020830392506106b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150610717858d606b8c0388516109e9565b6107218286610b50565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561082357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116107d9575b5050505050905090565b60008060608060608088519550886040518082805190602001908083835b602083101515610870578051825260208201915060208101905060208303925061084b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020945088600390805190602001906108b5929190610c18565b5084600281600019169055507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018560405180826000191660001916815260200191505060405180910390a1608d86036040519080825280601f01601f1916602001820160405280156109365781602001602082028038833980820191505090505b509350601f6040519080825280601f01601f19166020018201604052801561096d5781602001602082028038833980820191505090505b50925060416040519080825280601f01601f1916602001820160405280156109a45781602001602082028038833980820191505090505b509150602a6040519080825280601f01601f1916602001820160405280156109db5781602001602082028038833980820191505090505b509050505050505050505050565b60008090505b81811015610a9d5783818401815181101515610a0757fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028582815181101515610a6057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506109ef565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f191660200182016040528015610b0b5781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610b6657600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610b9157601b810190505b601b8160ff161480610ba65750601c8160ff16145b1515610bb157600080fd5b610bbd86828585610bc8565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610c0b57600080fd5b8092505050949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c5957805160ff1916838001178555610c87565b82800160010185558215610c87579182015b82811115610c86578251825591602001919060010190610c6b565b5b509050610c949190610c98565b5090565b610cba91905b80821115610cb6576000816000905550600101610c9e565b5090565b905600a165627a7a7230582009a70c54afc4fb7f922da0ee026dacb18eb44755eb2bc1e8b12424c23f2239b90029` @@ -300,27 +300,6 @@ func (_Validation *ValidationTransactorSession) ValidateBlock(header []byte, pre return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) } -// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. -// -// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactor) ValidationTest(opts *bind.TransactOpts, header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.contract.Transact(opts, "ValidationTest", header, prefixHeader, prefixExtraData) -} - -// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. -// -// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) -} - -// ValidationTest is a paid mutator transaction binding the contract method 0xebeafd77. -// -// Solidity: function ValidationTest(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactorSession) ValidationTest(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidationTest(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) -} - // ValidationBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Validation contract. type ValidationBroadcastHashIterator struct { Event *ValidationBroadcastHash // Event containing the contract specifics and raw log diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index c75d7c9..7f56f9c 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -102,8 +102,8 @@ func Launch(setup config.Setup) { }) shell.AddCmd(&ishell.Cmd{ - Name: "latestBlockSubmitted", - Help: "Queries the validator contract for the last block submitted, arguments: latestBlockSubmitted", + Name: "latestValidationBlock", + Help: "Queries the validator contract for the last block submitted, arguments: latestValidationBlock", Func: func(c *ishell.Context) { c.Println("===============================================================") result, err := validation.LatestBlock(&bind.CallOpts{}) @@ -119,47 +119,12 @@ func Launch(setup config.Setup) { }) shell.AddCmd(&ishell.Cmd{ - Name: "latestBytesSubmitted", - Help: "Queries the validator contract for the last block submitted, arguments: latestBlockSubmitted", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - result, err := validation.LatestBytes(&bind.CallOpts{}) - if err != nil { - fmt.Printf("Error: %s", err) - return - } - c.Println("Last Bytes Submitted:") - c.Printf("0x%x\n", result) - - c.Println("===============================================================") - }, - }) - - // Get block N and spew out the RLP encoded block - shell.AddCmd(&ishell.Cmd{ - Name: "rlpBlock", - Help: "Returns RLP encoded block header, arguments: rlpBlock [integer]", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - if len(c.Args) == 0 { - c.Println("Input argument required, e.g.: rlpBlock 10") - } else if len(c.Args) > 1 { - c.Println("Only enter single argument") - } else { - c.Println("RLP encode block: " + c.Args[0]) - rlpEncodeBlock(client, c.Args[0]) - } - c.Println("===============================================================") - }, - }) - - shell.AddCmd(&ishell.Cmd{ - Name: "submitRlpBlock", - Help: "Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract, arguments: submitRlpBlock [integer]", + Name: "submitValidationBlock", + Help: "Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract, arguments: submitValidationBlock [integer]", Func: func(c *ishell.Context) { c.Println("===============================================================") if len(c.Args) == 0 { - c.Println("Choose a block") + c.Println("Select a block") } else if len(c.Args) > 1 { c.Println("Too many arguments entered.") } else { @@ -176,37 +141,6 @@ func Launch(setup config.Setup) { }, }) - shell.AddCmd(&ishell.Cmd{ - Name: "validationTest", - Help: "Gets the latestBlockHash updates the latestBlockSubmitted, arguments: validationTest [integer]", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - if len(c.Args) == 0 { - c.Println("Choose a block") - } else if len(c.Args) > 1 { - c.Println("Too many arguments entered.") - } else { - c.Println("RLP encode block: " + c.Args[0]) - encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) - // encodedBlock, _, _ := calculateRlpEncoding(client, c.Args[0]) - - // Fiddle around because otherwise the formatting is wrong - // encodedStr := hex.EncodeToString(encodedBlock) - // encodedHex, _ := hex.DecodeString(encodedStr) - - // Submit to the validation contract - res, err := validation.ValidationTest(auth, encodedBlock, prefixBlock, prefixExtra) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) - - } - c.Println("===============================================================") - }, - }) - // run shell shell.Run() } diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 372c52f..5e7a97d 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -63,36 +63,6 @@ func getBlock(client *ethclient.Client, block string) { fmt.Println(string(b)) } -// func rlpEncodeBlock(client *rpc.Client, block string) { -func rlpEncodeBlock(client *ethclient.Client, block string) { - var blockHeader Header - blockNum := new(big.Int) - blockNum.SetString(block, 10) - - lastBlock, err := client.HeaderByNumber(context.Background(), blockNum) - if err != nil { - fmt.Println("can't get requested block:", err) - return - } - - // Marshal into a JSON - b, err := json.MarshalIndent(lastBlock, "", " ") - if err != nil { - fmt.Printf("Error: %s", err) - return - } - err = json.Unmarshal([]byte(b), &blockHeader) - if err != nil { - fmt.Printf("Error: %s", err) - return - } - - // fmt.Printf("%+v\n", blockHeader) - blockInterface := GenerateInterface(blockHeader) - encodedBlock := EncodeBlock(blockInterface) - fmt.Printf("%+x\n", encodedBlock) -} - // func calculateRlpEncoding(client *ethclient.Client, block string) { func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []byte, prefixBlock []byte, prefixExtra []byte) { var blockHeader Header @@ -147,7 +117,6 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by func GenerateInterface(blockHeader Header) (rest interface{}) { blockInterface := []interface{}{} s := reflect.ValueOf(&blockHeader).Elem() - // fmt.Println(s) // Append items into the interface for i := 0; i < s.NumField(); i++ { @@ -162,9 +131,6 @@ func GenerateInterface(blockHeader Header) (rest interface{}) { } element, _ := hex.DecodeString(f) - // fmt.Printf("%+v\n", s.Field(i)) - // fmt.Printf("%+x\n", f) - // fmt.Printf("%+x\n", element) blockInterface = append(blockInterface, element) } diff --git a/package.json b/package.json index 78b227e..3700a49 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "web3-utils": "^1.0.0-beta.33" }, "scripts": { + "clean": "rm -r ./build/contracts/*", "testrpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", "deploy": "truffle deploy", diff --git a/test/test.js b/test/test.js deleted file mode 100644 index 9feb8eb..0000000 --- a/test/test.js +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Util = require('ethereumjs-util'); -const Web3 = require('web3'); -const Web3Utils = require('web3-utils'); -const Web3Abi = require('web3-eth-abi'); -const Web3Accounts = require('web3-eth-accounts'); -const rlp = require('rlp'); - -const Validation = artifacts.require("Validation"); -const Recover = artifacts.require("Recover"); - -const web3 = new Web3(); - -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); - -function hexToBytes(hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; -} - -function bytesToHex(bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(""); -} - -contract.only('test.js', (accounts) => { - const blockNum = 8 - const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); - - const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); - - const ionAbi = [{"constant":true,"inputs":[],"name":"LatestBytes","outputs":[{"name":"_latestBytes","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidationTest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}]; - const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; - const genHash = "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28"; - - - // Here the block header is signed off chain but by a whitelisted validator - it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { - const accounts = web3.eth.accounts; - const signer = accounts[0]; - const ValidationContract = web3.eth.contract(ionAbi); - - // instantiate by address - const validation = ValidationContract.at('0xb9fd43a71c076f02d1dbbf473c389f0eacec559f'); - - // Get a single block - const block = web3.eth.getBlock(blockNum); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - // Create new signed hash - const extraBytes = hexToBytes(extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - // Make some changes to the block - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - // Encode and sign the new header - const encodedHeader = '0x' + rlp.encode(header).toString('hex'); - const headerHash = Util.sha3(encodedHeader); - - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - - const sig = Util.ecsign(headerHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); - const addrBuf = Util.pubToAddress(pubKey); - - // const sigTest = Util.toRpcSig(sig.v, sig.r, sig.s); - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig = newSigBytes.toString('hex') + '00'; - if (sig.v==27) { - newSig = newSigBytes.toString('hex') + '00'; - } else { - newSig = newSigBytes.toString('hex') + '01'; - } - - // Append signature to the end of extraData - const sigBytes = hexToBytes(newSig.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + bytesToHex(newExtraDataBytes); - - const newBlockHeader = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - newExtraData, - mixHash, - nonce - ]; - - console.log(newBlockHeader) - console.log(gasUsed) - console.log('0x' + rlp.encode(gasUsed).toString('hex')); - const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); - const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - assert.equal(block.hash, blockHeaderHash); - - // The new prefixes should be calculated off chain - const prefixHeader = '0x0214'; - const prefixExtraData = '0xa0'; - - console.log("Encoded Block Header:\n", encodedBlockHeader); - const ecrecoveryReceipt = await validation.ValidationTest(encodedBlockHeader, prefixHeader, prefixExtraData, {from: signer, gas: 1000000}); - const latestBlockReceipt = await validation.LatestBlock(); - const latestBytesReceipt = await validation.LatestBytes(); - console.log("Expected Block Hash:\n", block.hash); - console.log("Latest Block Hash:\n", latestBlockReceipt); - console.log("latest Bytes:\n", latestBytesReceipt); - // const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; - // const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; - // console.log(block.hash, recoveredBlockHash) - // assert.equal(block.hash, recoveredBlockHash) - // assert.equal(recoveredSignature, signer); - }) - - // Here the block header is signed off chain but by a whitelisted validator - it('Test: Check the latest data...', async () => { - const accounts = web3.eth.accounts; - const signer = accounts[0]; - const ValidationContract = web3.eth.contract(ionAbi); - - // instantiate by address - const validation = ValidationContract.at('0xb9fd43a71c076f02d1dbbf473c389f0eacec559f'); - - // Get a single block - const block = web3.eth.getBlock(blockNum); - - const latestBlockReceipt = await validation.LatestBlock(); - const latestBytesReceipt = await validation.LatestBytes(); - console.log("Expected Block Hash:\n", block.hash); - console.log("Latest Block Hash:\n", latestBlockReceipt); - console.log("latest Bytes:\n", latestBytesReceipt); - }) - -}); \ No newline at end of file From ceec01e6de5b201b5f92c45089dfd9df4d322219 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 10:09:43 +0100 Subject: [PATCH 016/203] Improved the comments on the help functions --- README.md | 19 +++++++++++++++++++ ion-cli/cli/cli.go | 14 +++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a9904c8..daa0415 100644 --- a/README.md +++ b/README.md @@ -123,5 +123,24 @@ User Account: 0x8671e5e08d74f338ee1c462340842346d797afd3 =============================================================== >>> ``` +running help displays the available commands. +``` +>>> help + +Commands: + clear clear the screen + exit exit the program + getBlock use: getBlock [integer] + description: Returns block header specified + getValidators use: getValidators + description: Returns the whitelist of validators from validator contract + help display help + latestBlock use: latestBlock + description: Returns number of latest block mined/sealed + latestValidationBlock use: latestValidationBlock + description: Returns hash of the last block submitted to the validation contract + submitValidationBlock use: submitValidationBlock [integer] + description: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract +``` diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 7f56f9c..5873db6 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -58,7 +58,7 @@ func Launch(setup config.Setup) { // Get the latest block number shell.AddCmd(&ishell.Cmd{ Name: "latestBlock", - Help: "Returns latest block number, arguments: latestBlock", + Help: "use: latestBlock \n\t\t\t\tdescription: Returns number of latest block mined/sealed", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Get latest block number:") @@ -70,7 +70,7 @@ func Launch(setup config.Setup) { // Get block N shell.AddCmd(&ishell.Cmd{ Name: "getBlock", - Help: "Returns a block header, arguments: getBlock [integer]", + Help: "use: getBlock [integer] \n\t\t\t\tdescription: Returns block header specified", Func: func(c *ishell.Context) { c.Println("===============================================================") if len(c.Args) == 0 { @@ -86,7 +86,7 @@ func Launch(setup config.Setup) { shell.AddCmd(&ishell.Cmd{ Name: "getValidators", - Help: "Queries the validator contract for the whitelist of validators, arguments: getValidatiors", + Help: "use: getValidators \n\t\t\t\tdescription: Returns the whitelist of validators from validator contract", Func: func(c *ishell.Context) { c.Println("===============================================================") result, err := validation.GetValidators(&bind.CallOpts{}) @@ -103,7 +103,7 @@ func Launch(setup config.Setup) { shell.AddCmd(&ishell.Cmd{ Name: "latestValidationBlock", - Help: "Queries the validator contract for the last block submitted, arguments: latestValidationBlock", + Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") result, err := validation.LatestBlock(&bind.CallOpts{}) @@ -120,7 +120,7 @@ func Launch(setup config.Setup) { shell.AddCmd(&ishell.Cmd{ Name: "submitValidationBlock", - Help: "Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract, arguments: submitValidationBlock [integer]", + Help: "use: submitValidationBlock [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") if len(c.Args) == 0 { @@ -151,11 +151,11 @@ func printInfo(setup config.Setup) { fmt.Println("Ion Command Line Interface\n") fmt.Println("RPC Client [to]:") fmt.Println("Listening on: " + setup.AddrTo + ":" + setup.PortTo) - fmt.Println("User Account: " + setup.AccountTo) + fmt.Println("user Account: " + setup.AccountTo) fmt.Println("Ion Contract: " + setup.Ion) fmt.Println("\nRPC Client [from]: ") fmt.Println("Listening on: " + setup.AddrFrom + ":" + setup.PortFrom) - fmt.Println("User Account: " + setup.AccountFrom) + fmt.Println("user Account: " + setup.AccountFrom) fmt.Println("===============================================================") } From 47e80f6f35ce47770b3bfe0a5a14b309bffdeb23 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 11:21:27 +0100 Subject: [PATCH 017/203] Cleaned up the initialisation of an ethclient instance and the connection to a specific contract --- ion-cli/cli/cli.go | 32 +------------------------------- ion-cli/config/config.go | 2 +- ion-cli/config/init.go | 32 ++++++++++++++++++++++++++++++++ ion-cli/main.go | 23 ++++++++++++++++++++++- 4 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 ion-cli/config/init.go diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 5873db6..145fb96 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -12,7 +12,6 @@ import ( "github.com/abiosoft/ishell" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ion/ion-cli/Validation" @@ -20,23 +19,10 @@ import ( ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup) { +func Launch(setup config.Setup, client *ethclient.Client, validation *Validation.Validation) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() - // Connect to the RPC Client - client, err := ethclient.Dial("http://" + setup.AddrTo + ":" + setup.PortTo) - if err != nil { - log.Fatalf("could not create RPC client: %v", err) - } - - // Initialise the contract - address := common.HexToAddress(setup.Ion) - validation, err := Validation.NewValidation(address, client) - if err != nil { - log.Fatal(err) - } - // Get a suggested gas price gasPrice, err := client.SuggestGasPrice(context.Background()) if err != nil { @@ -53,8 +39,6 @@ func Launch(setup config.Setup) { auth.GasLimit = uint64(300000) // in units auth.GasPrice = gasPrice - printInfo(setup) - // Get the latest block number shell.AddCmd(&ishell.Cmd{ Name: "latestBlock", @@ -145,20 +129,6 @@ func Launch(setup config.Setup) { shell.Run() } -func printInfo(setup config.Setup) { - // display welcome info. - fmt.Println("===============================================================") - fmt.Println("Ion Command Line Interface\n") - fmt.Println("RPC Client [to]:") - fmt.Println("Listening on: " + setup.AddrTo + ":" + setup.PortTo) - fmt.Println("user Account: " + setup.AccountTo) - fmt.Println("Ion Contract: " + setup.Ion) - fmt.Println("\nRPC Client [from]: ") - fmt.Println("Listening on: " + setup.AddrFrom + ":" + setup.PortFrom) - fmt.Println("user Account: " + setup.AccountFrom) - fmt.Println("===============================================================") -} - func strToHex(input string) (output string) { val, err := strconv.Atoi(input) if err != nil { diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 52c7587..0aaf5d2 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -30,7 +30,7 @@ func ReadSetup(config string) (setup Setup) { err = json.Unmarshal(raw, &setup) - return setup + return } // Takes path to a JSON and returns a string of the contents diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go new file mode 100644 index 0000000..b5772b8 --- /dev/null +++ b/ion-cli/config/init.go @@ -0,0 +1,32 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package config + +import ( + "log" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ion/ion-cli/Validation" +) + +func InitClient(port string, addr string) (clientTo *ethclient.Client) { + // Connect to the RPC Client + clientTo, err := ethclient.Dial("http://" + addr + ":" + port) + if err != nil { + log.Fatalf("could not create RPC client: %v", err) + } + + return +} + +func InitValidationContract(setup Setup, client *ethclient.Client) (validation *Validation.Validation) { + // Initialise the contract + address := common.HexToAddress(setup.Ion) + validation, err := Validation.NewValidation(address, client) + if err != nil { + log.Fatal(err) + } + + return +} diff --git a/ion-cli/main.go b/ion-cli/main.go index ffec2ab..cc65a76 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -19,11 +19,32 @@ func main() { if *configFile != "" { setup := config.ReadSetup(*configFile) + clientTo := config.InitClient(setup.PortTo, setup.AddrTo) + // clientFrom := config.InitClient(setup.PortFrom, setup.AddrFrom) + + validation := config.InitValidationContract(setup, clientTo) + + printInfo(setup) + // Launch the CLI - cli.Launch(setup) + cli.Launch(setup, clientTo, validation) } else { fmt.Print("Error: empty config!\n") os.Exit(3) } } + +func printInfo(setup config.Setup) { + // display welcome info. + fmt.Println("===============================================================") + fmt.Println("Ion Command Line Interface\n") + fmt.Println("RPC Client [to]:") + fmt.Println("Listening on: " + setup.AddrTo + ":" + setup.PortTo) + fmt.Println("user Account: " + setup.AccountTo) + fmt.Println("Ion Contract: " + setup.Ion) + fmt.Println("\nRPC Client [from]: ") + fmt.Println("Listening on: " + setup.AddrFrom + ":" + setup.PortFrom) + fmt.Println("user Account: " + setup.AccountFrom) + fmt.Println("===============================================================") +} From be0f80c6f4656ed1cf891f361b155f5a761c0e45 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 12:05:03 +0100 Subject: [PATCH 018/203] added the unlocked accounts from the PoA network to the testrpc --- ion-cli/config/config_test.go | 2 +- ion-cli/config/test.json | 11 +++++++++++ ion-cli/setup.json | 8 ++++---- package.json | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 ion-cli/config/test.json diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 2d00728..ed1a27f 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -13,7 +13,7 @@ import ( ) func Test_Read_ValidSetupJson(t *testing.T) { - path := findPath() + "../setup.json" + path := findPath() + "./test.json" setup := config.ReadSetup(path) assert.Equal(t, "8501", setup.PortTo) diff --git a/ion-cli/config/test.json b/ion-cli/config/test.json new file mode 100644 index 0000000..0c55e28 --- /dev/null +++ b/ion-cli/config/test.json @@ -0,0 +1,11 @@ +{ + "rpc-addr-to":"127.0.0.1", + "rpc-port-to":"8501", + "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", + "rpc-addr-from":"127.0.0.1", + "rpc-port-from":"8502", + "account-from":"0x8671e5e08d74f338ee1c462340842346d797afd3", + "keystore-from":"../poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3" +} diff --git a/ion-cli/setup.json b/ion-cli/setup.json index 0c55e28..eee8470 100644 --- a/ion-cli/setup.json +++ b/ion-cli/setup.json @@ -1,11 +1,11 @@ { "rpc-addr-to":"127.0.0.1", - "rpc-port-to":"8501", + "rpc-port-to":"8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", "rpc-addr-from":"127.0.0.1", - "rpc-port-from":"8502", - "account-from":"0x8671e5e08d74f338ee1c462340842346d797afd3", - "keystore-from":"../poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3" + "rpc-port-from":"8501", + "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/package.json b/package.json index 3700a49..9ccab81 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ }, "scripts": { "clean": "rm -r ./build/contracts/*", - "testrpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,2000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,2000000' --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", "deploy": "truffle deploy", "test": "truffle test --network development", From d26e2f635d806f676e2d3f969eaf33bdf6709ae3 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 13:36:36 +0100 Subject: [PATCH 019/203] Added second block chain and renamed the validation contract to be inline with go naming standards --- contracts/Validation.sol | 23 +++++++------------ ion-cli/cli/cli.go | 18 +++++++-------- ion-cli/config/init.go | 6 ++--- ion-cli/main.go | 6 ++--- .../validation.go} | 2 +- package.json | 5 ++-- truffle.js | 6 +++++ 7 files changed, 33 insertions(+), 33 deletions(-) rename ion-cli/{Validation/Validation.go => validation/validation.go} (99%) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 1598e6b..9ddc0e2 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -9,7 +9,7 @@ contract Validation { address[] validators; bytes32 prevBlockHash; - bytes someBytes; + bytes32 parentBlockHash; struct BlockHeader { bytes32 prevBlockHash; @@ -50,15 +50,8 @@ contract Validation { } /* - * Returns the latest block submitted - */ - function LatestBytes() public view returns (bytes _latestBytes) { - return someBytes; - } - - /* - * @param header header rlp encoded, with extraData signatures removed - * @param prefixHeader the new prefix for the signed hash header + * @param header header rlp encoded, with extraData signatures removed + * @param prefixHeader the new prefix for the signed hash header * @param prefixExtraData the new prefix for the extraData field */ function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public { @@ -81,7 +74,7 @@ contract Validation { // Extract the real extra data and create the signed hash extractData(extraData, header, length-140, extraData.length); assembly { - let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) + let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) } // Extract the end of the header @@ -128,10 +121,10 @@ contract Validation { } /* - * @param data memory allocation for the data you need to extract - * @param sig array from which the data should be extracted - * @param start index which the data starts within the byte array - * @param length total length of the data to be extracted + * @param data memory allocation for the data you need to extract + * @param sig array from which the data should be extracted + * @param start index which the data starts within the byte array + * @param length total length of the data to be extracted */ function extractData(bytes data, bytes input, uint start, uint length) private pure { for (uint i=0; i 1 { c.Println("Only enter single argument") } else { - getBlock(client, c.Args[0]) + getBlock(clientFrom, c.Args[0]) } c.Println("===============================================================") }, @@ -73,7 +73,7 @@ func Launch(setup config.Setup, client *ethclient.Client, validation *Validation Help: "use: getValidators \n\t\t\t\tdescription: Returns the whitelist of validators from validator contract", Func: func(c *ishell.Context) { c.Println("===============================================================") - result, err := validation.GetValidators(&bind.CallOpts{}) + result, err := Validation.GetValidators(&bind.CallOpts{}) if err != nil { fmt.Printf("Error: %s", err) return @@ -90,7 +90,7 @@ func Launch(setup config.Setup, client *ethclient.Client, validation *Validation Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") - result, err := validation.LatestBlock(&bind.CallOpts{}) + result, err := Validation.LatestBlock(&bind.CallOpts{}) if err != nil { fmt.Printf("Error: %s", err) return @@ -113,8 +113,8 @@ func Launch(setup config.Setup, client *ethclient.Client, validation *Validation c.Println("Too many arguments entered.") } else { c.Println("RLP encode block: " + c.Args[0]) - encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(client, c.Args[0]) - res, err := validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) + encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(clientFrom, c.Args[0]) + res, err := Validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) if err != nil { c.Printf("Error: %s", err) return diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index b5772b8..257f0c5 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ion/ion-cli/Validation" + "github.com/ion/ion-cli/validation" ) func InitClient(port string, addr string) (clientTo *ethclient.Client) { @@ -20,10 +20,10 @@ func InitClient(port string, addr string) (clientTo *ethclient.Client) { return } -func InitValidationContract(setup Setup, client *ethclient.Client) (validation *Validation.Validation) { +func InitValidationContract(setup Setup, client *ethclient.Client) (Validation *validation.Validation) { // Initialise the contract address := common.HexToAddress(setup.Ion) - validation, err := Validation.NewValidation(address, client) + Validation, err := validation.NewValidation(address, client) if err != nil { log.Fatal(err) } diff --git a/ion-cli/main.go b/ion-cli/main.go index cc65a76..c19670e 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -20,14 +20,14 @@ func main() { setup := config.ReadSetup(*configFile) clientTo := config.InitClient(setup.PortTo, setup.AddrTo) - // clientFrom := config.InitClient(setup.PortFrom, setup.AddrFrom) + clientFrom := config.InitClient(setup.PortFrom, setup.AddrFrom) - validation := config.InitValidationContract(setup, clientTo) + Validation := config.InitValidationContract(setup, clientTo) printInfo(setup) // Launch the CLI - cli.Launch(setup, clientTo, validation) + cli.Launch(setup, clientFrom, Validation) } else { fmt.Print("Error: empty config!\n") os.Exit(3) diff --git a/ion-cli/Validation/Validation.go b/ion-cli/validation/validation.go similarity index 99% rename from ion-cli/Validation/Validation.go rename to ion-cli/validation/validation.go index 05fa0a2..449397d 100644 --- a/ion-cli/Validation/Validation.go +++ b/ion-cli/validation/validation.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package Validation +package validation import ( "strings" diff --git a/package.json b/package.json index 9ccab81..9bd5f07 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,10 @@ }, "scripts": { "clean": "rm -r ./build/contracts/*", - "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,2000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,2000000' --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", - "deploy": "truffle deploy", + "deploy": "truffle deploy --network development", + "deploy-poa": "truffle deploy --network poanetwork", "test": "truffle test --network development", "coverage": "solidity-coverage", "lint": "solhint contracts/**/*.sol", diff --git a/truffle.js b/truffle.js index 264bfe3..84cce7f 100644 --- a/truffle.js +++ b/truffle.js @@ -1,6 +1,12 @@ module.exports = { networks: { development: { + host: "localhost", + port: 8545, + network_id: "*", + gas: 4600000 + }, + poanetwork: { host: "localhost", port: 8501, network_id: "*", From d84097e7e228e583f8009bc77d47d9900f81cf3b Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 15:38:22 +0100 Subject: [PATCH 020/203] Now blocks can only be submitted sequentially --- contracts/Validation.sol | 12 ++- ion-cli/setup_single.json | 11 +++ ion-cli/validation/validation.go | 150 +++++++++++++++++++++++++------ package.json | 2 +- 4 files changed, 145 insertions(+), 30 deletions(-) create mode 100644 ion-cli/setup_single.json diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 9ddc0e2..fb7e1d4 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -9,7 +9,6 @@ contract Validation { address[] validators; bytes32 prevBlockHash; - bytes32 parentBlockHash; struct BlockHeader { bytes32 prevBlockHash; @@ -21,6 +20,7 @@ contract Validation { event broadcastSig(address owner); event broadcastHashData(bytes header, bytes parentHash, bytes rootHash); event broadcastHash(bytes32 blockHash); + event broadcastHash2(bytes blockHash); /* * @param _validators list of validators at block 0 @@ -55,6 +55,13 @@ contract Validation { * @param prefixExtraData the new prefix for the extraData field */ function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public { + // Check the parent hash is the same as the previous block submitted + bytes32 _parentBlockHash; + assembly { + _parentBlockHash := mload(add(header, 36)) + } + require(_parentBlockHash==prevBlockHash, "Not child of previous block!"); + uint256 length = header.length; bytes32 blockHash = keccak256(header); @@ -74,7 +81,7 @@ contract Validation { // Extract the real extra data and create the signed hash extractData(extraData, header, length-140, extraData.length); assembly { - let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) + let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) } // Extract the end of the header @@ -95,6 +102,7 @@ contract Validation { } + function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { // Get the lengths sorted because they're needed later... uint256 headerStartLength = headerStart.length; diff --git a/ion-cli/setup_single.json b/ion-cli/setup_single.json new file mode 100644 index 0000000..f568936 --- /dev/null +++ b/ion-cli/setup_single.json @@ -0,0 +1,11 @@ +{ + "rpc-addr-to":"127.0.0.1", + "rpc-port-to":"8501", + "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", + "rpc-addr-from":"127.0.0.1", + "rpc-port-from":"8501", + "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" +} diff --git a/ion-cli/validation/validation.go b/ion-cli/validation/validation.go index 449397d..be83c6e 100644 --- a/ion-cli/validation/validation.go +++ b/ion-cli/validation/validation.go @@ -15,7 +15,7 @@ import ( ) // ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"LatestBytes\",\"outputs\":[{\"name\":\"_latestBytes\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" +const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHash2\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. const ValidationBin = `608060405234801561001057600080fd5b50604051610e8f380380610e8f83398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b8160028160001916905550505050610ce9806101a66000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334174e6c1461007d578063927a32e31461010d5780639db7d9f71461015a578063aae933e41461018d578063d405af3d14610282578063ebeafd77146102ee575b600080fd5b34801561008957600080fd5b506100926103e3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100d25780820151818401526020810190506100b7565b50505050905090810190601f1680156100ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011957600080fd5b5061013c6004803603810190808035600019169060200190929190505050610485565b60405180826000191660001916815260200191505060405180910390f35b34801561016657600080fd5b5061016f6104a3565b60405180826000191660001916815260200191505060405180910390f35b34801561019957600080fd5b50610280600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ad565b005b34801561028e57600080fd5b5061029761079f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102da5780820151818401526020810190506102bf565b505050509050019250505060405180910390f35b3480156102fa57600080fd5b506103e1600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061082d565b005b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561047b5780601f106104505761010080835404028352916020019161047b565b820191906000526020600020905b81548152906001019060200180831161045e57829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156104f557805182526020820191506020810190506020830392506104d0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156105995781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105d05781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156106075781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561063e5781602001602082028038833980820191505090505b50935061064f878d60008a516109e9565b600260218801600260208e016004610bb8fa50610672868d608c8c0389516109e9565b600160208701600160208d016004610bb8fa50610695848d602a8c0387516109e9565b6106a0878786610aa4565b9250826040518082805190602001908083835b6020831015156106d857805182526020820191506020810190506020830392506106b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150610717858d606b8c0388516109e9565b6107218286610b50565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561082357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116107d9575b5050505050905090565b60008060608060608088519550886040518082805190602001908083835b602083101515610870578051825260208201915060208101905060208303925061084b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020945088600390805190602001906108b5929190610c18565b5084600281600019169055507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018560405180826000191660001916815260200191505060405180910390a1608d86036040519080825280601f01601f1916602001820160405280156109365781602001602082028038833980820191505090505b509350601f6040519080825280601f01601f19166020018201604052801561096d5781602001602082028038833980820191505090505b50925060416040519080825280601f01601f1916602001820160405280156109a45781602001602082028038833980820191505090505b509150602a6040519080825280601f01601f1916602001820160405280156109db5781602001602082028038833980820191505090505b509050505050505050505050565b60008090505b81811015610a9d5783818401815181101515610a0757fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028582815181101515610a6057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506109ef565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f191660200182016040528015610b0b5781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610b6657600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610b9157601b810190505b601b8160ff161480610ba65750601c8160ff16145b1515610bb157600080fd5b610bbd86828585610bc8565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610c0b57600080fd5b8092505050949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c5957805160ff1916838001178555610c87565b82800160010185558215610c87579182015b82811115610c86578251825591602001919060010190610c6b565b5b509050610c949190610c98565b5090565b610cba91905b80821115610cb6576000816000905550600101610c9e565b5090565b905600a165627a7a7230582009a70c54afc4fb7f922da0ee026dacb18eb44755eb2bc1e8b12424c23f2239b90029` @@ -227,32 +227,6 @@ func (_Validation *ValidationCallerSession) LatestBlock() ([32]byte, error) { return _Validation.Contract.LatestBlock(&_Validation.CallOpts) } -// LatestBytes is a free data retrieval call binding the contract method 0x34174e6c. -// -// Solidity: function LatestBytes() constant returns(_latestBytes bytes) -func (_Validation *ValidationCaller) LatestBytes(opts *bind.CallOpts) ([]byte, error) { - var ( - ret0 = new([]byte) - ) - out := ret0 - err := _Validation.contract.Call(opts, out, "LatestBytes") - return *ret0, err -} - -// LatestBytes is a free data retrieval call binding the contract method 0x34174e6c. -// -// Solidity: function LatestBytes() constant returns(_latestBytes bytes) -func (_Validation *ValidationSession) LatestBytes() ([]byte, error) { - return _Validation.Contract.LatestBytes(&_Validation.CallOpts) -} - -// LatestBytes is a free data retrieval call binding the contract method 0x34174e6c. -// -// Solidity: function LatestBytes() constant returns(_latestBytes bytes) -func (_Validation *ValidationCallerSession) LatestBytes() ([]byte, error) { - return _Validation.Contract.LatestBytes(&_Validation.CallOpts) -} - // MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. // // Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) @@ -422,6 +396,128 @@ func (_Validation *ValidationFilterer) WatchBroadcastHash(opts *bind.WatchOpts, }), nil } +// ValidationBroadcastHash2Iterator is returned from FilterBroadcastHash2 and is used to iterate over the raw logs and unpacked data for BroadcastHash2 events raised by the Validation contract. +type ValidationBroadcastHash2Iterator struct { + Event *ValidationBroadcastHash2 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ValidationBroadcastHash2Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastHash2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ValidationBroadcastHash2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ValidationBroadcastHash2Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ValidationBroadcastHash2Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ValidationBroadcastHash2 represents a BroadcastHash2 event raised by the Validation contract. +type ValidationBroadcastHash2 struct { + BlockHash []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBroadcastHash2 is a free log retrieval operation binding the contract event 0xd5796acb84f214e8b630fe40f93fdbf75c0a53b553e23be97a99e61152f174d2. +// +// Solidity: event broadcastHash2(blockHash bytes) +func (_Validation *ValidationFilterer) FilterBroadcastHash2(opts *bind.FilterOpts) (*ValidationBroadcastHash2Iterator, error) { + + logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastHash2") + if err != nil { + return nil, err + } + return &ValidationBroadcastHash2Iterator{contract: _Validation.contract, event: "broadcastHash2", logs: logs, sub: sub}, nil +} + +// WatchBroadcastHash2 is a free log subscription operation binding the contract event 0xd5796acb84f214e8b630fe40f93fdbf75c0a53b553e23be97a99e61152f174d2. +// +// Solidity: event broadcastHash2(blockHash bytes) +func (_Validation *ValidationFilterer) WatchBroadcastHash2(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastHash2) (event.Subscription, error) { + + logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastHash2") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ValidationBroadcastHash2) + if err := _Validation.contract.UnpackLog(event, "broadcastHash2", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + // ValidationBroadcastHashDataIterator is returned from FilterBroadcastHashData and is used to iterate over the raw logs and unpacked data for BroadcastHashData events raised by the Validation contract. type ValidationBroadcastHashDataIterator struct { Event *ValidationBroadcastHashData // Event containing the contract specifics and raw log diff --git a/package.json b/package.json index 9bd5f07..0d3d889 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,6 @@ "lint": "solhint contracts/**/*.sol", "genbin": "solc --overwrite --bin ./contracts/* -o abi", "genabi": "solc --overwrite --abi ./contracts/* -o abi", - "abigen": "abigen --bin=abi/Validation.bin --abi=abi/Validation.abi --pkg=Validation --out=Validation.go" + "abigen": "abigen --bin=abi/Validation.bin --abi=abi/Validation.abi --pkg=validation --out=validation.go" } } From 3befc52c03e7be371d0b0f8834dbda83f30c014b Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 27 Jun 2018 16:42:16 +0100 Subject: [PATCH 021/203] Puts all data in a nice struct and returns submitted blocks --- contracts/Validation.sol | 33 ++++++++++--- ion-cli/cli/cli.go | 21 ++++++++ ion-cli/validation/validation.go | 85 +++++++++++++++++++++++++------- 3 files changed, 114 insertions(+), 25 deletions(-) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index fb7e1d4..f38aa66 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -8,13 +8,15 @@ contract Validation { address Owner; address[] validators; - bytes32 prevBlockHash; + uint256 blockHeight; + bytes32 blockHash; struct BlockHeader { + bytes32 blockHash; bytes32 prevBlockHash; } - mapping (bytes32 => BlockHeader) public m_blockheaders; + mapping (uint256 => BlockHeader) public m_blockheaders; mapping (address => bool) m_validators; event broadcastSig(address owner); @@ -25,14 +27,16 @@ contract Validation { /* * @param _validators list of validators at block 0 */ - constructor (address[] _validators, bytes32 genHash) public { + constructor (address[] _validators, bytes32 genesisHash) public { Owner = msg.sender; for (uint i = 0; i < _validators.length; i++) { validators.push(_validators[i]); m_validators[_validators[i]] = true; } - prevBlockHash = genHash; + blockHash = genesisHash; + m_blockheaders[0].blockHash = genesisHash; + } /* @@ -46,7 +50,16 @@ contract Validation { * Returns the latest block submitted */ function LatestBlock() public view returns (bytes32 _latestBlock) { - return prevBlockHash; + return blockHash; + } + + /* + * Returns the latest block submitted + */ + function GetBlock(uint256 blockNumber) public view returns (bytes32 _blockHash, bytes32 _prevBlockHash, uint256 _blockHeight) { + _blockHash = m_blockheaders[blockNumber].blockHash; + _prevBlockHash = m_blockheaders[blockNumber].prevBlockHash; + _blockHeight = blockHeight; } /* @@ -60,10 +73,10 @@ contract Validation { assembly { _parentBlockHash := mload(add(header, 36)) } - require(_parentBlockHash==prevBlockHash, "Not child of previous block!"); + require(_parentBlockHash==blockHash, "Not child of previous block!"); uint256 length = header.length; - bytes32 blockHash = keccak256(header); + bytes32 _blockHash = keccak256(header); emit broadcastHash(blockHash); @@ -96,7 +109,11 @@ contract Validation { address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); require(m_validators[sig_addr]==true, "Signer not a validator!"); - prevBlockHash = blockHash; + // Append the new block to the struct + blockHash = _blockHash; + blockHeight++; + m_blockheaders[blockHeight].blockHash = _blockHash; + m_blockheaders[blockHeight].prevBlockHash = _parentBlockHash; emit broadcastSig(sig_addr); diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 6a5935e..af4cabd 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -102,6 +102,27 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *valida }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "getValidationBlock", + Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + blockNum := new(big.Int) + blockNum.SetString(c.Args[0], 10) + result, err := Validation.GetBlock(&bind.CallOpts{}, blockNum) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + c.Println("Last Block Submitted:") + c.Printf("Block:\n\t%x\n", result.BlockHeight) + c.Printf("Hash:\n\t0x%x\n", result.BlockHash) + c.Printf("Parent Hash:\n\t0x%x\n", result.PrevBlockHash) + + c.Println("===============================================================") + }, + }) + shell.AddCmd(&ishell.Cmd{ Name: "submitValidationBlock", Help: "use: submitValidationBlock [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", diff --git a/ion-cli/validation/validation.go b/ion-cli/validation/validation.go index be83c6e..70ea041 100644 --- a/ion-cli/validation/validation.go +++ b/ion-cli/validation/validation.go @@ -4,6 +4,7 @@ package validation import ( + "math/big" "strings" ethereum "github.com/ethereum/go-ethereum" @@ -15,18 +16,18 @@ import ( ) // ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHash2\",\"type\":\"event\"}]" +const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GetBlock\",\"outputs\":[{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"_blockHeight\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genesisHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHash2\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. const ValidationBin = `608060405234801561001057600080fd5b50604051610e8f380380610e8f83398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b8160028160001916905550505050610ce9806101a66000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334174e6c1461007d578063927a32e31461010d5780639db7d9f71461015a578063aae933e41461018d578063d405af3d14610282578063ebeafd77146102ee575b600080fd5b34801561008957600080fd5b506100926103e3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100d25780820151818401526020810190506100b7565b50505050905090810190601f1680156100ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011957600080fd5b5061013c6004803603810190808035600019169060200190929190505050610485565b60405180826000191660001916815260200191505060405180910390f35b34801561016657600080fd5b5061016f6104a3565b60405180826000191660001916815260200191505060405180910390f35b34801561019957600080fd5b50610280600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ad565b005b34801561028e57600080fd5b5061029761079f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102da5780820151818401526020810190506102bf565b505050509050019250505060405180910390f35b3480156102fa57600080fd5b506103e1600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061082d565b005b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561047b5780601f106104505761010080835404028352916020019161047b565b820191906000526020600020905b81548152906001019060200180831161045e57829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156104f557805182526020820191506020810190506020830392506104d0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156105995781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105d05781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156106075781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561063e5781602001602082028038833980820191505090505b50935061064f878d60008a516109e9565b600260218801600260208e016004610bb8fa50610672868d608c8c0389516109e9565b600160208701600160208d016004610bb8fa50610695848d602a8c0387516109e9565b6106a0878786610aa4565b9250826040518082805190602001908083835b6020831015156106d857805182526020820191506020810190506020830392506106b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150610717858d606b8c0388516109e9565b6107218286610b50565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561082357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116107d9575b5050505050905090565b60008060608060608088519550886040518082805190602001908083835b602083101515610870578051825260208201915060208101905060208303925061084b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020945088600390805190602001906108b5929190610c18565b5084600281600019169055507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018560405180826000191660001916815260200191505060405180910390a1608d86036040519080825280601f01601f1916602001820160405280156109365781602001602082028038833980820191505090505b509350601f6040519080825280601f01601f19166020018201604052801561096d5781602001602082028038833980820191505090505b50925060416040519080825280601f01601f1916602001820160405280156109a45781602001602082028038833980820191505090505b509150602a6040519080825280601f01601f1916602001820160405280156109db5781602001602082028038833980820191505090505b509050505050505050505050565b60008090505b81811015610a9d5783818401815181101515610a0757fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028582815181101515610a6057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506109ef565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f191660200182016040528015610b0b5781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610b6657600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610b9157601b810190505b601b8160ff161480610ba65750601c8160ff16145b1515610bb157600080fd5b610bbd86828585610bc8565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610c0b57600080fd5b8092505050949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c5957805160ff1916838001178555610c87565b82800160010185558215610c87579182015b82811115610c86578251825591602001919060010190610c6b565b5b509050610c949190610c98565b5090565b610cba91905b80821115610cb6576000816000905550600101610c9e565b5090565b905600a165627a7a7230582009a70c54afc4fb7f922da0ee026dacb18eb44755eb2bc1e8b12424c23f2239b90029` // DeployValidation deploys a new Ethereum contract, binding an instance of Validation to it. -func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address, genHash [32]byte) (common.Address, *types.Transaction, *Validation, error) { +func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address, genesisHash [32]byte) (common.Address, *types.Transaction, *Validation, error) { parsed, err := abi.JSON(strings.NewReader(ValidationABI)) if err != nil { return common.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ValidationBin), backend, _validators, genHash) + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ValidationBin), backend, _validators, genesisHash) if err != nil { return common.Address{}, nil, nil, err } @@ -175,6 +176,46 @@ func (_Validation *ValidationTransactorRaw) Transact(opts *bind.TransactOpts, me return _Validation.Contract.contract.Transact(opts, method, params...) } +// GetBlock is a free data retrieval call binding the contract method 0x40ce4b6c. +// +// Solidity: function GetBlock(blockNumber uint256) constant returns(_blockHash bytes32, _prevBlockHash bytes32, _blockHeight uint256) +func (_Validation *ValidationCaller) GetBlock(opts *bind.CallOpts, blockNumber *big.Int) (struct { + BlockHash [32]byte + PrevBlockHash [32]byte + BlockHeight *big.Int +}, error) { + ret := new(struct { + BlockHash [32]byte + PrevBlockHash [32]byte + BlockHeight *big.Int + }) + out := ret + err := _Validation.contract.Call(opts, out, "GetBlock", blockNumber) + return *ret, err +} + +// GetBlock is a free data retrieval call binding the contract method 0x40ce4b6c. +// +// Solidity: function GetBlock(blockNumber uint256) constant returns(_blockHash bytes32, _prevBlockHash bytes32, _blockHeight uint256) +func (_Validation *ValidationSession) GetBlock(blockNumber *big.Int) (struct { + BlockHash [32]byte + PrevBlockHash [32]byte + BlockHeight *big.Int +}, error) { + return _Validation.Contract.GetBlock(&_Validation.CallOpts, blockNumber) +} + +// GetBlock is a free data retrieval call binding the contract method 0x40ce4b6c. +// +// Solidity: function GetBlock(blockNumber uint256) constant returns(_blockHash bytes32, _prevBlockHash bytes32, _blockHeight uint256) +func (_Validation *ValidationCallerSession) GetBlock(blockNumber *big.Int) (struct { + BlockHash [32]byte + PrevBlockHash [32]byte + BlockHeight *big.Int +}, error) { + return _Validation.Contract.GetBlock(&_Validation.CallOpts, blockNumber) +} + // GetValidators is a free data retrieval call binding the contract method 0xd405af3d. // // Solidity: function GetValidators() constant returns(_validators address[]) @@ -227,29 +268,39 @@ func (_Validation *ValidationCallerSession) LatestBlock() ([32]byte, error) { return _Validation.Contract.LatestBlock(&_Validation.CallOpts) } -// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// MBlockheaders is a free data retrieval call binding the contract method 0xc4cf3ed6. // -// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) -func (_Validation *ValidationCaller) MBlockheaders(opts *bind.CallOpts, arg0 [32]byte) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 +// Solidity: function m_blockheaders( uint256) constant returns(blockHash bytes32, prevBlockHash bytes32) +func (_Validation *ValidationCaller) MBlockheaders(opts *bind.CallOpts, arg0 *big.Int) (struct { + BlockHash [32]byte + PrevBlockHash [32]byte +}, error) { + ret := new(struct { + BlockHash [32]byte + PrevBlockHash [32]byte + }) + out := ret err := _Validation.contract.Call(opts, out, "m_blockheaders", arg0) - return *ret0, err + return *ret, err } -// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// MBlockheaders is a free data retrieval call binding the contract method 0xc4cf3ed6. // -// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) -func (_Validation *ValidationSession) MBlockheaders(arg0 [32]byte) ([32]byte, error) { +// Solidity: function m_blockheaders( uint256) constant returns(blockHash bytes32, prevBlockHash bytes32) +func (_Validation *ValidationSession) MBlockheaders(arg0 *big.Int) (struct { + BlockHash [32]byte + PrevBlockHash [32]byte +}, error) { return _Validation.Contract.MBlockheaders(&_Validation.CallOpts, arg0) } -// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// MBlockheaders is a free data retrieval call binding the contract method 0xc4cf3ed6. // -// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32) -func (_Validation *ValidationCallerSession) MBlockheaders(arg0 [32]byte) ([32]byte, error) { +// Solidity: function m_blockheaders( uint256) constant returns(blockHash bytes32, prevBlockHash bytes32) +func (_Validation *ValidationCallerSession) MBlockheaders(arg0 *big.Int) (struct { + BlockHash [32]byte + PrevBlockHash [32]byte +}, error) { return _Validation.Contract.MBlockheaders(&_Validation.CallOpts, arg0) } From 27ee774e59e53a6f3dd84110b0170426905c10fe Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 11:21:52 +0100 Subject: [PATCH 022/203] First draft of the tutorial has been added --- README.md | 32 +++++++++++++++++++------------- contracts/Validation.sol | 2 +- package.json | 4 ++-- test/validation.js | 38 +++++++++++++++++++++----------------- truffle.js | 2 +- 5 files changed, 44 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index daa0415..5105f49 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,23 @@ The Ion Interoperability Protocol provides mechanisms to perform atomic swaps an across multiple turing-complete blockchains. ## Block Validation Scheme -Block validation scheme is a set of smart contract which aim to be able to ensure that block headers submitted to the contract are sealed by an approved partie(s). The motivation behind this is to update the state of a Clique PoA or Istanbul PBFT chain onto any other blockchain. To do this we first need to know which blocks are valid - dependent on the definition of a valid by the underlying consensus algorithm. +Block validation scheme is a set of smart contracts which ensures that block headers submitted to the contract are mined/sealed by an approved partie(s). The motivation behind this is to update the state of a blockchain onto another blockchain. To do this we first need to know which blocks are valid - dependent on the definition of a valid by the underlying consensus algorithm. As deterministic finality is a requirement we seek Clique PoA and Istanbul PBFT consensus is to be used on the chain from which the state is being taken. -At this stage a Clique PoA chain is launched and then the block headers updated to the smart contract which is deployed on itself. However in the near future this will be extended to update the Clique header onto any other chain. For a full description and roadmap of the project please refer to the Clearmatics [Ion-Stage-2 Wiki](https://github.com/clearmatics/ion/wiki/Ion-Stage-2---Proposal#validation). +For a full description and roadmap of the project please refer to the Clearmatics [Ion-Stage-2 Wiki](https://github.com/clearmatics/ion/wiki/Ion-Stage-2---Proposal#validation). ## Running the Project -This project contains a number of components: +A Clique PoA chain is launched and then the block headers are taken and updated to the validation contract which is deployed on a ganache chain. However in the javascript tests the contract is deployed on the PoA chain itself for sake of simplicity, this has no bearing on the functionality of the project. + +Running the project requires initialisation of the following components: * Validation smart contract and tests - * Clique _proof of authority_ test network - * Command Line Interface for interacting with the smart contract + * Two separate blockchain: Clique _proof of authority_ network, Ganache test network + * Golang Ion CLI used to interact with the smart contract(s) -In order to use the smart contracts and run the tests it is necessary to first initialise the test network. +In order to use the smart contracts and run the tests it is necessary to first initialise the test networks. -***Note:*** that as the contract searches for specific parts of the block header that only exist in Clique, Ganache or Ethash chains cannot be used. +***Note:*** that as the contract searches for specific parts of the block header that only exist in Clique and IBFT, Ganache or Ethash chains cannot be used for the _root_ blockchain from which headers are extracted. -### Initialise the Test Network +### Initialise Clique PoA Blockchain The instructions are based on the tutorial of [Salanfe](https://hackernoon.com/setup-your-own-private-proof-of-authority-ethereum-network-with-geth-9a0a3750cda8) but has the more complicated parts already initialised. First install an instance of [geth](https://geth.ethereum.org/downloads/) and clone the repo. @@ -89,7 +91,7 @@ $ geth attach node2/geth.ipc After launching the network, from the root of the repository: ``` $ npm install -$ truffle test +$ npm run test ``` ### Ion Command Line Interface @@ -100,15 +102,19 @@ In its current form the Ion CLI allows the user to connect to two separate block #### Running the CLI As mentioned in the project description this simple implementation of the validation contract is active only on a single blockchain, however the CLI is simulating the passing of the headers to and from as if it were between separate chains. -Having followed the instructions on how to setup a Clique blockchain, which is hosted on `127.0.0.1:8502`, and running another chain on `127.0.0.1:8501` we can attach the CLI. +Having followed the instructions on how to setup a Clique blockchain, which is hosted on `127.0.0.1:8501`, we run a ganache-cli in another terminal on `127.0.0.1:8545`, +``` +$ npm run testrpc +``` +Following this we can attach to the Ion Command Line Interface, ``` $ cd /path/to/validation/src $ make build ``` -Assuming a successful build the tool can be run, +Assuming a successful build we must create a setup file which contains the connection of the separate blockchains, user accounts, account keystores, and the address of the deployed validation contract. Change the default values in the example setup.json then run the `ion-cli` poiinting to the modified setup file. ``` -$ ./ion-cli [/path/to/setup.json] +$ ./ion-cli -config [/path/to/setup.json] =============================================================== Ion Command Line Interface @@ -118,7 +124,7 @@ User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d Ion Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f RPC Client [from]: -Listening on: 127.0.0.1:8502 +Listening on: 127.0.0.1:8545 User Account: 0x8671e5e08d74f338ee1c462340842346d797afd3 =============================================================== >>> diff --git a/contracts/Validation.sol b/contracts/Validation.sol index f38aa66..aff74f5 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -78,7 +78,7 @@ contract Validation { uint256 length = header.length; bytes32 _blockHash = keccak256(header); - emit broadcastHash(blockHash); + emit broadcastHash(_blockHash); bytes memory headerStart = new bytes(length - 141); bytes memory extraData = new bytes(31); diff --git a/package.json b/package.json index 0d3d889..383bdae 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", "deploy": "truffle deploy --network development", - "deploy-poa": "truffle deploy --network poanetwork", - "test": "truffle test --network development", + "depclique": "truffle deploy --network clique", + "test": "truffle test --network clique", "coverage": "solidity-coverage", "lint": "solhint contracts/**/*.sol", "genbin": "solc --overwrite --bin ./contracts/* -o abi", diff --git a/test/validation.js b/test/validation.js index b18fc1e..0dd575a 100644 --- a/test/validation.js +++ b/test/validation.js @@ -29,18 +29,20 @@ function bytesToHex(bytes) { return hex.join(""); } -contract('validation.js', (accounts) => { +contract.only('validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); + const blockNum = 1; + const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; const genHash = "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28"; it('Test: GetValidators()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = accounts[0]; + const signer = validators[1]; const validatorsReceipt = await validation.GetValidators(); assert.equal(validators[0], validatorsReceipt[0]) @@ -50,10 +52,10 @@ contract('validation.js', (accounts) => { it('Test: Authentic Submission Happy Path - ValidateBlock()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = accounts[0]; + const signer = validators[1]; // Get a single block - const block = web3.eth.getBlock(10); + const block = web3.eth.getBlock(1); // Decompose the values in the block to hash const parentHash = block.parentHash; @@ -129,7 +131,7 @@ contract('validation.js', (accounts) => { const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; assert.equal(block.hash, recoveredBlockHash) - assert.equal(recoveredSignature, signer); + assert.notEqual(validators.indexOf(recoveredSignature), -1); }) @@ -137,10 +139,10 @@ contract('validation.js', (accounts) => { it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = accounts[0]; + const signer = validators[1]; // Get a single block - const block = web3.eth.getBlock(10); + const block = web3.eth.getBlock(1); // Decompose the values in the block to hash const parentHash = block.parentHash; @@ -188,7 +190,7 @@ contract('validation.js', (accounts) => { const encodedHeader = '0x' + rlp.encode(header).toString('hex'); const headerHash = Util.sha3(encodedHeader); - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + const privateKey = Buffer.from('d18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083', 'hex') const sig = Util.ecsign(headerHash, privateKey) if (this._chainId > 0) { @@ -239,18 +241,17 @@ contract('validation.js', (accounts) => { const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; - console.log(block.hash, recoveredBlockHash) assert.equal(block.hash, recoveredBlockHash) assert.equal(recoveredSignature, signer); }) - it('Test: Inauthentic Block Submission Off-Chain - ValidateBlock()', async () => { + it('Test: Inauthentic Block Submission - ValidateBlock()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = accounts[0]; + const signer = validators[1]; // Get a single block - const block = web3.eth.getBlock(10); + const block = web3.eth.getBlock(1); // Decompose the values in the block to hash const parentHash = block.parentHash; @@ -299,7 +300,7 @@ contract('validation.js', (accounts) => { const encodedHeader = '0x' + rlp.encode(header).toString('hex'); const headerHash = Util.sha3(encodedHeader); - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + const privateKey = Buffer.from('d18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083', 'hex') const sig = Util.ecsign(headerHash, privateKey) if (this._chainId > 0) { @@ -308,11 +309,14 @@ contract('validation.js', (accounts) => { const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); const addrBuf = Util.pubToAddress(pubKey); - const addr = Util.bufferToHex(addrBuf); const vPseudo = new Buffer(0); const newSigBytes = Buffer.concat([sig.r, sig.s]); - const newSig = newSigBytes.toString('hex') + '00'; + let newSig; + if (sig.v==28) + newSig = newSigBytes.toString('hex') + '00'; + else (sig.v==27) + newSig = newSigBytes.toString('hex') + '01'; // Append signature to the end of extraData const sigBytes = hexToBytes(newSig.toString('hex')); @@ -353,10 +357,10 @@ contract('validation.js', (accounts) => { it('Test: Authentic Block Unkown Validator Submission - ValidateBlock()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = accounts[0]; + const signer = validators[1]; // Get a single block - const block = web3.eth.getBlock(10); + const block = web3.eth.getBlock(1); // Decompose the values in the block to hash const parentHash = block.parentHash; diff --git a/truffle.js b/truffle.js index 84cce7f..28c2fb4 100644 --- a/truffle.js +++ b/truffle.js @@ -6,7 +6,7 @@ module.exports = { network_id: "*", gas: 4600000 }, - poanetwork: { + clique: { host: "localhost", port: 8501, network_id: "*", From 9524d3bf78c92af2bd4e198f77bece8ef1717df5 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 11:51:00 +0100 Subject: [PATCH 023/203] Improved the readme --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5105f49..80a888f 100644 --- a/README.md +++ b/README.md @@ -38,22 +38,25 @@ $ tree -L 1 Which hopefully returns this: ``` -├── abi -├── build +├── CODE_OF_CONDUCT.md ├── contracts +├── CONTRIBUTING.md +├── docs +├── ion-cli +├── LICENSE ├── migrations ├── package.json +├── package-lock.json ├── poa-network ├── README.md -├── src ├── test └── truffle.js ``` #### Initialise Nodes -Network files are found in the `/path/to/validation/poa-network` directory. Enter the poa-network directory and initialise the two nodes which will be sealing blocks: +Network files are found in the `/path/to/ion/poa-network` directory. Enter the poa-network directory and initialise the two nodes which will be sealing blocks: ``` -$ cd /path/to/validation/poa-network +$ cd /path/to/ion/poa-network $ geth --datadir node1/ init genesis.json $ geth --datadir node2/ init genesis.json ``` @@ -102,9 +105,10 @@ In its current form the Ion CLI allows the user to connect to two separate block #### Running the CLI As mentioned in the project description this simple implementation of the validation contract is active only on a single blockchain, however the CLI is simulating the passing of the headers to and from as if it were between separate chains. -Having followed the instructions on how to setup a Clique blockchain, which is hosted on `127.0.0.1:8501`, we run a ganache-cli in another terminal on `127.0.0.1:8545`, +Having followed the instructions on how to setup a Clique blockchain, which is hosted on `127.0.0.1:8501`, we run a ganache-cli in another terminal on `127.0.0.1:8545` and deploy the contract to the ganache blockchain, ``` $ npm run testrpc +$ npm run deploy ``` Following this we can attach to the Ion Command Line Interface, From ee959474dfd7a122092c05a57d8043dd03116c5c Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 15:44:05 +0100 Subject: [PATCH 024/203] Created some golang tests for the contract :) --- contracts/Validation.sol | 3 +- ion-cli/cli/cli_test.go | 11 +- ion-cli/cli/rpc.go | 34 +- ion-cli/cli/rpc_test.go | 47 +- ion-cli/cli/test.json | 11 + ion-cli/validation/validation_test.go | 85 + package-lock.json | 7571 ------------------------- 7 files changed, 166 insertions(+), 7596 deletions(-) create mode 100644 ion-cli/cli/test.json create mode 100644 ion-cli/validation/validation_test.go delete mode 100644 package-lock.json diff --git a/contracts/Validation.sol b/contracts/Validation.sol index aff74f5..a125b4b 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -25,7 +25,8 @@ contract Validation { event broadcastHash2(bytes blockHash); /* - * @param _validators list of validators at block 0 + * @param _validators list of validators at block 0 + * @param _genesisHash genesis block hash */ constructor (address[] _validators, bytes32 genesisHash) public { Owner = msg.sender; diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index 9d81dff..25135bf 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -13,13 +13,18 @@ import ( ) func Test_Read_ValidSetupJson(t *testing.T) { - path := findPath() + "../setup.json" + path := findPath() + "./test.json" setup := config.ReadSetup(path) - assert.Equal(t, "8501", setup.PortTo) + assert.Equal(t, "8545", setup.PortTo) assert.Equal(t, "127.0.0.1", setup.AddrTo) - assert.Equal(t, "8502", setup.PortFrom) + assert.Equal(t, "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.AccountTo) + assert.Equal(t, "../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.KeystoreTo) + assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) + assert.Equal(t, "8501", setup.PortFrom) assert.Equal(t, "127.0.0.1", setup.AddrFrom) + assert.Equal(t, "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.AccountFrom) + assert.Equal(t, "../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.KeystoreFrom) } func findPath() string { diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 5e7a97d..7ca131f 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -97,22 +97,40 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by } // Generate an interface to encode the blockheader without the signature in the extraData - blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] - blockInterface := GenerateInterface(blockHeader) - encodedPrefixBlock := EncodeBlock(blockInterface) - prefixBlock = encodedPrefixBlock[1:3] + prefixBlock = encodeBlock(blockHeader) fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", prefixBlock) // Generate an interface to encode the blockheader without the signature in the extraData - encExtra, _ := hex.DecodeString(blockHeader.Extra[2:]) - encodedExtraData := EncodeBlock(encExtra) - prefixExtra = encodedExtraData[0:1] + prefixExtra = EncodeExtraData(blockHeader) fmt.Printf("\nExtraData Field Prefix:\n%+x\n", prefixExtra) return rlpBlock, prefixBlock, prefixExtra } +// calculate prefix of the entire signed block +func EncodePrefix(blockHeader Header) (prefix []byte) { + blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] + blockInterface := GenerateInterface(blockHeader) + encodedPrefixBlock := encodeBlock(blockInterface) + + return encodedPrefixBlock[1:3] +} + +// calculate prefix of the extraData with the signature +func EncodeExtraData(blockHeader Header) (prefix []byte) { + blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] + encExtra, err := hex.DecodeString(blockHeader.Extra[2:]) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + + encodedExtraData := encodeBlock(encExtra) + + return encodedExtraData[0:1] +} + // Creates an interface for a block func GenerateInterface(blockHeader Header) (rest interface{}) { blockInterface := []interface{}{} @@ -138,7 +156,7 @@ func GenerateInterface(blockHeader Header) (rest interface{}) { } // Encodes a block -func EncodeBlock(blockInterface interface{}) (h []byte) { +func encodeBlock(blockInterface interface{}) (h []byte) { h, _ = rlp.EncodeToBytes(blockInterface) return h diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index 012b8d4..537212b 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -3,31 +3,52 @@ package cli_test import ( + "encoding/hex" "encoding/json" "fmt" "io/ioutil" "testing" "github.com/ion/ion-cli/cli" + "github.com/stretchr/testify/assert" ) -func Test_EncodeBlock(t *testing.T) { +func Test_EncodePrefix(t *testing.T) { + prefixString := "0214" + expectedPrefix, _ := hex.DecodeString(prefixString) + // read a fake block - raw, _ := ioutil.ReadFile("../block.json") + raw, err := ioutil.ReadFile("../block.json") + if err != nil { + fmt.Println("cannot find test block.json file:", err) + return + } + + // Marshall fake block into the Header + var blockHeader cli.Header + json.Unmarshal(raw, &blockHeader) + prefix := cli.EncodePrefix(blockHeader) + + assert.Equal(t, expectedPrefix, prefix) - const expectedRlpHex = "f90256a0b5567eddb3bf1b6d12af53e4f8983ee82684d48ce65afef8aa067bf6c59d801ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0db37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020883fe01c880845b3252dcb861d78301080a846765746887676f312e392e33856c696e75780000000000000000af64d47b7b33960eff2eaedfd6fae84784e47f13c97df41498c81288c72fe63c2d0429d8692d756d1c7ccb84f68e20acc298465de6b841ee34edc2778b8af3ac00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" - const expectedHash = "e65c9896678436a46b106b85cdea91a425e7df7c73128163f66125eefb27fa53" +} + +func Test_EncodeExtraDataPrefix(t *testing.T) { + prefixString := "a0" + expectedPrefix, _ := hex.DecodeString(prefixString) - var marshalledBlock cli.Header - json.Unmarshal(raw, &marshalledBlock) + // read a fake block + raw, err := ioutil.ReadFile("../block.json") + if err != nil { + fmt.Println("cannot find test block.json file:", err) + return + } - fmt.Printf("%+v\n", marshalledBlock) + // Marshall fake block into the Header + var blockHeader cli.Header + json.Unmarshal(raw, &blockHeader) + prefix := cli.EncodeExtraData(blockHeader) - // Now RLP encode the block - blockInterface := cli.GenerateInterface(marshalledBlock) - fmt.Println(blockInterface) + assert.Equal(t, expectedPrefix, prefix) - hash := cli.EncodeBlock(blockInterface) - fmt.Printf("%+v\n", hash) - // assert.Equal(t, expectedRlpHex, hex.EncodeToString(hash)) } diff --git a/ion-cli/cli/test.json b/ion-cli/cli/test.json new file mode 100644 index 0000000..eee8470 --- /dev/null +++ b/ion-cli/cli/test.json @@ -0,0 +1,11 @@ +{ + "rpc-addr-to":"127.0.0.1", + "rpc-port-to":"8545", + "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", + "rpc-addr-from":"127.0.0.1", + "rpc-port-from":"8501", + "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" +} diff --git a/ion-cli/validation/validation_test.go b/ion-cli/validation/validation_test.go new file mode 100644 index 0000000..4dc6eba --- /dev/null +++ b/ion-cli/validation/validation_test.go @@ -0,0 +1,85 @@ +package validation + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" +) + +// Test inbox contract gets deployed correctly +func TestDeployValidation(t *testing.T) { + + //Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} + blockchain := backends.NewSimulatedBackend(alloc) + + // Initialisation array + val1 := common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") + val2 := common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") + validators := []common.Address{val1, val2} + + genesisHash := [32]byte{} + copy(genesisHash[:], []byte("c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28")) + + // Deploy contract + address, _, _, err := DeployValidation( + auth, + blockchain, + validators, + genesisHash, + ) + // commit all pending transactions + blockchain.Commit() + + if err != nil { + t.Fatalf("Failed to deploy the Inbox contract: %v", err) + } + + if len(address.Bytes()) == 0 { + t.Error("Expected a valid deployment address. Received empty address byte array instead") + } + +} + +// Test inbox contract gets deployed correctly +func TestGetValidators(t *testing.T) { + + //Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} + blockchain := backends.NewSimulatedBackend(alloc) + + // Initialisation array + val1 := common.HexToAddress("0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d") + val2 := common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") + initValidators := []common.Address{val1, val2} + + genesisHash := [32]byte{} + copy(genesisHash[:], []byte("c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28")) + + // Deploy contract + _, _, contract, _ := DeployValidation( + auth, + blockchain, + initValidators, + genesisHash, + ) + // commit all pending transactions + blockchain.Commit() + + validators, _ := contract.GetValidators(&bind.CallOpts{}) + assert.Equal(t, validators[0], val1) + assert.Equal(t, validators[1], val2) + +} diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 4ee3f0e..0000000 --- a/package-lock.json +++ /dev/null @@ -1,7571 +0,0 @@ -{ - "name": "ion-truffle", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" - }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "requires": { - "mime-types": "2.1.18", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "requires": { - "acorn": "3.3.0" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" - } - } - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, - "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "1.9.1" - } - }, - "antlr4": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.0.tgz", - "integrity": "sha1-KX+VbdwG+DOX/AmQ7PLgzyC/u+4=" - }, - "any-observable": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", - "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=" - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "requires": { - "arr-flatten": "1.1.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "requires": { - "bn.js": "4.11.6", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "ast-types": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", - "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==" - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.5", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - }, - "dependencies": { - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.5", - "source-map": "0.5.7", - "trim-right": "1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "requires": { - "babel-helper-bindify-decorators": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" - }, - "babel-plugin-syntax-class-constructor-call": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" - }, - "babel-plugin-syntax-export-extensions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-class-constructor-call": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "requires": { - "babel-plugin-syntax-class-constructor-call": "6.18.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "requires": { - "babel-helper-explode-class": "6.24.1", - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "regexpu-core": "2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-export-extensions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "requires": { - "babel-plugin-syntax-export-extensions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "requires": { - "regenerator-transform": "0.10.1" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0" - } - }, - "babel-preset-node6": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-node6/-/babel-preset-node6-11.0.0.tgz", - "integrity": "sha1-CDWZRRckiYWinRj21GXasWu4p9g=", - "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0" - } - }, - "babel-preset-stage-1": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", - "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "requires": { - "babel-plugin-transform-class-constructor-call": "6.24.1", - "babel-plugin-transform-export-extensions": "6.22.0", - "babel-preset-stage-2": "6.24.1" - } - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators": "6.24.1", - "babel-preset-stage-3": "6.24.1" - } - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-generator-functions": "6.24.1", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.26.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "requires": { - "babel-core": "6.26.0", - "babel-runtime": "6.26.0", - "core-js": "2.5.3", - "home-or-tmp": "2.0.0", - "lodash": "4.17.5", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "requires": { - "source-map": "0.5.7" - } - } - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.5" - }, - "dependencies": { - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" - } - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.4", - "lodash": "4.17.5" - }, - "dependencies": { - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.5", - "to-fast-properties": "1.0.3" - } - }, - "babylon": { - "version": "7.0.0-beta.42", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz", - "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" - }, - "bignumber.js": { - "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" - }, - "binaryextensions": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", - "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" - }, - "bindings": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" - }, - "bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" - }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.16" - } - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "4.2.1" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "requires": { - "browserify-aes": "1.2.0", - "browserify-des": "1.0.1", - "evp_bytestokey": "1.0.3" - } - }, - "browserify-des": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", - "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", - "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "requires": { - "bn.js": "4.11.6", - "randombytes": "2.0.6" - } - }, - "browserify-sha3": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", - "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", - "requires": { - "js-sha3": "0.3.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "requires": { - "bn.js": "4.11.6", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.1" - } - }, - "buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" - }, - "buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "cacheable-request": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", - "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "requires": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - } - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "requires": { - "callsites": "0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "optional": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - } - }, - "chalk": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", - "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.3.0" - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-spinners": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" - }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "requires": { - "colors": "1.0.3" - }, - "dependencies": { - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - } - } - }, - "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "requires": { - "slice-ansi": "0.0.4", - "string-width": "1.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - } - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" - }, - "cliui": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", - "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - } - }, - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=" - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "requires": { - "mimic-response": "1.0.0" - } - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" - }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "requires": { - "inherits": "2.0.3", - "process-nextick-args": "2.0.0", - "readable-stream": "2.3.5" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "colors": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", - "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==" - }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "1.1.0", - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" - } - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "core-js": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", - "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", - "requires": { - "object-assign": "4.1.1", - "vary": "1.1.2" - } - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "requires": { - "bn.js": "4.11.6", - "elliptic": "6.4.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "md5.js": "1.3.4", - "ripemd160": "2.0.2", - "sha.js": "2.4.11" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "inherits": "2.0.3", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.1", - "sha.js": "2.4.11" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "1.0.4", - "path-key": "2.0.1", - "semver": "5.5.0", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "requires": { - "hoek": "4.2.1" - } - } - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "1.0.1", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.3", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "diffie-hellman": "5.0.3", - "inherits": "2.0.3", - "pbkdf2": "3.0.16", - "public-encrypt": "4.0.2", - "randombytes": "2.0.6", - "randomfill": "1.0.4" - } - }, - "crypto-js": { - "version": "3.1.9-1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", - "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" - }, - "dargs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "date-fns": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" - }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" - }, - "death": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "requires": { - "mimic-response": "1.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.2.8" - }, - "dependencies": { - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-conflict": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", - "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "requires": { - "repeating": "2.0.1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "requires": { - "bn.js": "4.11.6", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "requires": { - "esutils": "2.0.2" - } - }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" - }, - "drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", - "requires": { - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "create-hmac": "1.1.7" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "editions": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", - "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "ejs": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" - }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" - }, - "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "requires": { - "bn.js": "4.11.6", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "enhanced-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", - "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", - "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "tapable": "1.0.0" - } - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "requires": { - "prr": "1.0.1" - } - }, - "error": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", - "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "requires": { - "string-template": "0.2.1", - "xtend": "4.0.1" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "requires": { - "is-arrayish": "0.2.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "optional": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", - "requires": { - "ajv": "5.5.2", - "babel-code-frame": "6.26.0", - "chalk": "2.3.2", - "concat-stream": "1.6.2", - "cross-spawn": "5.1.0", - "debug": "3.1.0", - "doctrine": "2.1.0", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "1.0.0", - "espree": "3.5.4", - "esquery": "1.0.1", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "11.7.0", - "ignore": "3.3.10", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.1.0", - "js-yaml": "3.12.0", - "json-stable-stringify-without-jsonify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.5", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "7.0.0", - "progress": "2.0.0", - "regexpp": "1.1.0", - "require-uncached": "1.0.3", - "semver": "5.5.0", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", - "table": "4.0.2", - "text-table": "0.2.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "4.1.2", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==" - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.2", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.5", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - } - } - } - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "requires": { - "esrecurse": "4.2.1", - "estraverse": "4.2.0" - } - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "requires": { - "acorn": "5.7.1", - "acorn-jsx": "3.0.1" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "requires": { - "estraverse": "4.2.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "requires": { - "estraverse": "4.2.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "eth-lib": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", - "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", - "requires": { - "bn.js": "4.11.6", - "elliptic": "6.4.0", - "keccakjs": "0.2.1", - "nano-json-stream-parser": "0.1.2", - "servify": "0.1.12", - "ws": "3.3.3", - "xhr-request-promise": "0.1.2" - } - }, - "ethereumjs-testrpc-sc": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.2.tgz", - "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", - "requires": { - "source-map-support": "0.5.4", - "webpack-cli": "2.0.12" - } - }, - "ethereumjs-util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", - "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", - "requires": { - "bn.js": "4.11.6", - "create-hash": "1.2.0", - "ethjs-util": "0.1.6", - "keccak": "1.4.0", - "rlp": "2.0.0", - "safe-buffer": "5.1.1", - "secp256k1": "3.5.0" - } - }, - "ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "requires": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - } - }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } - }, - "eventemitter3": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", - "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.1" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "4.1.2", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - } - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "requires": { - "fill-range": "2.2.3" - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "1.0.1" - } - }, - "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", - "requires": { - "accepts": "1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.3", - "qs": "6.5.1", - "range-parser": "1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "1.4.0", - "type-is": "1.6.16", - "utils-merge": "1.0.1", - "vary": "1.1.2" - }, - "dependencies": { - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - } - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "external-editor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", - "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.19", - "tmp": "0.0.33" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "requires": { - "is-extglob": "1.0.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "2.0.0" - } - }, - "first-chunk-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", - "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "requires": { - "readable-stream": "2.3.5" - } - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" - } - }, - "flow-parser": { - "version": "0.68.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.68.0.tgz", - "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=" - }, - "for-each": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", - "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", - "requires": { - "is-function": "1.0.1" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "requires": { - "for-in": "1.0.2" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1", - "path-is-absolute": "1.0.1", - "rimraf": "2.2.8" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "ganache-cli": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.0.tgz", - "integrity": "sha512-FdTeyk4uLRHGeFiMe+Qnh4Hc5KiTVqvRVVvLDFJEVVKC1P1yHhEgZeh9sp1KhuvxSrxToxgJS25UapYQwH4zHw==", - "dev": true, - "requires": { - "source-map-support": "0.5.4", - "webpack-cli": "2.0.12" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "gh-got": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", - "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", - "requires": { - "got": "7.1.0", - "is-plain-obj": "1.1.0" - }, - "dependencies": { - "got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "requires": { - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-plain-obj": "1.1.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.0", - "p-cancelable": "0.3.0", - "p-timeout": "1.2.1", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "url-parse-lax": "1.0.0", - "url-to-options": "1.0.1" - } - }, - "p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" - }, - "p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "requires": { - "p-finally": "1.0.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "requires": { - "prepend-http": "1.0.4" - } - } - } - }, - "github-username": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", - "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", - "requires": { - "gh-got": "6.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-all": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", - "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", - "requires": { - "glob": "7.1.2", - "yargs": "1.2.6" - }, - "dependencies": { - "yargs": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", - "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", - "requires": { - "minimist": "0.1.0" - } - } - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "requires": { - "is-glob": "2.0.1" - } - }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "requires": { - "min-document": "2.19.0", - "process": "0.5.2" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, - "got": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.0.tgz", - "integrity": "sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==", - "requires": { - "@sindresorhus/is": "0.7.0", - "cacheable-request": "2.1.4", - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "into-stream": "3.1.0", - "is-retry-allowed": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.0", - "mimic-response": "1.0.0", - "p-cancelable": "0.4.0", - "p-timeout": "2.0.1", - "pify": "3.0.0", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "url-parse-lax": "3.0.0", - "url-to-options": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "grouped-queue": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", - "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", - "requires": { - "lodash": "4.17.5" - } - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - } - } - }, - "has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" - }, - "has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "requires": { - "has-symbol-support-x": "1.4.2" - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "requires": { - "parse-passwd": "1.0.0" - } - }, - "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" - }, - "http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - } - } - }, - "http-https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", - "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "2.0.1" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inquirer": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.1.0.tgz", - "integrity": "sha512-kn7N70US1MSZHZHSGJLiZ7iCwwncc7b0gc68YtlX29OjI3Mp0tSVV+snVXpZ1G+ONS3Ac9zd1m6hve2ibLDYfA==", - "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.2", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.5", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rxjs": "5.5.7", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" - }, - "into-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", - "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "requires": { - "from2": "2.3.0", - "p-is-promise": "1.1.0" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "1.3.1" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, - "ipaddr.js": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-function": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", - "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" - }, - "is-observable": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz", - "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", - "requires": { - "symbol-observable": "0.2.4" - }, - "dependencies": { - "symbol-observable": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", - "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=" - } - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "requires": { - "is-path-inside": "1.0.1" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" - }, - "is-scoped": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", - "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", - "requires": { - "scoped-regex": "1.0.0" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.12.0", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "istextorbinary": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", - "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "requires": { - "binaryextensions": "2.1.1", - "editions": "1.3.4", - "textextensions": "2.2.0" - } - }, - "isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "requires": { - "has-to-string-tag-x": "1.4.1", - "is-object": "1.0.1" - } - }, - "js-sha3": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", - "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "jscodeshift": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.0.tgz", - "integrity": "sha512-JAcQINNMFpdzzpKJN8k5xXjF3XDuckB1/48uScSzcnNyK199iWEc9AxKL9OoX5144M2w5zEx9Qs4/E/eBZZUlw==", - "requires": { - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-preset-es2015": "6.24.1", - "babel-preset-stage-1": "6.24.1", - "babel-register": "6.26.0", - "babylon": "7.0.0-beta.42", - "colors": "1.2.1", - "flow-parser": "0.68.0", - "lodash": "4.17.5", - "micromatch": "2.3.11", - "neo-async": "2.5.0", - "node-dir": "0.1.8", - "nomnom": "1.8.1", - "recast": "0.14.5", - "temp": "0.8.3", - "write-file-atomic": "1.3.4" - } - }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - }, - "json-bigint-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint-string/-/json-bigint-string-1.0.0.tgz", - "integrity": "sha1-M5l4TXeLt4RAvXLHCUrw4HW75oM=", - "dev": true - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - }, - "json-parse-better-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "requires": { - "graceful-fs": "4.1.11" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "keccak": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", - "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", - "requires": { - "bindings": "1.3.0", - "inherits": "2.0.3", - "nan": "2.10.0", - "safe-buffer": "5.1.1" - } - }, - "keccakjs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", - "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", - "requires": { - "browserify-sha3": "0.0.1", - "sha3": "1.2.0" - } - }, - "keyv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "requires": { - "json-buffer": "3.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "requires": { - "graceful-fs": "4.1.11" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "optional": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "1.0.0" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" - } - }, - "listr": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz", - "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", - "requires": { - "chalk": "1.1.3", - "cli-truncate": "0.2.1", - "figures": "1.7.0", - "indent-string": "2.1.0", - "is-observable": "0.2.0", - "is-promise": "2.1.0", - "is-stream": "1.1.0", - "listr-silent-renderer": "1.1.1", - "listr-update-renderer": "0.4.0", - "listr-verbose-renderer": "0.4.1", - "log-symbols": "1.0.2", - "log-update": "1.0.2", - "ora": "0.2.3", - "p-map": "1.2.0", - "rxjs": "5.5.7", - "stream-to-observable": "0.2.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "requires": { - "chalk": "1.1.3" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" - }, - "listr-update-renderer": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", - "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", - "requires": { - "chalk": "1.1.3", - "cli-truncate": "0.2.1", - "elegant-spinner": "1.0.1", - "figures": "1.7.0", - "indent-string": "3.2.0", - "log-symbols": "1.0.2", - "log-update": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "requires": { - "chalk": "1.1.3" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "listr-verbose-renderer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", - "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", - "requires": { - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "date-fns": "1.29.0", - "figures": "1.7.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "requires": { - "restore-cursor": "1.0.1" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "4.0.0", - "pify": "3.0.0", - "strip-bom": "3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - } - } - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - } - }, - "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "requires": { - "chalk": "2.3.2" - } - }, - "log-update": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", - "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", - "requires": { - "ansi-escapes": "1.4.0", - "cli-cursor": "1.0.2" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "requires": { - "restore-cursor": "1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" - } - } - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "requires": { - "js-tokens": "3.0.2" - } - }, - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" - }, - "lru-cache": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", - "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "make-dir": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", - "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", - "requires": { - "pify": "3.0.0" - } - }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "requires": { - "mimic-fn": "1.2.0" - } - }, - "mem-fs": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", - "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", - "requires": { - "through2": "2.0.3", - "vinyl": "1.2.0", - "vinyl-file": "2.0.0" - } - }, - "mem-fs-editor": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-3.0.2.tgz", - "integrity": "sha1-3Qpuryu4prN3QAZ6pUnrUwEFr58=", - "requires": { - "commondir": "1.0.1", - "deep-extend": "0.4.2", - "ejs": "2.5.7", - "glob": "7.1.2", - "globby": "6.1.0", - "mkdirp": "0.5.1", - "multimatch": "2.1.0", - "rimraf": "2.2.8", - "through2": "2.0.3", - "vinyl": "2.1.0" - }, - "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.1.2", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - } - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.5" - } - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "4.11.6", - "brorand": "1.1.0" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - }, - "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "requires": { - "mime-db": "1.33.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" - }, - "mimic-response": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", - "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" - }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "requires": { - "dom-walk": "0.1.1" - } - }, - "minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", - "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } - } - }, - "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "requires": { - "array-differ": "1.0.0", - "array-union": "1.0.2", - "arrify": "1.0.1", - "minimatch": "3.0.4" - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" - }, - "nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "neo-async": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", - "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==" - }, - "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" - }, - "node-dir": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", - "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" - }, - "nomnom": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", - "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "requires": { - "chalk": "0.4.0", - "underscore": "1.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" - }, - "chalk": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "requires": { - "ansi-styles": "1.0.0", - "has-color": "0.1.7", - "strip-ansi": "0.1.1" - } - }, - "strip-ansi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1.0.9" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.3" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "requires": { - "prepend-http": "2.0.0", - "query-string": "5.1.1", - "sort-keys": "2.0.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "2.0.1" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "requires": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - } - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "oboe": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", - "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", - "requires": { - "http-https": "1.0.0" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "1.2.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.3" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - } - }, - "ora": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", - "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", - "requires": { - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-spinners": "0.1.2", - "object-assign": "4.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "requires": { - "restore-cursor": "1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "original-require": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", - "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-cancelable": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.0.tgz", - "integrity": "sha512-/AodqPe1y/GYbhSlnMjxukLGQfQIgsmjSy2CXCNB96kg4ozKvmlovuHEKICToOO/yS3LLWgrWI1dFtFfrePS1g==" - }, - "p-each-series": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", - "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", - "requires": { - "p-reduce": "1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" - }, - "p-lazy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", - "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" - }, - "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "requires": { - "p-try": "1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "1.2.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" - }, - "p-reduce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" - }, - "p-timeout": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", - "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "requires": { - "p-finally": "1.0.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.16" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - } - }, - "parse-headers": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", - "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", - "requires": { - "for-each": "0.3.2", - "trim": "0.0.1" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "requires": { - "error-ex": "1.3.1", - "json-parse-better-errors": "1.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "requires": { - "pify": "3.0.0" - } - }, - "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "requires": { - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.1", - "sha.js": "2.4.11" - } - }, - "pegjs": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", - "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "2.0.4" - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" - }, - "prettier": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz", - "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==" - }, - "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" - }, - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" - }, - "proxy-addr": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", - "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", - "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.6.0" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "public-encrypt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", - "requires": { - "bn.js": "4.11.6", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "parse-asn1": "5.1.1", - "randombytes": "2.0.6" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" - }, - "query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "requires": { - "decode-uri-component": "0.2.0", - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.1" - } - }, - "randomhex": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", - "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - } - }, - "read-chunk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", - "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", - "requires": { - "pify": "3.0.0", - "safe-buffer": "5.1.1" - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "requires": { - "load-json-file": "4.0.0", - "normalize-package-data": "2.4.0", - "path-type": "3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "requires": { - "find-up": "2.1.0", - "read-pkg": "3.0.0" - } - }, - "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "recast": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.5.tgz", - "integrity": "sha512-GNFQGQrqW1R8w9XhhgYIN8H7ePPp088D+svHlb7DdP5DCqNDqTwH7lt378EouM+L18kCwkmqpAz1unLqpPhHmw==", - "requires": { - "ast-types": "0.11.3", - "esprima": "4.0.0", - "private": "0.1.8", - "source-map": "0.6.1" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "1.5.0" - } - }, - "regenerate": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "private": "0.1.8" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "requires": { - "is-equal-shallow": "0.1.3" - } - }, - "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==" - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "requires": { - "regenerate": "1.3.3", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "requires": { - "jsesc": "0.5.0" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "1.0.2" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" - }, - "req-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", - "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", - "requires": { - "req-from": "1.0.1" - } - }, - "req-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", - "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", - "requires": { - "resolve-from": "2.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" - } - } - }, - "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" - }, - "dependencies": { - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" - } - } - }, - "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "requires": { - "resolve-from": "3.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "requires": { - "lowercase-keys": "1.0.0" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "optional": true, - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" - } - }, - "rlp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.0.0.tgz", - "integrity": "sha1-nbOE/0uJqPYVY9kjldhiWxjzr7A=" - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "requires": { - "rx-lite": "4.0.8" - } - }, - "rxjs": { - "version": "5.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", - "integrity": "sha512-Hxo2ac8gRQjwjtKgukMIwBRbq5+KAeEV5hXM4obYBOAghev41bDQWgFH4svYiU9UnQ5kNww2LgfyBdevCd2HXA==", - "requires": { - "symbol-observable": "1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "scoped-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", - "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" - }, - "scrypt": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", - "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", - "requires": { - "nan": "2.10.0" - } - }, - "scrypt.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", - "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", - "requires": { - "scrypt": "6.0.3", - "scryptsy": "1.2.1" - } - }, - "scryptsy": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", - "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", - "requires": { - "pbkdf2": "3.0.16" - } - }, - "secp256k1": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.0.tgz", - "integrity": "sha512-e5QIJl8W7Y4tT6LHffVcZAxJjvpgE5Owawv6/XCYPQljE9aP2NFFddQ8OYMKhdLshNu88FfL3qCN3/xYkXGRsA==", - "requires": { - "bindings": "1.3.0", - "bip66": "1.1.5", - "bn.js": "4.11.6", - "create-hash": "1.2.0", - "drbg.js": "1.0.1", - "elliptic": "6.4.0", - "nan": "2.10.0", - "safe-buffer": "5.1.1" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "requires": { - "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", - "fresh": "0.5.2", - "http-errors": "1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.16.2" - } - }, - "servify": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", - "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", - "requires": { - "body-parser": "1.18.2", - "cors": "2.8.4", - "express": "4.16.3", - "request": "2.85.0", - "xhr": "2.4.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "sha3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.0.tgz", - "integrity": "sha1-aYnxtwpJhwWHajc+LGKs6WqpOZo=", - "requires": { - "nan": "2.10.0" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "shelljs": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", - "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "simple-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" - }, - "simple-get": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz", - "integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==", - "requires": { - "decompress-response": "3.3.0", - "once": "1.4.0", - "simple-concat": "1.0.0" - } - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "requires": { - "hoek": "4.2.1" - } - }, - "sol-explore": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", - "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=" - }, - "solc": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.23.tgz", - "integrity": "sha512-AT7anLHY6uIRg2It6N0UlCHeZ7YeecIkUhnlirrCgCPCUevtnoN48BxvgigN/4jJTRljv5oFhAJtI6gvHzT5DQ==", - "requires": { - "fs-extra": "0.30.0", - "memorystream": "0.3.1", - "require-from-string": "1.2.1", - "semver": "5.5.0", - "yargs": "4.8.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "1.3.1" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" - }, - "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" - } - } - } - }, - "solhint": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.2.1.tgz", - "integrity": "sha512-3B0ydhkOlicyyTmKnwJC6kiwdJUXvbbDYXcy8m7rznoQPgzzkmSOsJgb9BAe+KBQP5BD3PLgcoOQ84t3FSxqsQ==", - "requires": { - "antlr4": "4.7.0", - "commander": "2.11.0", - "eslint": "4.19.1", - "glob": "7.1.2", - "ignore": "3.3.10", - "lodash": "4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" - } - } - }, - "solidity-coverage": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.5.4.tgz", - "integrity": "sha512-UvjLBgUJiLvufU6K9xmf/gPIU7DhWcDmBA6iTJ0dZI7LsvU+vugN1/ByZojU54kWLpaODx0A+P4cIT0jcRVNNw==", - "requires": { - "death": "1.1.0", - "ethereumjs-testrpc-sc": "6.1.2", - "istanbul": "0.4.5", - "keccakjs": "0.2.1", - "req-cwd": "1.0.1", - "shelljs": "0.7.8", - "sol-explore": "1.6.2", - "solidity-parser-sc": "0.4.10", - "tree-kill": "1.2.0", - "web3": "0.18.4" - }, - "dependencies": { - "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" - }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" - } - }, - "web3": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", - "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", - "requires": { - "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "crypto-js": "3.1.8", - "utf8": "2.1.2", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - } - } - } - }, - "solidity-parser-sc": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.10.tgz", - "integrity": "sha512-oGgFpeX4OzvOfku/Bnw3/yrOmcVJTgXa994HjZwWXA/kHVZ4L1ml9BcbWHRAziJYm3ObHCXlKumfMCBXBt9K8Q==", - "requires": { - "mocha": "4.1.0", - "pegjs": "0.10.0", - "yargs": "4.8.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "1.3.1" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "requires": { - "has-flag": "2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" - }, - "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" - } - } - } - }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "requires": { - "is-plain-obj": "1.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-support": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", - "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", - "requires": { - "source-map": "0.6.1" - } - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - }, - "stream-to-observable": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", - "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", - "requires": { - "any-observable": "0.2.0" - } - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" - }, - "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "0.2.1" - } - }, - "strip-bom-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", - "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", - "requires": { - "first-chunk-stream": "2.0.0", - "strip-bom": "2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, - "strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "requires": { - "is-hex-prefixed": "1.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "supports-color": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", - "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "requires": { - "has-flag": "3.0.0" - } - }, - "symbol-observable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" - }, - "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "requires": { - "ajv": "5.5.2", - "ajv-keywords": "2.1.1", - "chalk": "2.3.2", - "lodash": "4.17.5", - "slice-ansi": "1.0.0", - "string-width": "2.1.1" - }, - "dependencies": { - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "requires": { - "is-fullwidth-code-point": "2.0.0" - } - } - } - }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" - }, - "temp": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", - "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "requires": { - "os-tmpdir": "1.0.2", - "rimraf": "2.2.8" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" - }, - "textextensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", - "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.5", - "xtend": "4.0.1" - } - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "requires": { - "punycode": "1.4.1" - } - }, - "tree-kill": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", - "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" - }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" - }, - "truffle": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.7.tgz", - "integrity": "sha512-fe6BIcD9xo6iIJvV1m6ZhOk56kmB8k38kdoWOKYnPPw7ZUUSupgojeTb2K5e+4qIpIHvEvmET4yLUjSGR+hvwA==", - "dev": true, - "requires": { - "mocha": "3.5.3", - "original-require": "1.0.1", - "solc": "0.4.23" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "requires": { - "prelude-ls": "1.1.2" - } - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "2.1.18" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "1.0.0" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "optional": true, - "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "optional": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "optional": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "optional": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "optional": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "optional": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "optional": true - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "untildify": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz", - "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=" - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "requires": { - "prepend-http": "2.0.0" - } - }, - "url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" - }, - "url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" - }, - "utf8": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", - "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" - }, - "v8-compile-cache": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz", - "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==" - }, - "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", - "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0", - "strip-bom-stream": "2.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, - "web3": { - "version": "github:ethereum/web3.js#59aae306c1c31ef6a65b9196e7f03af74c69e059", - "requires": { - "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", - "crypto-js": "3.1.8", - "utf8": "2.1.2", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "bignumber.js": { - "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" - }, - "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" - } - } - }, - "web3-core": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.34.tgz", - "integrity": "sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4=", - "requires": { - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-core-requestmanager": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-core-helpers": { - "version": "1.0.0-beta.33", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.33.tgz", - "integrity": "sha1-Kvcz5QTbBefDZIwdrPV3sOwV3EM=", - "dev": true, - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.33", - "web3-utils": "1.0.0-beta.33" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true - } - } - }, - "web3-core-method": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz", - "integrity": "sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0=", - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-promievent": "1.0.0-beta.34", - "web3-core-subscriptions": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-core-promievent": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz", - "integrity": "sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw=", - "requires": { - "any-promise": "1.3.0", - "eventemitter3": "1.1.1" - } - }, - "web3-core-requestmanager": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz", - "integrity": "sha1-Afj2zyrmtvC3DDi64e90G1urIVw=", - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", - "web3-providers-http": "1.0.0-beta.34", - "web3-providers-ipc": "1.0.0-beta.34", - "web3-providers-ws": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-core-subscriptions": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz", - "integrity": "sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4=", - "requires": { - "eventemitter3": "1.1.1", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-eth": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.34.tgz", - "integrity": "sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg=", - "requires": { - "underscore": "1.8.3", - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-core-subscriptions": "1.0.0-beta.34", - "web3-eth-abi": "1.0.0-beta.34", - "web3-eth-accounts": "1.0.0-beta.34", - "web3-eth-contract": "1.0.0-beta.34", - "web3-eth-iban": "1.0.0-beta.34", - "web3-eth-personal": "1.0.0-beta.34", - "web3-net": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-abi": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", - "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", - "requires": { - "bn.js": "4.11.6", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-eth-abi": { - "version": "1.0.0-beta.33", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.33.tgz", - "integrity": "sha1-IiH3FRZDZgAypN80D2EjSRaMgko=", - "dev": true, - "requires": { - "bn.js": "4.11.6", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.33", - "web3-utils": "1.0.0-beta.33" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true - } - } - }, - "web3-eth-accounts": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz", - "integrity": "sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM=", - "requires": { - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.7", - "scrypt.js": "0.2.0", - "underscore": "1.8.3", - "uuid": "2.0.1", - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "requires": { - "bn.js": "4.11.6", - "elliptic": "6.4.0", - "xhr-request-promise": "0.1.2" - } - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - }, - "dependencies": { - "eth-lib": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", - "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", - "requires": { - "bn.js": "4.11.6", - "elliptic": "6.4.0", - "keccakjs": "0.2.1", - "nano-json-stream-parser": "0.1.2", - "servify": "0.1.12", - "ws": "3.3.3", - "xhr-request-promise": "0.1.2" - } - } - } - } - } - }, - "web3-eth-contract": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz", - "integrity": "sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY=", - "requires": { - "underscore": "1.8.3", - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-core-promievent": "1.0.0-beta.34", - "web3-core-subscriptions": "1.0.0-beta.34", - "web3-eth-abi": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-abi": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", - "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", - "requires": { - "bn.js": "4.11.6", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.33", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.33.tgz", - "integrity": "sha1-HXPQxSiKRWWxdUp1tfs+oLd6Uy8=", - "dev": true, - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.33" - } - }, - "web3-eth-personal": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz", - "integrity": "sha1-mvuhZzQuveVCC81YlcP2w0OI8gU=", - "requires": { - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-net": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-net": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.34.tgz", - "integrity": "sha1-QnzqL0MYgUScjjjVIykPFz+f9j0=", - "requires": { - "web3-core": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-providers-http": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz", - "integrity": "sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno=", - "requires": { - "web3-core-helpers": "1.0.0-beta.34", - "xhr2": "0.1.4" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-providers-ipc": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz", - "integrity": "sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao=", - "requires": { - "oboe": "2.1.3", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-providers-ws": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz", - "integrity": "sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM=", - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", - "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-eth-iban": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-utils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - } - } - } - }, - "web3-utils": { - "version": "1.0.0-beta.33", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.33.tgz", - "integrity": "sha1-4JG3mU8JtxSwGYpAV9OtLrjL4jg=", - "dev": true, - "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=", - "dev": true - } - } - }, - "webpack-addons": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", - "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", - "requires": { - "jscodeshift": "0.4.1" - }, - "dependencies": { - "ast-types": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", - "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" - }, - "jscodeshift": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", - "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", - "requires": { - "async": "1.5.2", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-preset-es2015": "6.24.1", - "babel-preset-stage-1": "6.24.1", - "babel-register": "6.26.0", - "babylon": "6.18.0", - "colors": "1.2.1", - "flow-parser": "0.68.0", - "lodash": "4.17.5", - "micromatch": "2.3.11", - "node-dir": "0.1.8", - "nomnom": "1.8.1", - "recast": "0.12.9", - "temp": "0.8.3", - "write-file-atomic": "1.3.4" - } - }, - "recast": { - "version": "0.12.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", - "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", - "requires": { - "ast-types": "0.10.1", - "core-js": "2.5.3", - "esprima": "4.0.0", - "private": "0.1.8", - "source-map": "0.6.1" - } - } - } - }, - "webpack-cli": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.12.tgz", - "integrity": "sha512-kMi6NquWwUhmQok2IFrtAEIbaVvujzYvtDGb5WElkwylbLboDsCgizv8IjSi/Q6SQRJ8Crayl1JCBnIJ3rU4Rg==", - "requires": { - "chalk": "2.3.2", - "cross-spawn": "6.0.5", - "diff": "3.5.0", - "enhanced-resolve": "4.0.0", - "glob-all": "3.1.0", - "global-modules": "1.0.0", - "got": "8.3.0", - "inquirer": "5.1.0", - "interpret": "1.1.0", - "jscodeshift": "0.5.0", - "listr": "0.13.0", - "loader-utils": "1.1.0", - "lodash": "4.17.5", - "log-symbols": "2.2.0", - "mkdirp": "0.5.1", - "p-each-series": "1.0.0", - "p-lazy": "1.0.0", - "prettier": "1.11.1", - "resolve-cwd": "2.0.0", - "supports-color": "5.3.0", - "v8-compile-cache": "1.1.2", - "webpack-addons": "1.1.5", - "yargs": "11.0.0", - "yeoman-environment": "2.0.5", - "yeoman-generator": "2.0.3" - } - }, - "websocket": { - "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", - "requires": { - "debug": "2.6.9", - "nan": "2.10.0", - "typedarray-to-buffer": "3.1.5", - "yaeti": "0.0.6" - } - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "optional": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "requires": { - "mkdirp": "0.5.1" - } - }, - "write-file-atomic": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", - "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "slide": "1.1.6" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "requires": { - "async-limiter": "1.0.0", - "safe-buffer": "5.1.1", - "ultron": "1.1.1" - } - }, - "xhr": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.1.tgz", - "integrity": "sha512-pAIU5vBr9Hiy5cpFIbPnwf0C18ZF86DBsZKrlsf87N5De/JbA6RJ83UP/cv+aljl4S40iRVMqP4pr4sF9Dnj0A==", - "requires": { - "global": "4.3.2", - "is-function": "1.0.1", - "parse-headers": "2.0.1", - "xtend": "4.0.1" - } - }, - "xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "requires": { - "buffer-to-arraybuffer": "0.0.5", - "object-assign": "4.1.1", - "query-string": "5.1.1", - "simple-get": "2.7.0", - "timed-out": "4.0.1", - "url-set-query": "1.0.0", - "xhr": "2.4.1" - } - }, - "xhr-request-promise": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", - "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", - "requires": { - "xhr-request": "1.1.0" - } - }, - "xhr2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", - "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" - }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "yargs": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", - "requires": { - "cliui": "4.0.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "requires": { - "camelcase": "4.1.0" - } - }, - "yeoman-environment": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.0.5.tgz", - "integrity": "sha512-6/W7/B54OPHJXob0n0+pmkwFsirC8cokuQkPSmT/D0lCcSxkKtg/BA6ZnjUBIwjuGqmw3DTrT4en++htaUju5g==", - "requires": { - "chalk": "2.3.2", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "globby": "6.1.0", - "grouped-queue": "0.3.3", - "inquirer": "3.3.0", - "is-scoped": "1.0.0", - "lodash": "4.17.5", - "log-symbols": "2.2.0", - "mem-fs": "1.1.3", - "text-table": "0.2.0", - "untildify": "3.0.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.2", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.5", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - } - } - } - }, - "yeoman-generator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.3.tgz", - "integrity": "sha512-mODmrZ26a94djmGZZuIiomSGlN4wULdou29ZwcySupb2e9FdvoCl7Ps2FqHFjEHio3kOl/iBeaNqrnx3C3NwWg==", - "requires": { - "async": "2.6.0", - "chalk": "2.3.2", - "cli-table": "0.3.1", - "cross-spawn": "5.1.0", - "dargs": "5.1.0", - "dateformat": "3.0.3", - "debug": "3.1.0", - "detect-conflict": "1.0.1", - "error": "7.0.2", - "find-up": "2.1.0", - "github-username": "4.1.0", - "istextorbinary": "2.2.1", - "lodash": "4.17.5", - "make-dir": "1.2.0", - "mem-fs-editor": "3.0.2", - "minimist": "1.2.0", - "pretty-bytes": "4.0.2", - "read-chunk": "2.1.0", - "read-pkg-up": "3.0.0", - "rimraf": "2.6.2", - "run-async": "2.3.0", - "shelljs": "0.8.1", - "text-table": "0.2.0", - "through2": "2.0.3", - "yeoman-environment": "2.0.5" - }, - "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "requires": { - "lodash": "4.17.5" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "4.1.2", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "7.1.2" - } - } - } - } - } -} From 44e2deabccc6225a4c5718e8148f8a17eff3265a Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 16:17:16 +0100 Subject: [PATCH 025/203] Added the travis ci --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..62bb450 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: go +go_import_path: github.com/clearmatics/ion +go: +- '1.8' +- 1.10.x +notifications: + slack: + secure: k6j6BWCTMJ6U7JXhy0yBcJpfkOw4eUNnL9xyufiI6Ue5Cf+NvN9FJxNZvoz4BvVSitq/BSlcWGjQoIW5AoWtf15tl4hvQmFN4YYHT79TKjRGEcSBg1+D55aXmjIM3UwHtCOuSJxAkl7dTgWAJ3FU0/aBqy96OsODjhcP8VeuMay+2Z+kT/QQjtO5rduHfLpeJxVfoEdhXR9QjHozV287rE49E6wWV6KzNCDOYy3CFGkQsgBQzlxkmlvhwbjDeNb72UcruSh50ic78/NLru3AXwRFx2yc1fkr2Nv9q6l5r9I1iWek8EZ46OCe/dQ004s7PI7knVx1vssdA3ksLDyRzhNHvWpn1EI1fi4Aqc+ki9vHbccR5c1pw85zwcQiLEoVFpJ+MpfHi9ExmAJmvvrzz2RBMqsL5JuSfInxiSLyX6vSVpufgZYrDKAemWXhR030dQQZ8BVQOCbt2lzCgHZajmDvrOktq6QdTFzEz/JjyorXn+0Rpho+7FHY5sW9KdgvmexI9SAjjz0BgcQzof9QKpyuRZpbboWRxPsfPUQDlx+Wxm541ndunGNQ2mVXqSgKaTQShiKhhu7dOPevw1a+dreJ6n8afL9pfW4SHcs0O+FlHvAnLAbRDvbnxROF89RRDiTVBdC6h7vcAX6lNDFUxF0F1bYTiWE0s4+umB2zlqc= From ee35978f49c505dde37ae184c57affeb5a1af358 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 16:25:49 +0100 Subject: [PATCH 026/203] Added a script testing --- .travis.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 62bb450..ea9f06d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,15 @@ language: go -go_import_path: github.com/clearmatics/ion -go: -- '1.8' -- 1.10.x + +matrix: + include: + - os: linux + dist: trusty + go_import_path: github.com/clearmatics/ion + go: 1.8.x + script: + - make check + - make coverage + notifications: slack: secure: k6j6BWCTMJ6U7JXhy0yBcJpfkOw4eUNnL9xyufiI6Ue5Cf+NvN9FJxNZvoz4BvVSitq/BSlcWGjQoIW5AoWtf15tl4hvQmFN4YYHT79TKjRGEcSBg1+D55aXmjIM3UwHtCOuSJxAkl7dTgWAJ3FU0/aBqy96OsODjhcP8VeuMay+2Z+kT/QQjtO5rduHfLpeJxVfoEdhXR9QjHozV287rE49E6wWV6KzNCDOYy3CFGkQsgBQzlxkmlvhwbjDeNb72UcruSh50ic78/NLru3AXwRFx2yc1fkr2Nv9q6l5r9I1iWek8EZ46OCe/dQ004s7PI7knVx1vssdA3ksLDyRzhNHvWpn1EI1fi4Aqc+ki9vHbccR5c1pw85zwcQiLEoVFpJ+MpfHi9ExmAJmvvrzz2RBMqsL5JuSfInxiSLyX6vSVpufgZYrDKAemWXhR030dQQZ8BVQOCbt2lzCgHZajmDvrOktq6QdTFzEz/JjyorXn+0Rpho+7FHY5sW9KdgvmexI9SAjjz0BgcQzof9QKpyuRZpbboWRxPsfPUQDlx+Wxm541ndunGNQ2mVXqSgKaTQShiKhhu7dOPevw1a+dreJ6n8afL9pfW4SHcs0O+FlHvAnLAbRDvbnxROF89RRDiTVBdC6h7vcAX6lNDFUxF0F1bYTiWE0s4+umB2zlqc= From 0f95043615b87cbbae0e411a16fd4981bedb0fac Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 16:39:11 +0100 Subject: [PATCH 027/203] just trying to get the formatting correct --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ea9f06d..fa7dabc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ matrix: go: 1.8.x script: - make check - - make coverage + - make coverage notifications: slack: From c13201521ce12ddd2d5799593e3508fca3847a2f Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 16:42:02 +0100 Subject: [PATCH 028/203] Still not parsing --- .travis.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa7dabc..0572edc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,12 @@ language: go - matrix: - include: + include: - os: linux dist: trusty go_import_path: github.com/clearmatics/ion go: 1.8.x script: - - make check - - make coverage - + - cd ./ion-cli && make test notifications: slack: secure: k6j6BWCTMJ6U7JXhy0yBcJpfkOw4eUNnL9xyufiI6Ue5Cf+NvN9FJxNZvoz4BvVSitq/BSlcWGjQoIW5AoWtf15tl4hvQmFN4YYHT79TKjRGEcSBg1+D55aXmjIM3UwHtCOuSJxAkl7dTgWAJ3FU0/aBqy96OsODjhcP8VeuMay+2Z+kT/QQjtO5rduHfLpeJxVfoEdhXR9QjHozV287rE49E6wWV6KzNCDOYy3CFGkQsgBQzlxkmlvhwbjDeNb72UcruSh50ic78/NLru3AXwRFx2yc1fkr2Nv9q6l5r9I1iWek8EZ46OCe/dQ004s7PI7knVx1vssdA3ksLDyRzhNHvWpn1EI1fi4Aqc+ki9vHbccR5c1pw85zwcQiLEoVFpJ+MpfHi9ExmAJmvvrzz2RBMqsL5JuSfInxiSLyX6vSVpufgZYrDKAemWXhR030dQQZ8BVQOCbt2lzCgHZajmDvrOktq6QdTFzEz/JjyorXn+0Rpho+7FHY5sW9KdgvmexI9SAjjz0BgcQzof9QKpyuRZpbboWRxPsfPUQDlx+Wxm541ndunGNQ2mVXqSgKaTQShiKhhu7dOPevw1a+dreJ6n8afL9pfW4SHcs0O+FlHvAnLAbRDvbnxROF89RRDiTVBdC6h7vcAX6lNDFUxF0F1bYTiWE0s4+umB2zlqc= From 738e771d750dd2c5c47cb35c44abc61c4d33b898 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 16:51:49 +0100 Subject: [PATCH 029/203] Parsing but not working :( --- .travis.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0572edc..8b13d2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,8 @@ language: go -matrix: - include: - - os: linux - dist: trusty - go_import_path: github.com/clearmatics/ion - go: 1.8.x - script: - - cd ./ion-cli && make test +go_import_path: github.com/clearmatics/ion +go: 1.8.x +script: + - cd ./ion-cli && make test notifications: slack: secure: k6j6BWCTMJ6U7JXhy0yBcJpfkOw4eUNnL9xyufiI6Ue5Cf+NvN9FJxNZvoz4BvVSitq/BSlcWGjQoIW5AoWtf15tl4hvQmFN4YYHT79TKjRGEcSBg1+D55aXmjIM3UwHtCOuSJxAkl7dTgWAJ3FU0/aBqy96OsODjhcP8VeuMay+2Z+kT/QQjtO5rduHfLpeJxVfoEdhXR9QjHozV287rE49E6wWV6KzNCDOYy3CFGkQsgBQzlxkmlvhwbjDeNb72UcruSh50ic78/NLru3AXwRFx2yc1fkr2Nv9q6l5r9I1iWek8EZ46OCe/dQ004s7PI7knVx1vssdA3ksLDyRzhNHvWpn1EI1fi4Aqc+ki9vHbccR5c1pw85zwcQiLEoVFpJ+MpfHi9ExmAJmvvrzz2RBMqsL5JuSfInxiSLyX6vSVpufgZYrDKAemWXhR030dQQZ8BVQOCbt2lzCgHZajmDvrOktq6QdTFzEz/JjyorXn+0Rpho+7FHY5sW9KdgvmexI9SAjjz0BgcQzof9QKpyuRZpbboWRxPsfPUQDlx+Wxm541ndunGNQ2mVXqSgKaTQShiKhhu7dOPevw1a+dreJ6n8afL9pfW4SHcs0O+FlHvAnLAbRDvbnxROF89RRDiTVBdC6h7vcAX6lNDFUxF0F1bYTiWE0s4+umB2zlqc= From b93d3c9b33378369cab2efecd89621133e1ae474 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 28 Jun 2018 16:59:24 +0100 Subject: [PATCH 030/203] trying one fix --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8b13d2a..af2c6b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: go -go_import_path: github.com/clearmatics/ion +go_import_path: github.com/clearmatics/ion/ion-cli go: 1.8.x script: - cd ./ion-cli && make test From 69a148f08ea18885cf08dba0914cc8895fbef86d Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 08:37:56 +0100 Subject: [PATCH 031/203] test --- .travis.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index af2c6b5..e080cd5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,14 @@ language: go -go_import_path: github.com/clearmatics/ion/ion-cli -go: 1.8.x -script: - - cd ./ion-cli && make test + +matrix: + include: + - os: linux + dist: trusty + go: 1.8.x + script: + - go get github.com/golang/lint/golint + - cd ./ion-cli && make test + notifications: slack: secure: k6j6BWCTMJ6U7JXhy0yBcJpfkOw4eUNnL9xyufiI6Ue5Cf+NvN9FJxNZvoz4BvVSitq/BSlcWGjQoIW5AoWtf15tl4hvQmFN4YYHT79TKjRGEcSBg1+D55aXmjIM3UwHtCOuSJxAkl7dTgWAJ3FU0/aBqy96OsODjhcP8VeuMay+2Z+kT/QQjtO5rduHfLpeJxVfoEdhXR9QjHozV287rE49E6wWV6KzNCDOYy3CFGkQsgBQzlxkmlvhwbjDeNb72UcruSh50ic78/NLru3AXwRFx2yc1fkr2Nv9q6l5r9I1iWek8EZ46OCe/dQ004s7PI7knVx1vssdA3ksLDyRzhNHvWpn1EI1fi4Aqc+ki9vHbccR5c1pw85zwcQiLEoVFpJ+MpfHi9ExmAJmvvrzz2RBMqsL5JuSfInxiSLyX6vSVpufgZYrDKAemWXhR030dQQZ8BVQOCbt2lzCgHZajmDvrOktq6QdTFzEz/JjyorXn+0Rpho+7FHY5sW9KdgvmexI9SAjjz0BgcQzof9QKpyuRZpbboWRxPsfPUQDlx+Wxm541ndunGNQ2mVXqSgKaTQShiKhhu7dOPevw1a+dreJ6n8afL9pfW4SHcs0O+FlHvAnLAbRDvbnxROF89RRDiTVBdC6h7vcAX6lNDFUxF0F1bYTiWE0s4+umB2zlqc= From 548a8b8bc9b1777245be7925e8ec674397fd36dd Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 08:45:17 +0100 Subject: [PATCH 032/203] Added makefile supposedly it solves the errors that keep occuring --- Makefile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..223f8ae --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +target: ; From 07919a295afada5724622c604dc4c04cd3723e5e Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 08:56:08 +0100 Subject: [PATCH 033/203] makefile made things better now we need to get the ion package --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e080cd5..4485e13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ matrix: dist: trusty go: 1.8.x script: - - go get github.com/golang/lint/golint + - go get github.com/clearmatics/ion - cd ./ion-cli && make test notifications: From 1b7bc263e652a9fea066b22225059b2774f2368c Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 09:01:10 +0100 Subject: [PATCH 034/203] Test --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4485e13..4e53a1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ matrix: dist: trusty go: 1.8.x script: - - go get github.com/clearmatics/ion + - go get github.com/clearmatics/ion/ion-cli - cd ./ion-cli && make test notifications: From d8e111c99835c622429e40ddeffc5bc7ebfe47b5 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 09:30:49 +0100 Subject: [PATCH 035/203] testing makefile --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4e53a1f..3f2d61d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ matrix: dist: trusty go: 1.8.x script: - - go get github.com/clearmatics/ion/ion-cli - cd ./ion-cli && make test notifications: From 56138c6ebe372c2a6b6fb5f8ec9a8c3a5331e1b6 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 09:35:47 +0100 Subject: [PATCH 036/203] go paths werent in proper structure --- ion-cli/cli/cli.go | 4 ++-- ion-cli/cli/cli_test.go | 2 +- ion-cli/cli/rpc_test.go | 2 +- ion-cli/config/config_test.go | 2 +- ion-cli/config/init.go | 2 +- ion-cli/main.go | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index af4cabd..9eb1e75 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ion/ion-cli/config" - "github.com/ion/ion-cli/validation" + "github.com/clearmatics/ion/ion-cli/config" + "github.com/clearmatics/ion/ion-cli/validation" ) // Launch - definition of commands and creates the iterface diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index 25135bf..c9f53af 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ion/ion-cli/config" + "github.com/clearmatics/ion/ion-cli/config" ) func Test_Read_ValidSetupJson(t *testing.T) { diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index 537212b..9b758d7 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -9,7 +9,7 @@ import ( "io/ioutil" "testing" - "github.com/ion/ion-cli/cli" + "github.com/clearmatics/ion/ion-cli/cli" "github.com/stretchr/testify/assert" ) diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index ed1a27f..5c9f4e4 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ion/ion-cli/config" + "github.com/clearmatics/ion/ion-cli/config" ) func Test_Read_ValidSetupJson(t *testing.T) { diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index 257f0c5..712a9b4 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -5,9 +5,9 @@ package config import ( "log" + "github.com/clearmatics/ion/ion-cli/validation" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ion/ion-cli/validation" ) func InitClient(port string, addr string) (clientTo *ethclient.Client) { diff --git a/ion-cli/main.go b/ion-cli/main.go index c19670e..b4b33a2 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -7,8 +7,8 @@ import ( "fmt" "os" - "github.com/ion/ion-cli/cli" - "github.com/ion/ion-cli/config" + "github.com/clearmatics/ion/ion-cli/cli" + "github.com/clearmatics/ion/ion-cli/config" ) var configFile = flag.String("config", "setup.json", "Description:\n path to the configuration file") From 9acd44e5052e2352a66aff6caa6d511725e64f0e Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 09:48:28 +0100 Subject: [PATCH 037/203] Travis test --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3f2d61d..68484a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ matrix: dist: trusty go: 1.8.x script: - - cd ./ion-cli && make test + - cd ./ion-cli && go get ./... + - make test notifications: slack: From ed51329775218073b85a2108890f980185253cfd Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 09:52:51 +0100 Subject: [PATCH 038/203] Travis test again --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 68484a5..3fbaeb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ matrix: dist: trusty go: 1.8.x script: - - cd ./ion-cli && go get ./... + - cd ./ion-cli + - go get github.com/stretchr/testify/assert - make test notifications: From fb5558b538ae3d8de196124e793078e0e585be99 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 09:54:45 +0100 Subject: [PATCH 039/203] Travis test again --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3fbaeb1..567b46b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ matrix: go: 1.8.x script: - cd ./ion-cli - - go get github.com/stretchr/testify/assert + - go dep - make test notifications: From 653610121ad848dda6e56401af1ef7f36afcd65a Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 09:56:37 +0100 Subject: [PATCH 040/203] Travis test again --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 567b46b..fb783ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ matrix: go: 1.8.x script: - cd ./ion-cli - - go dep + - go get -t ./... - make test notifications: From 58f4486a7d2821e25eafdcd16b17b846a092bea2 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 10:06:57 +0100 Subject: [PATCH 041/203] changed go version to 1.9.x for testing --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb783ec..1cca900 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ matrix: include: - os: linux dist: trusty - go: 1.8.x + go: 1.9.x script: - cd ./ion-cli - go get -t ./... From fa18ffb105004a6b0a4f07ca8aceec0cf4c38b24 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 10:22:17 +0100 Subject: [PATCH 042/203] Merged with ion-stage-2 and changed the travis notifications --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1cca900..eaf3140 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,4 +12,6 @@ matrix: notifications: slack: + on_success: never + on_failure: always secure: k6j6BWCTMJ6U7JXhy0yBcJpfkOw4eUNnL9xyufiI6Ue5Cf+NvN9FJxNZvoz4BvVSitq/BSlcWGjQoIW5AoWtf15tl4hvQmFN4YYHT79TKjRGEcSBg1+D55aXmjIM3UwHtCOuSJxAkl7dTgWAJ3FU0/aBqy96OsODjhcP8VeuMay+2Z+kT/QQjtO5rduHfLpeJxVfoEdhXR9QjHozV287rE49E6wWV6KzNCDOYy3CFGkQsgBQzlxkmlvhwbjDeNb72UcruSh50ic78/NLru3AXwRFx2yc1fkr2Nv9q6l5r9I1iWek8EZ46OCe/dQ004s7PI7knVx1vssdA3ksLDyRzhNHvWpn1EI1fi4Aqc+ki9vHbccR5c1pw85zwcQiLEoVFpJ+MpfHi9ExmAJmvvrzz2RBMqsL5JuSfInxiSLyX6vSVpufgZYrDKAemWXhR030dQQZ8BVQOCbt2lzCgHZajmDvrOktq6QdTFzEz/JjyorXn+0Rpho+7FHY5sW9KdgvmexI9SAjjz0BgcQzof9QKpyuRZpbboWRxPsfPUQDlx+Wxm541ndunGNQ2mVXqSgKaTQShiKhhu7dOPevw1a+dreJ6n8afL9pfW4SHcs0O+FlHvAnLAbRDvbnxROF89RRDiTVBdC6h7vcAX6lNDFUxF0F1bYTiWE0s4+umB2zlqc= From b9c60e35839ba187c5f473194cffa1821a80e2a2 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 16:06:59 +0100 Subject: [PATCH 043/203] Some extra testing but blockchain simulator is a bit hard work at times... --- README.md | 15 +- ion-cli/Makefile | 2 + ion-cli/cli/rpc.go | 21 +- ion-cli/cli/rpc_test.go | 11 +- ion-cli/validation/validation_test.go | 52 +++-- test/signature.js | 286 -------------------------- 6 files changed, 69 insertions(+), 318 deletions(-) delete mode 100644 test/signature.js diff --git a/README.md b/README.md index 80a888f..5f6e7f2 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,9 @@ In order to use the smart contracts and run the tests it is necessary to first i ***Note:*** that as the contract searches for specific parts of the block header that only exist in Clique and IBFT, Ganache or Ethash chains cannot be used for the _root_ blockchain from which headers are extracted. +### Requirements +* golang version: 1.9.x + ### Initialise Clique PoA Blockchain The instructions are based on the tutorial of [Salanfe](https://hackernoon.com/setup-your-own-private-proof-of-authority-ethereum-network-with-geth-9a0a3750cda8) but has the more complicated parts already initialised. @@ -44,9 +47,9 @@ Which hopefully returns this: ├── docs ├── ion-cli ├── LICENSE +├── Makefile ├── migrations ├── package.json -├── package-lock.json ├── poa-network ├── README.md ├── test @@ -102,7 +105,15 @@ The Ion CLI is a tool for handling the passing of block headers between to block In its current form the Ion CLI allows the user to connect to two separate blockchains, via RPC, and submit block headers to a validation contract. -#### Running the CLI +#### Testing Ion CLI +``` +$ cd ion-cli +$ make build +$ make test +``` +If the tests pass successfully then the CLI can be run. + +#### Running Ion CLI As mentioned in the project description this simple implementation of the validation contract is active only on a single blockchain, however the CLI is simulating the passing of the headers to and from as if it were between separate chains. Having followed the instructions on how to setup a Clique blockchain, which is hosted on `127.0.0.1:8501`, we run a ganache-cli in another terminal on `127.0.0.1:8545` and deploy the contract to the ganache blockchain, diff --git a/ion-cli/Makefile b/ion-cli/Makefile index 76bed69..d8cf34a 100644 --- a/ion-cli/Makefile +++ b/ion-cli/Makefile @@ -5,6 +5,7 @@ SHELL=/bin/bash clean: @rm -f ion-cli + @rm *.out test: @go test ./... -v @@ -20,6 +21,7 @@ coverage: go tool cover -html=coverage-all.out build: + @go get -t -v ./... @go build -o ion-cli . check: diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 7ca131f..18e49b3 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -14,7 +14,8 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -type Header struct { +// Header used to marshall blocks into a string based struct +type header struct { ParentHash string `json:"parentHash"` UncleHash string `json:"sha3Uncles"` Coinbase string `json:"miner"` @@ -44,7 +45,7 @@ func latestBlock(client *ethclient.Client) { } func getBlock(client *ethclient.Client, block string) { - // var blockHeader Header + // var blockHeader header blockNum := new(big.Int) blockNum.SetString(block, 10) @@ -65,7 +66,7 @@ func getBlock(client *ethclient.Client, block string) { // func calculateRlpEncoding(client *ethclient.Client, block string) { func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []byte, prefixBlock []byte, prefixExtra []byte) { - var blockHeader Header + var blockHeader header blockNum := new(big.Int) blockNum.SetString(block, 10) @@ -101,15 +102,15 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", prefixBlock) // Generate an interface to encode the blockheader without the signature in the extraData - prefixExtra = EncodeExtraData(blockHeader) + prefixExtra = encodeExtraData(blockHeader) fmt.Printf("\nExtraData Field Prefix:\n%+x\n", prefixExtra) return rlpBlock, prefixBlock, prefixExtra } -// calculate prefix of the entire signed block -func EncodePrefix(blockHeader Header) (prefix []byte) { +// EncodePrefix calculate prefix of the entire signed block +func encodePrefix(blockHeader header) (prefix []byte) { blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] blockInterface := GenerateInterface(blockHeader) encodedPrefixBlock := encodeBlock(blockInterface) @@ -117,8 +118,8 @@ func EncodePrefix(blockHeader Header) (prefix []byte) { return encodedPrefixBlock[1:3] } -// calculate prefix of the extraData with the signature -func EncodeExtraData(blockHeader Header) (prefix []byte) { +// EncodeExtraData calculate prefix of the extraData with the signature +func encodeExtraData(blockHeader header) (prefix []byte) { blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] encExtra, err := hex.DecodeString(blockHeader.Extra[2:]) if err != nil { @@ -131,8 +132,8 @@ func EncodeExtraData(blockHeader Header) (prefix []byte) { return encodedExtraData[0:1] } -// Creates an interface for a block -func GenerateInterface(blockHeader Header) (rest interface{}) { +// GenerateInterface Creates an interface for a block +func GenerateInterface(blockHeader header) (rest interface{}) { blockInterface := []interface{}{} s := reflect.ValueOf(&blockHeader).Elem() diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index 9b758d7..da4e3c9 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -1,6 +1,6 @@ // Copyright (c) 2018 Clearmatics Technologies Ltd -package cli_test +package cli import ( "encoding/hex" @@ -9,7 +9,6 @@ import ( "io/ioutil" "testing" - "github.com/clearmatics/ion/ion-cli/cli" "github.com/stretchr/testify/assert" ) @@ -25,9 +24,9 @@ func Test_EncodePrefix(t *testing.T) { } // Marshall fake block into the Header - var blockHeader cli.Header + var blockHeader header json.Unmarshal(raw, &blockHeader) - prefix := cli.EncodePrefix(blockHeader) + prefix := encodePrefix(blockHeader) assert.Equal(t, expectedPrefix, prefix) @@ -45,9 +44,9 @@ func Test_EncodeExtraDataPrefix(t *testing.T) { } // Marshall fake block into the Header - var blockHeader cli.Header + var blockHeader header json.Unmarshal(raw, &blockHeader) - prefix := cli.EncodeExtraData(blockHeader) + prefix := encodeExtraData(blockHeader) assert.Equal(t, expectedPrefix, prefix) diff --git a/ion-cli/validation/validation_test.go b/ion-cli/validation/validation_test.go index 4dc6eba..a3c4e17 100644 --- a/ion-cli/validation/validation_test.go +++ b/ion-cli/validation/validation_test.go @@ -12,8 +12,15 @@ import ( "github.com/stretchr/testify/assert" ) +// Initialisation array +var val1 = common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") +var val2 = common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") +var initValidators = []common.Address{val1, val2} + +var genesisString = "c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28" + // Test inbox contract gets deployed correctly -func TestDeployValidation(t *testing.T) { +func Test_DeployValidation(t *testing.T) { //Setup simulated block chain key, _ := crypto.GenerateKey() @@ -22,19 +29,14 @@ func TestDeployValidation(t *testing.T) { alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} blockchain := backends.NewSimulatedBackend(alloc) - // Initialisation array - val1 := common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") - val2 := common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") - validators := []common.Address{val1, val2} - genesisHash := [32]byte{} - copy(genesisHash[:], []byte("c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28")) + copy(genesisHash[:], []byte(genesisString)) // Deploy contract address, _, _, err := DeployValidation( auth, blockchain, - validators, + initValidators, genesisHash, ) // commit all pending transactions @@ -60,13 +62,8 @@ func TestGetValidators(t *testing.T) { alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} blockchain := backends.NewSimulatedBackend(alloc) - // Initialisation array - val1 := common.HexToAddress("0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d") - val2 := common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") - initValidators := []common.Address{val1, val2} - genesisHash := [32]byte{} - copy(genesisHash[:], []byte("c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28")) + copy(genesisHash[:], []byte(genesisString)) // Deploy contract _, _, contract, _ := DeployValidation( @@ -83,3 +80,30 @@ func TestGetValidators(t *testing.T) { assert.Equal(t, validators[1], val2) } + +// Test that the latest block returns the last submitted block hash +func Test_LatestBlock(t *testing.T) { + + //Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} + blockchain := backends.NewSimulatedBackend(alloc) + + genesisHash := [32]byte{} + copy(genesisHash[:], []byte(genesisString)) + + // Deploy contract + _, _, contract, _ := DeployValidation( + auth, + blockchain, + initValidators, + genesisHash, + ) + // commit all pending transactions + blockchain.Commit() + + latestBlock, _ := contract.LatestBlock(&bind.CallOpts{}) + assert.Equal(t, latestBlock, genesisHash) +} diff --git a/test/signature.js b/test/signature.js deleted file mode 100644 index fc46b3c..0000000 --- a/test/signature.js +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3 = require('web3'); -const Web3Utils = require('web3-utils'); -const Web3Abi = require('web3-eth-abi'); -const Web3Accounts = require('web3-eth-accounts'); -const rlp = require('rlp'); - -const Recover = artifacts.require("Recover"); - - -const web3 = new Web3(); - -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); - -function hexToBytes(hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; -} - -function bytesToHex(bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(""); -} - -contract('signatures.js', (accounts) => { - const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join('') - - it('Test: VerifyBlockHash()', async () => { - const recover = await Recover.new(); - const accounts = web3.eth.accounts; - const signer = accounts[0]; - - // Get a single block - const block = web3.eth.getBlock(10); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraData, - mixHash, - nonce - ]; - - const encodedHeader = rlp.encode(header); - - const headerHash = Web3Utils.sha3(encodedHeader); - assert.equal(block.hash, headerHash); - }) - - it('Test: VerifySignedHash()', async () => { - const recover = await Recover.new(); - const accounts = web3.eth.accounts; - const signer = accounts[0]; - - // Get a single block - const block = web3.eth.getBlock(10); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - // Remove last 65 Bytes of extraData - const extraBytes = hexToBytes(extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - const encodedHeader = rlp.encode(header); - - const headerHash = Web3Utils.sha3(encodedHeader); - - const ecrecoveryReceipt = await recover.VerifyHash(headerHash, extraDataSignature); - const ecrecoveryExpected = ecrecoveryReceipt.logs[0].args['owner']; - assert.equal(ecrecoveryExpected, signer); - }) - - it('Test: VerifyBlock()', async () => { - const recover = await Recover.new(); - const accounts = web3.eth.accounts; - const signer = accounts[0]; - - // Get a single block - const block = web3.eth.getBlock(10); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - // Remove last 65 Bytes of extraData - const extraBytes = hexToBytes(extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - const encodedHeader = '0x' + rlp.encode(header).toString('hex'); - const headerHash = Web3Utils.sha3(encodedHeader); - - const ecrecoveryReceipt = await recover.VerifyBlock(encodedHeader, extraDataSignature); - const recoveredParentHash = ecrecoveryReceipt.logs[0].args['parentHash'] - const recoveredRootHash = ecrecoveryReceipt.logs[0].args['rootHash'] - const ecrecoveryExpected = ecrecoveryReceipt.logs[1].args['owner']; - assert.equal(recoveredParentHash, parentHash); - assert.equal(recoveredRootHash, root); - assert.equal(ecrecoveryExpected, signer); - }) - - it('Test: ExtractSignature()', async () => { - const recover = await Recover.new(); - const accounts = web3.eth.accounts; - const signer = accounts[0]; - - // Get a single block - const block = web3.eth.getBlock(10); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - // Remove last 65 Bytes of extraData - const extraBytes = hexToBytes(extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - const blockHeader = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraData, - mixHash, - nonce - ]; - - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - const encodedBlockHeader = '0x' + rlp.encode(blockHeader).toString('hex'); - const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - assert.equal(block.hash, blockHeaderHash); - - const encodedHeader = '0x' + rlp.encode(header).toString('hex'); - const headerHash = Web3Utils.sha3(encodedHeader); - - // The new prefixes should be calculated off chain - const prefixHeader = '0x0214'; - const prefixExtraData = '0xa0'; - - const ecrecoveryReceipt = await recover.ExtractHash(encodedBlockHeader, prefixHeader, prefixExtraData); - const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; - const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; - assert.equal(block.hash, recoveredBlockHash) - assert.equal(recoveredSignature, signer); - }) -}); From 20b3a586bd1730471882afc420be618250b5d326 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 29 Jun 2018 17:08:52 +0100 Subject: [PATCH 044/203] Changed the extraction of hashes to assembly seems to have made little impact upon performance but hey ho... --- contracts/Validation.sol | 23 ++++++++++++----------- test/validation.js | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index a125b4b..db513c5 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -87,25 +87,25 @@ contract Validation { bytes memory headerEnd = new bytes(42); // Extract the start of the header and replace the length - extractData(headerStart, header, 0, headerStart.length); + extractData(headerStart, header, 0); assembly { let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) } // Extract the real extra data and create the signed hash - extractData(extraData, header, length-140, extraData.length); + extractData(extraData, header, length-140); assembly { - let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) + let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) } // Extract the end of the header - extractData(headerEnd, header, length-42, headerEnd.length); + extractData(headerEnd, header, length-42); bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); bytes32 hashData = keccak256(newHeader); // Extract the signature of the hash create above - extractData(extraDataSig, header, length-107, extraDataSig.length); + extractData(extraDataSig, header, length-107); address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); require(m_validators[sig_addr]==true, "Signer not a validator!"); @@ -149,13 +149,14 @@ contract Validation { /* * @param data memory allocation for the data you need to extract * @param sig array from which the data should be extracted - * @param start index which the data starts within the byte array - * @param length total length of the data to be extracted + * @param start index which the data starts within the byte array needs to have 32 bytes appended */ - function extractData(bytes data, bytes input, uint start, uint length) private pure { - for (uint i=0; i { +contract('validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From a9a31682fc36293beef2c680b2af0f49029a0a16 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 2 Jul 2018 13:37:38 +0100 Subject: [PATCH 045/203] Removed some of the assembly stuff into a nice library --- contracts/SolidityUtils.sol | 34 ++++++++++++++++++++++++++++++++++ contracts/Validation.sol | 27 ++++++--------------------- 2 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 contracts/SolidityUtils.sol diff --git a/contracts/SolidityUtils.sol b/contracts/SolidityUtils.sol new file mode 100644 index 0000000..0707c19 --- /dev/null +++ b/contracts/SolidityUtils.sol @@ -0,0 +1,34 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +// A library of funky data manipulation stuff +library SolUtils { + /* + * @description copies 32 bytes from input into the output + * @param output memory allocation for the data you need to extract + * @param input array from which the data should be extracted + * @param buf index which the data starts within the byte array needs to have 32 bytes appended + */ + function BytesToBytes32(bytes input, uint256 buf) internal pure returns (bytes32 output) { + buf = buf + 32; + assembly { + output := mload(add(input, buf)) + } + } + + /* + * @description copies output.length bytes from the input into the output + * @param output memory allocation for the data you need to extract + * @param input array from which the data should be extracted + * @param buf index which the data starts within the byte array + */ + function BytesToBytes(bytes output, bytes input, uint256 buf) constant internal { + uint256 outputLength = output.length; + buf = buf + 32; // Append 32 as we need to point past the variable type definition + assembly { + let ret := staticcall(3000, 4, add(input, buf), outputLength, add(output, 32), outputLength) + } + } + +} diff --git a/contracts/Validation.sol b/contracts/Validation.sol index db513c5..3120711 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.23; import "./ECVerify.sol"; +import "./SolidityUtils.sol"; contract Validation { address Owner; @@ -70,10 +71,7 @@ contract Validation { */ function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public { // Check the parent hash is the same as the previous block submitted - bytes32 _parentBlockHash; - assembly { - _parentBlockHash := mload(add(header, 36)) - } + bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header, 4); require(_parentBlockHash==blockHash, "Not child of previous block!"); uint256 length = header.length; @@ -87,25 +85,25 @@ contract Validation { bytes memory headerEnd = new bytes(42); // Extract the start of the header and replace the length - extractData(headerStart, header, 0); + SolUtils.BytesToBytes(headerStart, header, 0); assembly { let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) } // Extract the real extra data and create the signed hash - extractData(extraData, header, length-140); + SolUtils.BytesToBytes(extraData, header, length-140); assembly { let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) } // Extract the end of the header - extractData(headerEnd, header, length-42); + SolUtils.BytesToBytes(headerEnd, header, length-42); bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); bytes32 hashData = keccak256(newHeader); // Extract the signature of the hash create above - extractData(extraDataSig, header, length-107); + SolUtils.BytesToBytes(extraDataSig, header, length-107); address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); require(m_validators[sig_addr]==true, "Signer not a validator!"); @@ -146,17 +144,4 @@ contract Validation { output = header; } - /* - * @param data memory allocation for the data you need to extract - * @param sig array from which the data should be extracted - * @param start index which the data starts within the byte array needs to have 32 bytes appended - */ - function extractData(bytes data, bytes input, uint256 buffer) private view { - uint256 dataLength = data.length; - buffer = buffer + 32; - assembly { - let ret := staticcall(3000, 4, add(input, buffer), dataLength, add(data, 32), dataLength) - } - } - } From b7f777e83243d0c9db969b47d595d68019fd4fd9 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 2 Jul 2018 14:27:29 +0100 Subject: [PATCH 046/203] added some documentation --- docs/Roadmap.md | 102 ++++++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 50f82af..c06e3ee 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -36,42 +36,40 @@ In order to perform a cross-chain PvP payment we must: ### Assumptions Listed here are the assumptions with which the project is being developed: * Ethereum-based blockchain - * PBFT Consensus Protocol or other immediate-finality algorithms + * IBFT Consensus Protocol or other immediate-finality algorithms * Permissioned network * Validator set is known and assumed as correct ## Project Planning -Ion stage 2 will be developed using agile methodologies, with weekly sprints. Note that the sprint objective will remain dynamic and should change as the project continues. +Ion stage 2 will be developed using agile methodologies, with fortnightly sprints. Note that the sprint objective will remain dynamic and should change as the project continues. -### Sprint 1 - PoC Final Proposal Definition. -Date: 04.06.2018 - 08.06.2018 - -Description: -We aim to describe fully how the Phase 1 PoC would work, detailing in entirety the functionality of all smart-contracts to be developed. - -Output: - * Project specification. +## Project Planning +Ion stage 2 will be developed using agile methodologies, with fortnightly sprints. Note that the sprint objective will remain dynamic and should change as the project continues. -### Sprint 2 - Skeleton Implementation -Date: 11.06.2018 - 15.06.2018 +### Sprint 6 - Minimal Viabable Ion Stage 2 +Date: 16.07.2018 - 23.07.2018 Description: -It should be shown that it is indeed possible to prove the state of a foreign on a native chain and make assertions of that state. Separately it should be shown that the validators from foreign chain can be added to the native chain. Blocks submitted and validated on the foreign chain validated on the native chain using the signature of the foreign validator set. +Various separated components should be integrated with required tooling and documentation. -Output: - * Smart contract for state proof verification - * Tests for state proofs - * Smart contract for block validation - * Tests for block validation +Goals: + * Ability to submit and verify proofs against Ion Relay contract -### Sprint 3 - Validation of Passed State -Date: 18.06.2018 - 22.06.2018 +Achieved: + +### Sprint 5 - Off-Chain Proof Generation +Date: 02.07.2018 - 13.07.2018 Description: -The two separate problems of validation and proofs should be integrated and a minimum smart-contract that allows the immediate validation of a submitted block be developed. +We aim to be able to generate proofs _off-chain_, preferably using the Ion CLI. This is the key part to being able to make claims against state _on-chain_. -Output: - * Single contract which allows state proof and block validation to be performed simultaneously +Goals: + * Research indepth the complexities of creating continually executing smart-contracts and update specification + * Generate off-chain proofs of state transition + * Begin research into the outline of potential use cases i.e. PvP + * Increase testing coverage of smart contracts and Ion CLI + +Achieved: ### Sprint 4 - User Flow Development Date: 25.06.2018 - 29.06.2018 @@ -79,30 +77,58 @@ Date: 25.06.2018 - 29.06.2018 Description: Given the original user stories the smart contract should now contain minimum functions necessary to interact with the project. This should naturally be an extension of the previous week to smooth out the integration and interaction flows of the stack. -Output: +Goals: * Smart contract should now have protection for edge-cases * Addition of user permissioniong * Automation of block generation + * Tutorial CLI and Validation contract + * CLI Golang + +Achieved: + * Automation of block generation + * Tutorial CLI and Validation contract + * CLI Golang -### Sprint 5 - Tooling and Documentation -Date: 02.07.2018 - 06.07.2018 +Notes: + * Sprints changed to fortnightly from this point onwards + +### Sprint 3 - Validation of Passed State +Date: 18.06.2018 - 22.06.2018 + +Description: +The two separate problems of validation and proofs should be integrated and a minimum smart-contract that allows the immediate validation of a submitted block be developed. + +Goals: + * Single contract which allows state proof and block validation to be performed simultaneously + +Achieved: + +### Sprint 2 - Skeleton Implementation +Date: 11.06.2018 - 15.06.2018 Description: -Develop the tooling and documentation necessary for users to clone the repository and run the base functions immediately. We should write enough API documentation to allow developers to immediately be able to interface their own interoperability contracts to the Relay contract. +It should be shown that it is indeed possible to prove the state of a foreign on a native chain and make assertions of that state. Separately it should be shown that the validators from foreign chain can be added to the native chain. Blocks submitted and validated on the foreign chain validated on the native chain using the signature of the foreign validator set. + +Goals: + * Smart contract for state proof verification + * Tests for state proofs + * Smart contract for block validation + * Tests for block validation + +Achieved: -Output: - * CLI - * Tutorial - * Development Documentation -### Sprint 6 - Testing and QA -Date: 09.07.2018 - 13.07.2018 +### Sprint 1 - PoC Final Proposal Definition. +Date: 04.06.2018 - 08.06.2018 Description: -Enhance testing to show attack resilience and any known vulnerabilities. +We aim to describe fully how the Phase 1 PoC would work, detailing in entirety the functionality of all smart-contracts to be developed. + +Goals: + * Project specification. + +Achieved: + * Specification was released + -Output: - * Complete test coverage - * Code Review - * Documentation of all possible vulnerabilities From 77b488630678712fd2a730deca6b18ec30b9b679 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 2 Jul 2018 14:46:21 +0100 Subject: [PATCH 047/203] Ammendments ot roadmap --- docs/Roadmap.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/Roadmap.md b/docs/Roadmap.md index c06e3ee..4cb8cef 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -54,6 +54,7 @@ Various separated components should be integrated with required tooling and docu Goals: * Ability to submit and verify proofs against Ion Relay contract + * Execute contract given state transition Achieved: @@ -64,8 +65,9 @@ Description: We aim to be able to generate proofs _off-chain_, preferably using the Ion CLI. This is the key part to being able to make claims against state _on-chain_. Goals: - * Research indepth the complexities of creating continually executing smart-contracts and update specification - * Generate off-chain proofs of state transition + * Research indepth the complexities of creating continually executing smart-contracts + * Update Ion specification + * Generate off-chain proofs of state transition: Solidity, Golang, and Ion CLI Integration * Begin research into the outline of potential use cases i.e. PvP * Increase testing coverage of smart contracts and Ion CLI From 25e2c35bfb6de59a949f0daff099e765d1d414a3 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 2 Jul 2018 17:01:12 +0100 Subject: [PATCH 048/203] Added some tutorial for the Ion CLI **cough** documentation --- docs/Ion-CLI.md | 92 +++++++++++++++++++ ion-cli/cli/cli.go | 10 +- ion-cli/config/init.go | 6 +- .../{validation => contracts}/validation.go | 2 +- .../validation_test.go | 2 +- 5 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 docs/Ion-CLI.md rename ion-cli/{validation => contracts}/validation.go (99%) rename ion-cli/{validation => contracts}/validation_test.go (99%) diff --git a/docs/Ion-CLI.md b/docs/Ion-CLI.md new file mode 100644 index 0000000..7243caf --- /dev/null +++ b/docs/Ion-CLI.md @@ -0,0 +1,92 @@ +# Ion Command Line Interface +The Ion CLI is a tool which allows users to easily interact with the Ion project. Written in golang it allows rapid development of new commands and contracts by leveraging the [ishell](https://github.com/abiosoft/ishell) and [go-ethereum smart contract bindings](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts). + +***Note:*** The Ion CLI is not a trusted part of the Ion infrastructure rather it is just a tool to facilitate users, who should verify it functionality prior to using any unknown code. + +## Running Ion CLI +In order to compile the Ion CLI run: +``` +$ cd /path/to/validation/src +$ make build +$ make test +``` + +Given all tests pass, the Ion CLI can be run. Prior to running the user must ensure that the `setup.json` file has been modified to contain: + + * Address and port of foreign Clique chain rpc + * Address and port of native chain rpc + * User account on foreign Clique chain + * User account on native chain + * Address of the deployed validation contract on native + +Once this has been setup correctly the CLI can be launched as follows: +``` +$ ./ion-cli -config [/path/to/setup.json] +=============================================================== +Ion Command Line Interface + +RPC Client [to]: +Listening on: 127.0.0.1:8501 +User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d +Ion Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f + +RPC Client [from]: +Listening on: 127.0.0.1:8545 +User Account: 0x8671e5e08d74f338ee1c462340842346d797afd3 +=============================================================== +>>> +``` + +Running help displays the available commands: +``` +>>> help + +Commands: + clear clear the screen + exit exit the program + getBlock use: getBlock [integer] + description: Returns block header specified + getValidators use: getValidators + description: Returns the whitelist of validators from validator contract + help display help + latestBlock use: latestBlock + description: Returns number of latest block mined/sealed + latestValidationBlock use: latestValidationBlock + description: Returns hash of the last block submitted to the validation contract + submitValidationBlock use: submitValidationBlock [integer] + description: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract +``` + +### Tutorial + + +## Extending the Ion CLI +In order to add your contract to the Ion CLI first a golang version of the solidity smart contract needs to be created, to do this we follow the instructions from [go-ethereum smart contract bindings](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts). + +We will add a contract called `Spoon.sol` to the CLI. This requires the generation of the `abi` and `bin` files. To do this run: +``` +$ npm run genbin +$ npm run genabi +``` +Now the latest versions of the `abi` and `bin` files will be found in the `/path/to/ion/contracts/` directory. Next generate the `.go` version of the desired smart contract using the `abigen` to do so run: +``` +$ abigen --bin=/path/to/Spoon.bin --abi /path/to/Spoon.abi --pkg contract --type Spoon --out Spoon.go +``` +next place the output `Spoon.go` in the package specific directory for your golang code. The contract can then be interfaced with simply through importing the contract package. + +### Golang Smart Contract Interface +Given the exisiting Ion CLI framework any additional contracts should be placed in the `ion/ion-cli/contracts/` directory and appended to the contract package. + +To use an instance of the Spoon contract insert: +``` +func InitSpoonContract(setup Setup, client *ethclient.Client) (Spoon *contract.Spoon) { + // Initialise the contract + address := common.HexToAddress(setup.Ion) + Spoon, err := contract.NewSpoon(address, client) + if err != nil { + log.Fatal(err) + } + + return +} +``` diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 9eb1e75..a000347 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -15,11 +15,11 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/clearmatics/ion/ion-cli/config" - "github.com/clearmatics/ion/ion-cli/validation" + contract "github.com/clearmatics/ion/ion-cli/contracts" ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *validation.Validation) { +func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contract.Validation) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -45,6 +45,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *valida Help: "use: latestBlock \n\t\t\t\tdescription: Returns number of latest block mined/sealed", Func: func(c *ishell.Context) { c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) c.Println("Get latest block number:") latestBlock(clientFrom) c.Println("===============================================================") @@ -57,6 +58,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *valida Help: "use: getBlock [integer] \n\t\t\t\tdescription: Returns block header specified", Func: func(c *ishell.Context) { c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) if len(c.Args) == 0 { c.Println("Input argument required, e.g.: getBlock 10") } else if len(c.Args) > 1 { @@ -73,6 +75,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *valida Help: "use: getValidators \n\t\t\t\tdescription: Returns the whitelist of validators from validator contract", Func: func(c *ishell.Context) { c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) result, err := Validation.GetValidators(&bind.CallOpts{}) if err != nil { fmt.Printf("Error: %s", err) @@ -90,6 +93,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *valida Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo + ":" + setup.PortTo) result, err := Validation.LatestBlock(&bind.CallOpts{}) if err != nil { fmt.Printf("Error: %s", err) @@ -107,6 +111,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *valida Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) blockNum := new(big.Int) blockNum.SetString(c.Args[0], 10) result, err := Validation.GetBlock(&bind.CallOpts{}, blockNum) @@ -128,6 +133,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *valida Help: "use: submitValidationBlock [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo + ":" + setup.PortTo) if len(c.Args) == 0 { c.Println("Select a block") } else if len(c.Args) > 1 { diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index 712a9b4..a88169f 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -5,7 +5,7 @@ package config import ( "log" - "github.com/clearmatics/ion/ion-cli/validation" + contract "github.com/clearmatics/ion/ion-cli/contracts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" ) @@ -20,10 +20,10 @@ func InitClient(port string, addr string) (clientTo *ethclient.Client) { return } -func InitValidationContract(setup Setup, client *ethclient.Client) (Validation *validation.Validation) { +func InitValidationContract(setup Setup, client *ethclient.Client) (Validation *contract.Validation) { // Initialise the contract address := common.HexToAddress(setup.Ion) - Validation, err := validation.NewValidation(address, client) + Validation, err := contract.NewValidation(address, client) if err != nil { log.Fatal(err) } diff --git a/ion-cli/validation/validation.go b/ion-cli/contracts/validation.go similarity index 99% rename from ion-cli/validation/validation.go rename to ion-cli/contracts/validation.go index 70ea041..e34a43a 100644 --- a/ion-cli/validation/validation.go +++ b/ion-cli/contracts/validation.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package validation +package contract import ( "math/big" diff --git a/ion-cli/validation/validation_test.go b/ion-cli/contracts/validation_test.go similarity index 99% rename from ion-cli/validation/validation_test.go rename to ion-cli/contracts/validation_test.go index a3c4e17..acb89b0 100644 --- a/ion-cli/validation/validation_test.go +++ b/ion-cli/contracts/validation_test.go @@ -1,4 +1,4 @@ -package validation +package contract import ( "math/big" From 74d8d3b765ea4f5990c79068bd73c5cfd6098ecb Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 5 Jul 2018 16:47:16 +0100 Subject: [PATCH 049/203] Can create a proof for any given transaction --- contracts/Validation.sol | 13 +++- ion-cli/cli/cli.go | 36 +++++++-- ion-cli/cli/cli_test.go | 6 +- ion-cli/cli/proof.go | 134 ++++++++++++++++++++++++++++++++++ ion-cli/cli/proof_test.go | 38 ++++++++++ ion-cli/cli/test.json | 6 +- ion-cli/config/config.go | 6 +- ion-cli/config/config_test.go | 6 +- ion-cli/config/init.go | 4 +- ion-cli/config/test.json | 10 +-- ion-cli/main.go | 8 +- ion-cli/setup.json | 6 +- 12 files changed, 232 insertions(+), 41 deletions(-) create mode 100644 ion-cli/cli/proof.go create mode 100644 ion-cli/cli/proof_test.go diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 3120711..8909b9c 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -42,21 +42,22 @@ contract Validation { } /* - * Returns the validators array + * @description returns the validators array */ function GetValidators() public view returns (address[] _validators) { return validators; } /* - * Returns the latest block submitted + * @description returns the latest block submitted */ function LatestBlock() public view returns (bytes32 _latestBlock) { return blockHash; } /* - * Returns the latest block submitted + * @description returns information regarding specific block + * @param blockNumber specific block number */ function GetBlock(uint256 blockNumber) public view returns (bytes32 _blockHash, bytes32 _prevBlockHash, uint256 _blockHeight) { _blockHash = m_blockheaders[blockNumber].blockHash; @@ -119,6 +120,12 @@ contract Validation { } + /* + * @description creates header from the original against which the signatures are recovered + * @param headerStart all block header fields until extraData field + * @param extraData extraData field minus signatures + * @param headerEnd all block header fields post extraData field + */ function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { // Get the lengths sorted because they're needed later... uint256 headerStartLength = headerStart.length; diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index a000347..040c73f 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -45,7 +45,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra Help: "use: latestBlock \n\t\t\t\tdescription: Returns number of latest block mined/sealed", Func: func(c *ishell.Context) { c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) + c.Println("Connecting to: " + setup.AddrFrom) c.Println("Get latest block number:") latestBlock(clientFrom) c.Println("===============================================================") @@ -58,7 +58,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra Help: "use: getBlock [integer] \n\t\t\t\tdescription: Returns block header specified", Func: func(c *ishell.Context) { c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) + c.Println("Connecting to: " + setup.AddrFrom) if len(c.Args) == 0 { c.Println("Input argument required, e.g.: getBlock 10") } else if len(c.Args) > 1 { @@ -75,7 +75,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra Help: "use: getValidators \n\t\t\t\tdescription: Returns the whitelist of validators from validator contract", Func: func(c *ishell.Context) { c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) + c.Println("Connecting to: " + setup.AddrFrom) result, err := Validation.GetValidators(&bind.CallOpts{}) if err != nil { fmt.Printf("Error: %s", err) @@ -93,7 +93,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrTo + ":" + setup.PortTo) + c.Println("Connecting to: " + setup.AddrTo) result, err := Validation.LatestBlock(&bind.CallOpts{}) if err != nil { fmt.Printf("Error: %s", err) @@ -111,7 +111,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrFrom + ":" + setup.PortFrom) + c.Println("Connecting to: " + setup.AddrFrom) blockNum := new(big.Int) blockNum.SetString(c.Args[0], 10) result, err := Validation.GetBlock(&bind.CallOpts{}, blockNum) @@ -133,7 +133,31 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra Help: "use: submitValidationBlock [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrTo + ":" + setup.PortTo) + c.Println("Connecting to: " + setup.AddrTo) + if len(c.Args) == 0 { + c.Println("Select a block") + } else if len(c.Args) > 1 { + c.Println("Too many arguments entered.") + } else { + c.Println("RLP encode block: " + c.Args[0]) + encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(clientFrom, c.Args[0]) + res, err := Validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "generateTxProof", + Help: "use: generateTxProof [txHash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo) if len(c.Args) == 0 { c.Println("Select a block") } else if len(c.Args) > 1 { diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index c9f53af..73574ec 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -16,13 +16,11 @@ func Test_Read_ValidSetupJson(t *testing.T) { path := findPath() + "./test.json" setup := config.ReadSetup(path) - assert.Equal(t, "8545", setup.PortTo) - assert.Equal(t, "127.0.0.1", setup.AddrTo) + assert.Equal(t, "127.0.0.1:8545", setup.AddrTo) assert.Equal(t, "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.AccountTo) assert.Equal(t, "../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.KeystoreTo) assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) - assert.Equal(t, "8501", setup.PortFrom) - assert.Equal(t, "127.0.0.1", setup.AddrFrom) + assert.Equal(t, "127.0.0.1:8501", setup.AddrFrom) assert.Equal(t, "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.AccountFrom) assert.Equal(t, "../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.KeystoreFrom) } diff --git a/ion-cli/cli/proof.go b/ion-cli/cli/proof.go new file mode 100644 index 0000000..934e379 --- /dev/null +++ b/ion-cli/cli/proof.go @@ -0,0 +1,134 @@ +package cli + +import ( + "bytes" + "context" + "fmt" + "log" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" + "github.com/maxrobot/go-ethereum/crypto" +) + +// GenerateTxProof takes a transaction and block, returns the trie root, tx index and proof path +func GenerateTxProof(client *ethclient.Client, transaction string, blockNum string) (root common.Hash, txIdx []byte, leaf []byte, proof *ethdb.MemDatabase) { + // Select a specific block + blockNumber := new(big.Int) + blockNumber.SetString(blockNum, 10) + + // Fetch header of block num + header, err := client.HeaderByNumber(context.Background(), blockNumber) + if err != nil { + log.Fatal(err) + } + + // Fetch block of block num + block, err := client.BlockByNumber(context.Background(), header.Number) + if err != nil { + log.Fatal(err) + } + + // Select a transaction, index should be 49 + transx := block.Transaction(common.HexToHash(transaction)) + + // Generate the trie + trieObj := new(trie.Trie) + for idx, tx := range block.Transactions() { + rlpIdx, _ := rlp.EncodeToBytes(uint(idx)) // rlp encode index of transaction + rlpTransaction, _ := rlp.EncodeToBytes(tx) // rlp encode transaction + + trieObj.Update(rlpIdx, rlpTransaction) + + // Get the information about the transaction I care about... + if transx == tx { + txIdx = rlpIdx + leaf = rlpTransaction + } + + } + + root = trieObj.Hash() + + // Generate a merkle proof for a key + proof = ethdb.NewMemDatabase() + trieObj.Prove(txIdx, 0, proof) + if proof == nil { + fmt.Printf("prover: nil proof") + } + + return +} + +// VerifyTxProof takes a transaction and block, returns the trie root, tx index and proof path +func VerifyTxProof(client *ethclient.Client, transaction string, blockNum string) { + // Select a specific block + blockNumber := new(big.Int) + blockNumber.SetString(blockNum, 10) + + // Fetch header of block num + header, err := client.HeaderByNumber(context.Background(), blockNumber) + if err != nil { + log.Fatal(err) + } + // assert.Equal(t, expectedBlockHash, header.Hash()) + + // Fetch block of block num + block, err := client.BlockByNumber(context.Background(), header.Number) + if err != nil { + log.Fatal(err) + } + // assert.Equal(t, expectedBlockHash, block.Hash()) + + // Select a transaction, index should be 49 + transx := block.Transaction(common.HexToHash(transaction)) + var txIdx []byte + var leaf []byte + // fmt.Printf("\nTransaction:\n% 0x", transx.Hash().Bytes()) + + // Generate the trie + trieObj := new(trie.Trie) + for idx, tx := range block.Transactions() { + rlpIdx, _ := rlp.EncodeToBytes(uint(idx)) // rlp encode index of transaction + rlpTransaction, _ := rlp.EncodeToBytes(tx) // rlp encode transaction + + trieObj.Update(rlpIdx, rlpTransaction) + + txRlpHash := crypto.Keccak256Hash(rlpTransaction) + + fmt.Printf("TxHash[%d]: \t% 0x\n\tHash(RLP(Tx)): \t% 0x\n", + idx, tx.Hash().Bytes(), txRlpHash.Bytes()) + + // Get the information about the transaction I care about... + if transx == tx { + txIdx = rlpIdx + leaf = rlpTransaction + } + + } + root := trieObj.Hash() + expectedRoot := block.TxHash() + + fmt.Printf("\nExpected Root:\t%x\nRecovered Root:\t%x\n", expectedRoot, root) + + // Generate a merkle proof for a key + proof := ethdb.NewMemDatabase() + trieObj.Prove(txIdx, 0, proof) + if proof == nil { + fmt.Printf("prover: nil proof") + } + + // Verify the proof + val, _, err := trie.VerifyProof(root, txIdx, proof) + if err != nil { + fmt.Printf("prover: failed to verify proof: %v\nraw proof: %x", err, proof) + } + if !bytes.Equal(val, leaf) { + fmt.Printf("prover: verified value mismatch: have %x, want 'k'", val) + } + fmt.Printf("\nVerified Value:\t%x\nExpected Leaf:\t%x\n", val, leaf) +} diff --git a/ion-cli/cli/proof_test.go b/ion-cli/cli/proof_test.go new file mode 100644 index 0000000..905b1f1 --- /dev/null +++ b/ion-cli/cli/proof_test.go @@ -0,0 +1,38 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package cli_test + +import ( + "encoding/hex" + "log" + "testing" + + "github.com/clearmatics/ion/ion-cli/cli" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/assert" +) + +func initTestClient() (client *ethclient.Client) { + client, err := ethclient.Dial("https://mainnet.infura.io") + if err != nil { + log.Fatal(err) + } + return client +} + +func Test_GenerateTxProof(t *testing.T) { + client := initTestClient() + + var transaction = "0xd828cadfcc7694d314058404506fc10a4dadac72aba68c286b34137da4156630" + + var expectedRootHash = common.HexToHash("0x363d32a031aea0b43d92989f96fa0d19c75f18d93fe86f1e11be79202a614bd0") + expectedLeaf, _ := hex.DecodeString("f8cb8201e1850d09dc3000827c9f9466323324b77d72c65ea76caa918464836498ebd680b864b31d61b000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000561dedea8f2554241222e2f2eb221e625c7fb7b526a03b8772e36e5f5a4ffc4c1e6ef884c72208e6086b5d637591fe2dc7b8559aec9ba02c1da7488bdf45f01f511358b7b79e330b5e9e28bb3a10e6006e112148460801") + expectedIdx, _ := hex.DecodeString("31") // 49 is 31 in hex bytes + var blockNumber = "5904064" + + rootHash, idx, leaf, _ := cli.GenerateTxProof(client, transaction, blockNumber) + assert.Equal(t, expectedRootHash, rootHash) + assert.Equal(t, expectedIdx, idx) + assert.Equal(t, expectedLeaf, leaf) +} diff --git a/ion-cli/cli/test.json b/ion-cli/cli/test.json index eee8470..e682029 100644 --- a/ion-cli/cli/test.json +++ b/ion-cli/cli/test.json @@ -1,11 +1,9 @@ { - "rpc-addr-to":"127.0.0.1", - "rpc-port-to":"8545", + "rpc-to":"127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-addr-from":"127.0.0.1", - "rpc-port-from":"8501", + "rpc-from":"127.0.0.1:8501", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 0aaf5d2..419f7c1 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -10,12 +10,10 @@ import ( // Settings type Setup struct { - PortTo string `json:"rpc-port-to"` - AddrTo string `json:"rpc-addr-to"` + AddrTo string `json:"rpc-to"` AccountTo string `json:"account-to"` KeystoreTo string `json:"keystore-to"` - PortFrom string `json:"rpc-port-from"` - AddrFrom string `json:"rpc-addr-from"` + AddrFrom string `json:"rpc-from"` AccountFrom string `json:"account-from"` KeystoreFrom string `json:"keystore-from"` Ion string `json:"ion-addr"` diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 5c9f4e4..52d125f 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -16,10 +16,8 @@ func Test_Read_ValidSetupJson(t *testing.T) { path := findPath() + "./test.json" setup := config.ReadSetup(path) - assert.Equal(t, "8501", setup.PortTo) - assert.Equal(t, "127.0.0.1", setup.AddrTo) - assert.Equal(t, "8502", setup.PortFrom) - assert.Equal(t, "127.0.0.1", setup.AddrFrom) + assert.Equal(t, "127.0.0.1:8545", setup.AddrTo) + assert.Equal(t, "127.0.0.1:8501", setup.AddrFrom) assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) } diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index a88169f..e990209 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -10,9 +10,9 @@ import ( "github.com/ethereum/go-ethereum/ethclient" ) -func InitClient(port string, addr string) (clientTo *ethclient.Client) { +func InitClient(addr string) (clientTo *ethclient.Client) { // Connect to the RPC Client - clientTo, err := ethclient.Dial("http://" + addr + ":" + port) + clientTo, err := ethclient.Dial("http://" + addr) if err != nil { log.Fatalf("could not create RPC client: %v", err) } diff --git a/ion-cli/config/test.json b/ion-cli/config/test.json index 0c55e28..e682029 100644 --- a/ion-cli/config/test.json +++ b/ion-cli/config/test.json @@ -1,11 +1,9 @@ { - "rpc-addr-to":"127.0.0.1", - "rpc-port-to":"8501", + "rpc-to":"127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-addr-from":"127.0.0.1", - "rpc-port-from":"8502", - "account-from":"0x8671e5e08d74f338ee1c462340842346d797afd3", - "keystore-from":"../poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3" + "rpc-from":"127.0.0.1:8501", + "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/ion-cli/main.go b/ion-cli/main.go index b4b33a2..5aac1be 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -19,8 +19,8 @@ func main() { if *configFile != "" { setup := config.ReadSetup(*configFile) - clientTo := config.InitClient(setup.PortTo, setup.AddrTo) - clientFrom := config.InitClient(setup.PortFrom, setup.AddrFrom) + clientTo := config.InitClient(setup.AddrTo) + clientFrom := config.InitClient(setup.AddrFrom) Validation := config.InitValidationContract(setup, clientTo) @@ -40,11 +40,11 @@ func printInfo(setup config.Setup) { fmt.Println("===============================================================") fmt.Println("Ion Command Line Interface\n") fmt.Println("RPC Client [to]:") - fmt.Println("Listening on: " + setup.AddrTo + ":" + setup.PortTo) + fmt.Println("Listening on: " + setup.AddrTo) fmt.Println("user Account: " + setup.AccountTo) fmt.Println("Ion Contract: " + setup.Ion) fmt.Println("\nRPC Client [from]: ") - fmt.Println("Listening on: " + setup.AddrFrom + ":" + setup.PortFrom) + fmt.Println("Listening on: " + setup.AddrFrom) fmt.Println("user Account: " + setup.AccountFrom) fmt.Println("===============================================================") } diff --git a/ion-cli/setup.json b/ion-cli/setup.json index eee8470..e682029 100644 --- a/ion-cli/setup.json +++ b/ion-cli/setup.json @@ -1,11 +1,9 @@ { - "rpc-addr-to":"127.0.0.1", - "rpc-port-to":"8545", + "rpc-to":"127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-addr-from":"127.0.0.1", - "rpc-port-from":"8501", + "rpc-from":"127.0.0.1:8501", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } From c16969a04a31070898ae01bde6c95c418e76d438 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 11 Jul 2018 19:09:40 +0100 Subject: [PATCH 050/203] Patricia proof verifications finally working. Tests working against Tx proofs. --- contracts/Ion.sol | 37 +++++++- contracts/PatriciaTrie.sol | 117 +++++++++++++++++++++++ contracts/RLP.sol | 68 ++++++++------ migrations/2_deploy_contracts.js | 3 + package.json | 4 + test/helpers/trie.js | 0 test/ion.js | 155 ++++++++++++++++++++++++++----- tooling/ion.py | 38 -------- tooling/trie.py | 0 truffle.js | 14 +-- 10 files changed, 336 insertions(+), 100 deletions(-) create mode 100644 contracts/PatriciaTrie.sol create mode 100644 test/helpers/trie.js delete mode 100644 tooling/ion.py create mode 100644 tooling/trie.py diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 72fd4aa..b6a97ce 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -1,6 +1,7 @@ pragma solidity ^0.4.23; import "./RLP.sol"; +import "./PatriciaTrie.sol"; contract Ion { using RLP for RLP.RLPItem; @@ -30,6 +31,7 @@ contract Ion { chainId = _id; } + event VerifiedTxProof(bytes32 chainId, bytes32 blockHash); /* ======================================================================================================================== @@ -56,6 +58,19 @@ contract Ion { _; } + modifier onlyExistingBlocks(bytes32 _id, bytes32 _hash) { + bool blockExists = false; + bytes32[] hashes = m_blockhashes[_id]; + for (uint i = 0; i < hashes.length; i++) { + if (_hash == hashes[i]) { + blockExists = true; + break; + } + } + require(blockExists, "Block does not exist for chain"); + _; + } + /* ======================================================================================================================== @@ -102,7 +117,27 @@ contract Ion { addBlockHashToChain(_id, _blockHash); } - function CheckTxProof() public { + /* + * CheckTxProof + * param: _id (bytes32) Unique id of chain submitting block from + * param: _blockHash (bytes32) Block hash of block being submitted + * param: _value (bytes) RLP-encoded transaction object array with fields defined as: https://github.com/ethereumjs/ethereumjs-tx/blob/0358fad36f6ebc2b8bea441f0187f0ff0d4ef2db/index.js#L50 + * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove + * param: _path (bytes) Byte array of the path to the node to be proved + * + * emits: VerifiedTxProof(chainId, blockHash) + * chainId: (bytes32) hash of the chain verifying proof against + * blockHash: (bytes32) hash of the block verifying proof against + * + * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution + * of this function to only allow if the chain the proof is for is registered to this contract and if the block that + * the proof is for has been submitted. + */ + function CheckTxProof(bytes32 _id, bytes32 _blockHash, bytes _value, bytes _parentNodes, bytes _path) onlyRegisteredChains(_id) onlyExistingBlocks(_id, _blockHash) public returns (bool) { + BlockHeader storage blockHeader = m_blockheaders[_blockHash]; + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.txRootHash) ); + emit VerifiedTxProof(_id, _blockHash); + return true; } function CheckReceiptProof() public { diff --git a/contracts/PatriciaTrie.sol b/contracts/PatriciaTrie.sol new file mode 100644 index 0000000..73cdb6c --- /dev/null +++ b/contracts/PatriciaTrie.sol @@ -0,0 +1,117 @@ +pragma solidity ^0.4.23; + +import "./RLP.sol"; + +library PatriciaTrie { + + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) returns (bool) { + RLP.RLPItem memory nodes = RLP.toRLPItem(_parentNodes); + RLP.RLPItem[] memory parentNodes = RLP.toList(nodes); + + bytes32 currentNodeKey = _root; + bytes memory b_currentNode; + RLP.RLPItem[] memory currentNode; + + uint traversedNibbles = 0; + bytes memory path = toNibbleArray(_path, false); + + for (uint i = 0; i < parentNodes.length; i++) { + b_currentNode = RLP.toBytes(parentNodes[i]); + + if (currentNodeKey != keccak256(b_currentNode)) { + return false; + } + + currentNode = RLP.toList(parentNodes[i]); + + if (currentNode.length == 17) { + // Branch Node + if (traversedNibbles == path.length) { + + if(keccak256(RLP.toBytes(currentNode[16])) == keccak256(_value)) { + return true; + } else { + return false; + } + } + + uint16 nextPathNibble = uint16(path[traversedNibbles]); + currentNodeKey = RLP.toBytes32(currentNode[nextPathNibble]); + traversedNibbles += 1; + + } else if (currentNode.length == 2) { + // Extension/Leaf Node + bytes memory nextPathNibbles = RLP.toData(currentNode[0]); + traversedNibbles += toNibbleArray(nextPathNibbles, true).length; + + if (traversedNibbles == path.length) { + if(keccak256(RLP.toData(currentNode[1])) == keccak256(_value)) { + return true; + } else { + return false; + } + } + + // Reached a leaf before end of the path. Proof false. + if (toNibbleArray(nextPathNibbles, true).length == 0) { + return false; + } + + bytes memory nextNodeKey = RLP.toData(currentNode[1]); + currentNodeKey = bytesToBytes32(nextNodeKey, 0); + } else { + return false; + } + } + } + + function toNibbleArray(bytes b, bool hexPrefixed) private returns (bytes) { + bytes memory nibbleArray = new bytes(255); + + uint8 nibblesFound = 0; + for (uint i = 0; i < b.length; i++) { + byte[2] memory nibbles = byteToNibbles(b[i]); + + if (hexPrefixed && i == 0) { + if (nibbles[0] == 1 || nibbles[0] == 3) { + nibbleArray[nibblesFound] = nibbles[1]; + nibblesFound += 1; + } + } else { + nibbleArray[nibblesFound] = nibbles[0]; + nibbleArray[nibblesFound + 1] = nibbles[1]; + nibblesFound += 2; + } + } + + bytes memory finiteNibbleArray = new bytes(nibblesFound); + for (uint j = 0; j < nibblesFound; j++) { + finiteNibbleArray[j] = nibbleArray[j]; + } + return finiteNibbleArray; + } + + function byteToNibbles(byte b) private pure returns (byte[2]) { + byte firstNibble = rightShift(b, 4); + byte secondNibble = b & 0xf; + + return [firstNibble, secondNibble]; + } + + function leftShift(byte i, uint8 bits) private pure returns (byte) { + return byte(uint8(i) * 2 ** bits); + } + + function rightShift(byte i, uint8 bits) private pure returns (byte) { + return byte(uint8(i) / 2 ** bits); + } + + function bytesToBytes32(bytes b, uint offset) private pure returns (bytes32) { + bytes32 out; + + for (uint i = 0; i < 32; i++) { + out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); + } + return out; + } +} diff --git a/contracts/RLP.sol b/contracts/RLP.sol index 9967e65..42ba1cf 100644 --- a/contracts/RLP.sol +++ b/contracts/RLP.sol @@ -28,10 +28,10 @@ library RLP { /* Iterator */ - function next(Iterator memory self) internal constant returns (RLPItem memory subItem) { + function next(Iterator memory self) internal pure returns (RLPItem memory subItem) { if(hasNext(self)) { - var ptr = self._unsafe_nextPtr; - var itemLength = _itemLength(ptr); + uint ptr = self._unsafe_nextPtr; + uint itemLength = _itemLength(ptr); subItem._unsafe_memPtr = ptr; subItem._unsafe_length = itemLength; self._unsafe_nextPtr = ptr + itemLength; @@ -40,15 +40,15 @@ library RLP { revert(); } - function next(Iterator memory self, bool strict) internal constant returns (RLPItem memory subItem) { + function next(Iterator memory self, bool strict) internal pure returns (RLPItem memory subItem) { subItem = next(self); if(strict && !_validate(subItem)) revert(); return; } - function hasNext(Iterator memory self) internal constant returns (bool) { - var item = self._unsafe_item; + function hasNext(Iterator memory self) internal pure returns (bool) { + RLPItem memory item = self._unsafe_item; return self._unsafe_nextPtr < item._unsafe_memPtr + item._unsafe_length; } @@ -57,7 +57,7 @@ library RLP { /// @dev Creates an RLPItem from an array of RLP encoded bytes. /// @param self The RLP encoded bytes. /// @return An RLPItem - function toRLPItem(bytes memory self) internal constant returns (RLPItem memory) { + function toRLPItem(bytes memory self) internal pure returns (RLPItem memory) { uint len = self.length; if (len == 0) { return RLPItem(0, 0); @@ -73,8 +73,8 @@ library RLP { /// @param self The RLP encoded bytes. /// @param strict Will revert() if the data is not RLP encoded. /// @return An RLPItem - function toRLPItem(bytes memory self, bool strict) internal constant returns (RLPItem memory) { - var item = toRLPItem(self); + function toRLPItem(bytes memory self, bool strict) internal pure returns (RLPItem memory) { + RLPItem memory item = toRLPItem(self); if(strict) { uint len = self.length; if(_payloadOffset(item) > len) @@ -90,14 +90,14 @@ library RLP { /// @dev Check if the RLP item is null. /// @param self The RLP item. /// @return 'true' if the item is null. - function isNull(RLPItem memory self) internal constant returns (bool ret) { + function isNull(RLPItem memory self) internal pure returns (bool ret) { return self._unsafe_length == 0; } /// @dev Check if the RLP item is a list. /// @param self The RLP item. /// @return 'true' if the item is a list. - function isList(RLPItem memory self) internal constant returns (bool ret) { + function isList(RLPItem memory self) internal pure returns (bool ret) { if (self._unsafe_length == 0) return false; uint memPtr = self._unsafe_memPtr; @@ -109,7 +109,7 @@ library RLP { /// @dev Check if the RLP item is data. /// @param self The RLP item. /// @return 'true' if the item is data. - function isData(RLPItem memory self) internal constant returns (bool ret) { + function isData(RLPItem memory self) internal pure returns (bool ret) { if (self._unsafe_length == 0) return false; uint memPtr = self._unsafe_memPtr; @@ -121,7 +121,7 @@ library RLP { /// @dev Check if the RLP item is empty (string or list). /// @param self The RLP item. /// @return 'true' if the item is null. - function isEmpty(RLPItem memory self) internal constant returns (bool ret) { + function isEmpty(RLPItem memory self) internal pure returns (bool ret) { if(isNull(self)) return false; uint b0; @@ -135,7 +135,7 @@ library RLP { /// @dev Get the number of items in an RLP encoded list. /// @param self The RLP item. /// @return The number of items. - function items(RLPItem memory self) internal constant returns (uint) { + function items(RLPItem memory self) internal pure returns (uint) { if (!isList(self)) return 0; uint b0; @@ -156,7 +156,7 @@ library RLP { /// @dev Create an iterator. /// @param self The RLP item. /// @return An 'Iterator' over the item. - function iterator(RLPItem memory self) internal constant returns (Iterator memory it) { + function iterator(RLPItem memory self) internal pure returns (Iterator memory it) { if (!isList(self)) revert(); uint ptr = self._unsafe_memPtr + _payloadOffset(self); @@ -168,7 +168,7 @@ library RLP { /// @param self The RLPItem. /// @return The bytes. function toBytes(RLPItem memory self) internal constant returns (bytes memory bts) { - var len = self._unsafe_length; + uint len = self._unsafe_length; if (len == 0) return; bts = new bytes(len); @@ -182,7 +182,9 @@ library RLP { function toData(RLPItem memory self) internal constant returns (bytes memory bts) { if(!isData(self)) revert(); - var (rStartPos, len) = _decode(self); + uint rStartPos; + uint len; + (rStartPos, len) = _decode(self); bts = new bytes(len); _copyToBytes(rStartPos, bts, len); } @@ -194,9 +196,9 @@ library RLP { function toList(RLPItem memory self) internal constant returns (RLPItem[] memory list) { if(!isList(self)) revert(); - var numItems = items(self); + uint numItems = items(self); list = new RLPItem[](numItems); - var it = iterator(self); + Iterator memory it = iterator(self); uint idx; while(hasNext(it)) { list[idx] = next(it); @@ -211,7 +213,9 @@ library RLP { function toAscii(RLPItem memory self) internal constant returns (string memory str) { if(!isData(self)) revert(); - var (rStartPos, len) = _decode(self); + uint rStartPos; + uint len; + (rStartPos, len) = _decode(self); bytes memory bts = new bytes(len); _copyToBytes(rStartPos, bts, len); str = string(bts); @@ -224,7 +228,9 @@ library RLP { function toUint(RLPItem memory self) internal constant returns (uint data) { if(!isData(self)) revert(); - var (rStartPos, len) = _decode(self); + uint rStartPos; + uint len; + (rStartPos, len) = _decode(self); if (len > 32 || len == 0) revert(); assembly { @@ -239,7 +245,9 @@ library RLP { function toBool(RLPItem memory self) internal constant returns (bool data) { if(!isData(self)) revert(); - var (rStartPos, len) = _decode(self); + uint rStartPos; + uint len; + (rStartPos, len) = _decode(self); if (len != 1) revert(); uint temp; @@ -258,7 +266,9 @@ library RLP { function toByte(RLPItem memory self) internal constant returns (byte data) { if(!isData(self)) revert(); - var (rStartPos, len) = _decode(self); + uint rStartPos; + uint len; + (rStartPos, len) = _decode(self); if (len != 1) revert(); uint temp; @@ -291,7 +301,9 @@ library RLP { function toAddress(RLPItem memory self) internal constant returns (address data) { if(!isData(self)) revert(); - var (rStartPos, len) = _decode(self); + uint rStartPos; + uint len; + (rStartPos, len) = _decode(self); if (len != 20) revert(); assembly { @@ -300,7 +312,7 @@ library RLP { } // Get the payload offset. - function _payloadOffset(RLPItem memory self) private constant returns (uint) { + function _payloadOffset(RLPItem memory self) private pure returns (uint) { if(self._unsafe_length == 0) return 0; uint b0; @@ -318,7 +330,7 @@ library RLP { } // Get the full length of an RLP item. - function _itemLength(uint memPtr) private constant returns (uint len) { + function _itemLength(uint memPtr) private pure returns (uint len) { uint b0; assembly { b0 := byte(0, mload(memPtr)) @@ -374,7 +386,7 @@ library RLP { } // Assumes that enough memory has been allocated to store in target. - function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private constant { + function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private { // Exploiting the fact that 'tgt' was the last thing to be allocated, // we can write entire words, and just overwrite any excess. assembly { @@ -398,7 +410,7 @@ library RLP { } // Check that an RLP item is valid. - function _validate(RLPItem memory self) private constant returns (bool ret) { + function _validate(RLPItem memory self) private pure returns (bool ret) { // Check that RLP is well-formed. uint b0; uint b1; diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index db644d2..509f05e 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,7 +1,10 @@ const Ion = artifacts.require("Ion"); +const PatriciaTrie = artifacts.require("PatriciaTrie"); module.exports = async (deployer) => { try { + await deployer.deploy(PatriciaTrie); + await deployer.link(PatriciaTrie, Ion); deployer.deploy(Ion, "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") } catch(err) { diff --git a/package.json b/package.json index 30a5981..a2dd710 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,10 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", + "eth-proof": "git@github.com:Shirikatsu/eth-proof.git#log-encoding", + "ethereumjs-block": "^2.0.0", + "ethereumjs-tx": "^1.3.5", + "merkle-patricia-tree": "^2.3.1", "rlp": "^2.0.0", "solc": "^0.4.23", "solhint": "^1.1.10", diff --git a/test/helpers/trie.js b/test/helpers/trie.js new file mode 100644 index 0000000..e69de29 diff --git a/test/ion.js b/test/ion.js index 1ee4c31..5a38239 100644 --- a/test/ion.js +++ b/test/ion.js @@ -4,8 +4,20 @@ const Web3Utils = require('web3-utils'); const BN = require('bignumber.js') const merkle = require('./helpers/merkle.js') +const encoder = require('./helpers/encoder.js') +const Trie = require('merkle-patricia-tree'); +const rlp = require('rlp'); +const async = require('async') +const EthereumTx = require('ethereumjs-tx'); +const EthereumBlock = require('ethereumjs-block/from-rpc') +const levelup = require('levelup'); +const sha3 = require('js-sha3').keccak_256 +const EP = require('eth-proof'); + +const Web3 = require('web3'); const Ion = artifacts.require("Ion"); +const PatriciaTrie = artifacts.require("PatriciaTrie"); require('chai') .use(require('chai-as-promised')) @@ -16,27 +28,44 @@ const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" const TESTBLOCK = { difficulty: 2, - extraData: "0xd88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01", - gasLimit: 939056936520814100, - gasUsed: 26920, - hash: "0xe40cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", - logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - miner: "0x0000000000000000000000000000000000000000", - mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000", - nonce: "0x0000000000000000", - number: 210, - parentHash: "0xf4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72", - receiptsRoot: "0x5ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845", - sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - size: 756, - stateRoot: "0x19ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161ed", - timestamp: 1529069678, - totalDifficulty: 421, - transactions: ["0x93f687edff8cf04c60b177b47ddcd8861c795664e5af1da9116b62d06e91694b"], - transactionsRoot: "0x87c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464", + extraData: '0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00', + gasLimit: 5635559972940396, + gasUsed: 273138, + hash: '0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4', + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + miner: '0x0000000000000000000000000000000000000000', + mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x0000000000000000', + number: 5446, + parentHash: '0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284', + receiptsRoot: '0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: 2027, + stateRoot: '0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967', + timestamp: 1531327572, + totalDifficulty: 10893, + transactions: + [ '0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3', + '0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5', + '0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8', + '0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6', + '0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8', + '0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1', + '0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446', + '0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462', + '0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e', + '0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314', + '0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d', + '0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede', + '0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc' ], + transactionsRoot: '0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35', uncles: [] } -const TESTRLPENCODING = "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + +const TESTRLPENCODING = "0xf9025fa0aa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0b347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967a0cb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35a01d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002821546871405830e4c2a6c83042af2845b463454b861d88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +const TEST_NODE_VALUE = "0xf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a" +const TEST_PATH = "0x80" +const TEST_PARENT_NODES = "0xf8c3f851a0448f4ee6a987bf17a91096e25247c3d7d78dbd08afddb5cfd4186d6a9f36bbc080808080808080a0c47289442eb85e0ca1f12c5ac6168f15513036935879931655dadfad3586dcb78080808080808080f86e30b86bf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a" contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { @@ -101,12 +130,96 @@ contract('Ion.js', (accounts) => { await ion.SubmitBlock(TESTCHAINID, "0xe4" + "1" + "cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000").should.be.rejected; }) - it('Check Tx Proof', () => { + it('Check Tx Proof', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_NODE_VALUE, TEST_PARENT_NODES, TEST_PATH); }) - it('Fail Tx Proof', () => { +// it('Check EP Proofs', async () => { +// const ion = await Ion.new(DEPLOYEDCHAINID); +// +// // Building transactions in a block for better trie constructions +// for (let i = 0; i < 10; i++) { +// web3.eth.sendTransaction({from: web3.eth.accounts[0], to: ion.address, value:1}) +// } +// +// block = web3.eth.getBlock(5446); +// blockNumber = block.number; +// +// block.difficulty = block.difficulty.toNumber(); +// block.totalDifficulty = block.totalDifficulty.toNumber(); +// console.log(block); +// +// while (block.transactions < 1) { +// console.log("No transactions found for block: " + blockNumber.toString()); +// console.log("Trying again..."); +// blockNumber -= 1; +// block = web3.eth.getBlock(blockNumber); +// } +// +// txHash = block.transactions[0]; +// transaction = web3.eth.getTransaction(txHash); +// +// var eP = new EP(web3.currentProvider); +// +// await eP.getTransactionTrieRoot(txHash).then( (root) => { +// console.log("EP Root hash = 0x" + root.toString('hex')) +// }) +// +// var txValue; +// var txPath; +// var txParentNodes; +// await eP.getTransactionProof(txHash).then( (proof) => { +// verified = EP.transaction(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); +// assert(verified); +// +// txValue = rlp.encode(proof.value); +// txPath = proof.path; +// txParentNodes = rlp.encode(proof.parentNodes); +// }) +// +// console.log("EP VALUE = 0x" + txValue.toString('hex')); +// console.log("EP PATH = 0x" + txPath.toString('hex')); +// console.log("EP PARENT NODES = 0x" + txParentNodes.toString('hex')); +// +// }) + +// it('Check Infura Proofs', async () => { +// +// var eP = new EP(new Web3.providers.HttpProvider("https://gmainnet.infura.io")); +// +// await eP.getTransactionProof("0xb53f752216120e8cbe18783f41c6d960254ad59fac16229d4eaec5f7591319de").then( (proof) => { +// verified = EP.transaction(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); +// assert(verified); +// +// txValue = rlp.encode(proof.value); +// txPath = rlp.encode(proof.path); +// txParentNodes = rlp.encode(proof.parentNodes); +// }) +// +// +// }) + + it('Fail Tx Proof', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await ion.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_NODE_VALUE, TEST_PARENT_NODES, TEST_PATH).should.be.rejected; + + // Fail with wrong block hash + await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_NODE_VALUE, TEST_PARENT_NODES, TEST_PATH).should.be.rejected; + // Fail with wrong path + await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_NODE_VALUE, TEST_PARENT_NODES, "0xff").should.be.rejected; }) it('Check Receipt Proof', () => { diff --git a/tooling/ion.py b/tooling/ion.py deleted file mode 100644 index eab1e79..0000000 --- a/tooling/ion.py +++ /dev/null @@ -1,38 +0,0 @@ -import click -from .encoder import RLPEncoder - -@click.command(help="Returns an RLP encoded block in hexadecimal format.") -@click.argument('rpc-host', nargs=1, type=str) -@click.argument('rpc-port', nargs=1, type=int) -@click.argument('number', nargs=1, type=int) -def get_encoded_block(rpc_host, rpc_port, number): - rlp_encoder = RLPEncoder(rpc_host, rpc_port) - block = rlp_encoder.get_block(number) - click.echo('0x'+rlp_encoder.encode_block(block).hex()) - -@click.command(help="Returns block hash in hexadecimal format.") -@click.argument('rpc-host', nargs=1, type=str) -@click.argument('rpc-port', nargs=1, type=int) -@click.argument('number', nargs=1, type=int) -def get_block_hash(rpc_host, rpc_port, number): - rlp_encoder = RLPEncoder(rpc_host, rpc_port) - block = rlp_encoder.get_block(number) - click.echo('0x'+rlp_encoder.hash_block_header(block)) - - -@click.command(help="Returns a list of transaction hashes from a specified block") -@click.argument('rpc-host', nargs=1, type=str) -@click.argument('rpc-port', nargs=1, type=int) -@click.argument('number', nargs=1, type=int) -def get_block_transactions(rpc_host, rpc_port, number): - rlp_encoder = RLPEncoder(rpc_host, rpc_port) - block = rlp_encoder.get_block(number) - click.echo(rlp_encoder.get_transactions(block)) - -commands = click.Group('commands') -commands.add_command(get_encoded_block, "encodeblock") -commands.add_command(get_block_hash, "blockhash") -commands.add_command(get_block_transactions, "gettx") - -if __name__ == "__main__": - commands.main() \ No newline at end of file diff --git a/tooling/trie.py b/tooling/trie.py new file mode 100644 index 0000000..e69de29 diff --git a/truffle.js b/truffle.js index 2566b29..f9634f7 100644 --- a/truffle.js +++ b/truffle.js @@ -5,9 +5,9 @@ module.exports = { port: 8545, network_id: "*" // Match any network id }, - ci: { + clique: { host: "localhost", - port: 8545, + port: 8501, network_id: "*" // Match any network id }, coverage: { @@ -17,16 +17,6 @@ module.exports = { gas: 0xFFFFFFF, gasprice: 0x1 }, - testrpca: { - host: "localhost", - port: 8545, - network_id: "*" // Match any network id - }, - testrpcb: { - host: "localhost", - port: 8546, - network_id: "*" // Match any network id - } }, mocha: { useColors: true, From fa65c812bef10866670eccc4fffdbf69b9e7b8b3 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 12 Jul 2018 09:39:40 +0100 Subject: [PATCH 051/203] Fixed the compiler warnings from solc --- contracts/Merkle.sol | 3 ++- docs/TransactionVerification.md | 2 ++ ion-cli/cli/cli.go | 13 ++++--------- ion-cli/cli/cli_test.go | 4 ++-- ion-cli/cli/test.json | 4 ++-- ion-cli/config/init.go | 2 +- ion-cli/setup.json | 4 ++-- ion-cli/setup_single.json | 11 ----------- 8 files changed, 15 insertions(+), 28 deletions(-) create mode 100644 docs/TransactionVerification.md delete mode 100644 ion-cli/setup_single.json diff --git a/contracts/Merkle.sol b/contracts/Merkle.sol index bae7d10..511fb77 100644 --- a/contracts/Merkle.sol +++ b/contracts/Merkle.sol @@ -10,7 +10,8 @@ library Merkle { internal pure returns (uint256) { - uint256 x = uint256(keccak256(a, b)); + bytes32 outputHash = keccak256(abi.encodePacked(a, b)); + uint256 x = uint256(outputHash); // Clears highest bit from result // left/right of node is stored there diff --git a/docs/TransactionVerification.md b/docs/TransactionVerification.md new file mode 100644 index 0000000..f2ba55c --- /dev/null +++ b/docs/TransactionVerification.md @@ -0,0 +1,2 @@ +# Transaction Verification +As part of the Ion Stage 2 project in order to perform continuous execution it is necessary to prove that an event was emitted. In Ethereum this information is \ No newline at end of file diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 040c73f..32d997c 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -154,23 +154,18 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra shell.AddCmd(&ishell.Cmd{ Name: "generateTxProof", - Help: "use: generateTxProof [txHash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Help: "use: generateTxProof [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) if len(c.Args) == 0 { c.Println("Select a block") - } else if len(c.Args) > 1 { + } else if len(c.Args) > 2 { c.Println("Too many arguments entered.") } else { c.Println("RLP encode block: " + c.Args[0]) - encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(clientFrom, c.Args[0]) - res, err := Validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) + rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) + c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) } c.Println("===============================================================") }, diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index 73574ec..69d8e5b 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -16,11 +16,11 @@ func Test_Read_ValidSetupJson(t *testing.T) { path := findPath() + "./test.json" setup := config.ReadSetup(path) - assert.Equal(t, "127.0.0.1:8545", setup.AddrTo) + assert.Equal(t, "http://127.0.0.1:8545", setup.AddrTo) assert.Equal(t, "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.AccountTo) assert.Equal(t, "../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.KeystoreTo) assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) - assert.Equal(t, "127.0.0.1:8501", setup.AddrFrom) + assert.Equal(t, "http://127.0.0.1:8501", setup.AddrFrom) assert.Equal(t, "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.AccountFrom) assert.Equal(t, "../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", setup.KeystoreFrom) } diff --git a/ion-cli/cli/test.json b/ion-cli/cli/test.json index e682029..0c6eafb 100644 --- a/ion-cli/cli/test.json +++ b/ion-cli/cli/test.json @@ -1,9 +1,9 @@ { - "rpc-to":"127.0.0.1:8545", + "rpc-to":"http://127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-from":"127.0.0.1:8501", + "rpc-from":"http://127.0.0.1:8501", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index e990209..0b4ef21 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -12,7 +12,7 @@ import ( func InitClient(addr string) (clientTo *ethclient.Client) { // Connect to the RPC Client - clientTo, err := ethclient.Dial("http://" + addr) + clientTo, err := ethclient.Dial(addr) if err != nil { log.Fatalf("could not create RPC client: %v", err) } diff --git a/ion-cli/setup.json b/ion-cli/setup.json index e682029..0c6eafb 100644 --- a/ion-cli/setup.json +++ b/ion-cli/setup.json @@ -1,9 +1,9 @@ { - "rpc-to":"127.0.0.1:8545", + "rpc-to":"http://127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-from":"127.0.0.1:8501", + "rpc-from":"http://127.0.0.1:8501", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/ion-cli/setup_single.json b/ion-cli/setup_single.json deleted file mode 100644 index f568936..0000000 --- a/ion-cli/setup_single.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "rpc-addr-to":"127.0.0.1", - "rpc-port-to":"8501", - "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-addr-from":"127.0.0.1", - "rpc-port-from":"8501", - "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" -} From aae3abadc0b85dbadcb73ed51dc02f27884302b1 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 12 Jul 2018 11:02:06 +0100 Subject: [PATCH 052/203] Changed script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d18e873..d0d8065 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "compile": "truffle compile", "deploy": "truffle deploy", "depclique": "truffle deploy --network clique", - "test": "truffle test", + "test": "truffle test --network clique", "coverage": "solidity-coverage", "lint": "solhint contracts/**/*.sol", "genbin": "solc --overwrite --bin ./contracts/* -o abi", From bf8a7f05522c25a71041f9c6b72e107aa249af0a Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 12 Jul 2018 11:29:03 +0100 Subject: [PATCH 053/203] tests are being turbulent... --- contracts/libraries/ECVerify.sol | 2 +- requirements.txt | 27 --------------------------- test/validation.js | 2 +- 3 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 requirements.txt diff --git a/contracts/libraries/ECVerify.sol b/contracts/libraries/ECVerify.sol index d7f02ab..288da23 100644 --- a/contracts/libraries/ECVerify.sol +++ b/contracts/libraries/ECVerify.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.23; +pragma solidity ^0.4.18; // // The new assembly support in Solidity makes writing helpers easy. diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 591d991..0000000 --- a/requirements.txt +++ /dev/null @@ -1,27 +0,0 @@ -asn1crypto==0.24.0 -certifi==2018.4.16 -cffi==1.11.5 -chardet==3.0.4 -click==6.7 -coincurve==7.1.0 -cytoolz==0.9.0.1 -decode==0.4.2 -eth-hash==0.1.4 -eth-utils==1.0.3 -ethereum==2.3.1 -future==0.16.0 -idna==2.7 -pbkdf2==1.3 -pkg-resources==0.0.0 -py-ecc==1.4.2 -pycparser==2.18 -pycryptodome==3.6.1 -pyethash==0.1.27 -pysha3==1.0.2 -PyYAML==3.12 -repoze.lru==0.7 -requests==2.19.1 -rlp==0.6.0 -scrypt==0.8.6 -toolz==0.9.0 -urllib3==1.23 diff --git a/test/validation.js b/test/validation.js index 8441022..0dd575a 100644 --- a/test/validation.js +++ b/test/validation.js @@ -29,7 +29,7 @@ function bytesToHex(bytes) { return hex.join(""); } -contract('validation.js', (accounts) => { +contract.only('validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From 82b6a4f1eac23b6dfd2c97418fc61b8d37b9a7ac Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 12 Jul 2018 11:56:44 +0100 Subject: [PATCH 054/203] Added the package-lock.json --- package-lock.json | 8723 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 +- 2 files changed, 8726 insertions(+), 2 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..16f70ae --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8723 @@ +{ + "name": "ion-truffle", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "requires": { + "call-me-maybe": "1.0.1", + "glob-to-regexp": "0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", + "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "requires": { + "any-observable": "0.3.0" + } + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + }, + "abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "requires": { + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "antlr4": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.0.tgz", + "integrity": "sha1-KX+VbdwG+DOX/AmQ7PLgzyC/u+4=" + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.10", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-preset-node6": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-node6/-/babel-preset-node6-11.0.0.tgz", + "integrity": "sha1-CDWZRRckiYWinRj21GXasWu4p9g=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "requires": { + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "home-or-tmp": "2.0.0", + "lodash": "4.17.10", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "requires": { + "source-map": "0.5.7" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.10" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.10" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.10", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "bignumber.js": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + }, + "binaryextensions": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", + "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "1.2.0", + "browserify-des": "1.0.2", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sha3": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", + "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", + "requires": { + "js-sha3": "0.3.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, + "buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "requires": { + "check-error": "1.0.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "requires": { + "slice-ansi": "0.0.4", + "string-width": "1.0.2" + }, + "dependencies": { + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + } + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "1.0.1" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "requires": { + "color-name": "1.1.1" + } + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" + }, + "colors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", + "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.2" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.3", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" + } + }, + "crypto-js": { + "version": "3.1.9-1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", + "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" + }, + "dargs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" + }, + "death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "1.0.1" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "4.0.8" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "requires": { + "abstract-leveldown": "2.6.3" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-conflict": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "2.0.1" + } + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "2.0.2" + } + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "create-hmac": "1.1.7" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.5", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "tapable": "1.0.0" + } + }, + "envinfo": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-5.10.0.tgz", + "integrity": "sha512-rXbzXWvnQxy+TcqZlARbWVQwgGVVouVJgFZhLVN5htjLxl1thstrP2ZGi0pXC309AbK7gVOPU+ulz/tmpCI7iw==" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "1.0.1" + } + }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "requires": { + "string-template": "0.2.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.4.1", + "concat-stream": "1.6.2", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "3.3.10", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "eth-proof": { + "version": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#98e4ee11051d3a9b0e4b1f06bce8098e627a5d55", + "requires": { + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.6", + "keccak": "1.4.0", + "leveldown": "1.9.0", + "levelup": "1.3.9", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "rlp": "2.1.0", + "web3": "0.19.1" + }, + "dependencies": { + "bignumber.js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" + }, + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + }, + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, + "ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "requires": { + "async": "2.6.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "1.3.6", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" + } + }, + "merkle-patricia-tree": { + "version": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "integrity": "sha512-wJSFtpBHTdtRsqrVH7UoEyQOm0KNqqmTdE3vzZ/FamCe/w3cIhv7+khBiMlNlvRsrhxIhCCeVbshaG/FMz+xiQ==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.6", + "rlp": "2.1.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "web3": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", + "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", + "requires": { + "bignumber.js": "4.1.0", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + } + } + }, + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + }, + "ethereumjs-block": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.0.0.tgz", + "integrity": "sha512-doi2jH6fryGmBMzjxv2XFuJjcOUx4qZCil+qBNNdruNpDtXE1BZvC8Chj+YpuabzzTUZx5op9ob/MjXz3Xk+aw==", + "requires": { + "async": "2.6.1", + "ethereumjs-common": "0.3.1", + "ethereumjs-tx": "1.3.6", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "2.3.1" + } + }, + "ethereumjs-common": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-0.3.1.tgz", + "integrity": "sha512-o7GIMruAsif5RBe5A+dB3NhHjssYitoriiTzqHweTe5Wh45zL0kbpjPGTBQXo8dUp1QbjML40Cwsu+v7lcU6lA==" + }, + "ethereumjs-testrpc-sc": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.2.tgz", + "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", + "requires": { + "source-map-support": "0.5.6", + "webpack-cli": "2.1.5" + } + }, + "ethereumjs-tx": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.6.tgz", + "integrity": "sha512-wzsEs0mCSLqdDjqSDg6AWh1hyL8H3R/pyZxehkcCXq5MJEFXWz+eJ2jSv+3yEaLy6tXrNP7dmqS3Kyb3zAONkg==", + "requires": { + "ethereum-common": "0.0.18", + "ethereumjs-util": "5.2.0" + } + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.1.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + }, + "ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "requires": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.2" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "2.2.4" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.3", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "1.4.0", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.23", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-future": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", + "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" + }, + "fast-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", + "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "requires": { + "@mrmlnc/readdir-enhanced": "2.2.1", + "@nodelib/fs.stat": "1.1.0", + "glob-parent": "3.1.0", + "is-glob": "4.0.0", + "merge2": "1.2.2", + "micromatch": "3.1.10" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.0.0", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "requires": { + "readable-stream": "2.3.6" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "flow-parser": { + "version": "0.76.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.76.0.tgz", + "integrity": "sha512-p+K8OKiMlq8AIZH8KTydHEGUUd71AqfCL+zTJNsdHtQmX3i3eaeIysF83Ad6Oo7OQcHCj3vocb/EHYiEyq+ZBg==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "1.1.4" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "ganache-cli": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.6.tgz", + "integrity": "sha512-S+mPguwQD8dt9T0O/7mH941U9IYDbmCsoenCr31Zlr9yxjSYdNbWYGj3xsNw8CViZsMRGwIYeCaHPqK4bx2YVw==", + "dev": true, + "requires": { + "source-map-support": "0.5.6" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "gh-got": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", + "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", + "requires": { + "got": "7.1.0", + "is-plain-obj": "1.1.0" + }, + "dependencies": { + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + } + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "github-username": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", + "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", + "requires": { + "gh-got": "6.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-all": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", + "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", + "requires": { + "glob": "7.1.2", + "yargs": "1.2.6" + }, + "dependencies": { + "minimist": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" + }, + "yargs": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", + "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", + "requires": { + "minimist": "0.1.0" + } + } + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "2.19.0", + "process": "0.5.2" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "requires": { + "@sindresorhus/is": "0.7.0", + "cacheable-request": "2.1.4", + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "into-stream": "3.1.0", + "is-retry-allowed": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "mimic-response": "1.0.1", + "p-cancelable": "0.4.1", + "p-timeout": "2.0.1", + "pify": "3.0.0", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "3.0.0", + "url-to-options": "1.0.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grouped-queue": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", + "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", + "requires": { + "lodash": "4.17.10" + } + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "1.4.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "1.1.5", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.5.0" + } + }, + "http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "2.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "2.3.0", + "p-is-promise": "1.1.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "1.4.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "requires": { + "symbol-observable": "1.2.0" + }, + "dependencies": { + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-scoped": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", + "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", + "requires": { + "scoped-regex": "1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.12.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.1", + "wordwrap": "1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "requires": { + "binaryextensions": "2.1.1", + "editions": "1.3.4", + "textextensions": "2.2.0" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "js-sha3": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", + "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jscodeshift": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.1.tgz", + "integrity": "sha512-sRMollbhbmSDrR79JMAnhEjyZJlQQVozeeY9A6/KNuV26DNcuB3mGSCWXp0hks9dcwRNOELbNOiwraZaXXRk5Q==", + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "7.0.0-beta.47", + "colors": "1.3.0", + "flow-parser": "0.76.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "neo-async": "2.5.1", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.15.2", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.47", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", + "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==" + } + } + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + }, + "json-bigint-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint-string/-/json-bigint-string-1.0.0.tgz", + "integrity": "sha1-M5l4TXeLt4RAvXLHCUrw4HW75oM=", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "1.3.0", + "inherits": "2.0.3", + "nan": "2.10.0", + "safe-buffer": "5.1.2" + } + }, + "keccakjs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", + "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", + "requires": { + "browserify-sha3": "0.0.1", + "sha3": "1.2.2" + } + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "optional": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + }, + "level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "requires": { + "inherits": "2.0.3", + "level-errors": "1.0.5", + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "leveldown": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-1.9.0.tgz", + "integrity": "sha512-3MwcrnCUIuFiKp/jSrG1UqDTV4k1yH8f5HH6T9dpqCKG+lRxcfo2KwAqbzTT+TTKfCbaATeHMy9mm1y6sI3ZvA==", + "requires": { + "abstract-leveldown": "2.7.2", + "bindings": "1.3.0", + "fast-future": "1.0.2", + "nan": "2.7.0", + "prebuild-install": "2.5.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "requires": { + "deferred-leveldown": "1.2.2", + "level-codec": "7.0.1", + "level-errors": "1.0.5", + "level-iterator-stream": "1.3.1", + "prr": "1.0.1", + "semver": "5.4.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "listr": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.1.tgz", + "integrity": "sha512-MSMUUVN1f8aRnPi4034RkOqdiUlpYW+FqwFE3aL0uYNPRavkt2S2SsSpDDofn8BDpqv2RNnsdOcCHWsChcq77A==", + "requires": { + "@samverschueren/stream-to-observable": "0.3.0", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "1.1.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "6.2.1", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + }, + "rxjs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.1.tgz", + "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==", + "requires": { + "tslib": "1.9.3" + } + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" + }, + "listr-update-renderer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", + "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "requires": { + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "1.0.1" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "1.2.0" + } + }, + "mem-fs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", + "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", + "requires": { + "through2": "2.0.3", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" + } + }, + "mem-fs-editor": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-4.0.3.tgz", + "integrity": "sha512-tgWmwI/+6vwu6POan82dTjxEpwAoaj0NAFnghtVo/FcLK2/7IhPUtFUUYlwou4MOY6OtjTUJtwpfH1h+eSUziw==", + "requires": { + "commondir": "1.0.1", + "deep-extend": "0.6.0", + "ejs": "2.6.1", + "glob": "7.1.2", + "globby": "7.1.1", + "isbinaryfile": "3.0.2", + "mkdirp": "0.5.1", + "multimatch": "2.1.0", + "rimraf": "2.6.2", + "through2": "2.0.3", + "vinyl": "2.2.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.10", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + } + } + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "requires": { + "abstract-leveldown": "2.7.2", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "0.1.7", + "readable-stream": "2.3.6" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge2": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", + "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==" + }, + "merkle-patricia-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", + "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.6", + "rlp": "2.1.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "0.1.1" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", + "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==" + }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" + }, + "node-abi": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", + "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "requires": { + "semver": "5.4.1" + } + }, + "node-dir": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", + "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "requires": { + "chalk": "0.4.0", + "underscore": "1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" + } + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.0.9" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.3" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "2.0.0", + "query-string": "5.1.1", + "sort-keys": "2.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "requires": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "oboe": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", + "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", + "requires": { + "http-https": "1.0.0" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "1.2.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "original-require": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", + "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "requires": { + "p-reduce": "1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-lazy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", + "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "1.3.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-headers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", + "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", + "requires": { + "for-each": "0.3.3", + "trim": "0.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.2" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "requires": { + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, + "pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + } + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "prettier": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.7.tgz", + "integrity": "sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==" + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.2" + } + }, + "randomhex": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "read-chunk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", + "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", + "requires": { + "pify": "3.0.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "recast": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.2.tgz", + "integrity": "sha512-L4f/GqxjlEJ5IZ+tdll/l+6dVi2ylysWbkgFJbMuldD6Jklgfv6zJnCpuAZDfjwHhfcd/De0dDKelsTEPQ29qA==", + "requires": { + "ast-types": "0.11.5", + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "1.8.1" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==" + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "requires": { + "regenerate": "1.4.0", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "0.5.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "req-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", + "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", + "requires": { + "req-from": "1.0.1" + } + }, + "req-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", + "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", + "requires": { + "resolve-from": "2.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + } + } + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "1.0.1" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "rlp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", + "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "requires": { + "rx-lite": "4.0.8" + } + }, + "rxjs": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", + "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "scoped-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" + }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "requires": { + "nan": "2.10.0" + } + }, + "scrypt.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", + "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", + "requires": { + "scrypt": "6.0.3", + "scryptsy": "1.2.1" + } + }, + "scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "requires": { + "pbkdf2": "3.0.16" + } + }, + "secp256k1": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.0.tgz", + "integrity": "sha512-e5QIJl8W7Y4tT6LHffVcZAxJjvpgE5Owawv6/XCYPQljE9aP2NFFddQ8OYMKhdLshNu88FfL3qCN3/xYkXGRsA==", + "requires": { + "bindings": "1.3.0", + "bip66": "1.1.5", + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "drbg.js": "1.0.1", + "elliptic": "6.4.0", + "nan": "2.10.0", + "safe-buffer": "5.1.2" + } + }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.3", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.2" + } + }, + "servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "requires": { + "body-parser": "1.18.3", + "cors": "2.8.4", + "express": "4.16.3", + "request": "2.87.0", + "xhr": "2.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "sha3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", + "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", + "requires": { + "nan": "2.10.0" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + } + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "3.2.2" + } + }, + "sol-explore": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", + "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=" + }, + "solc": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", + "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", + "requires": { + "fs-extra": "0.30.0", + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "semver": "5.4.1", + "yargs": "4.8.1" + } + }, + "solhint": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.2.1.tgz", + "integrity": "sha512-3B0ydhkOlicyyTmKnwJC6kiwdJUXvbbDYXcy8m7rznoQPgzzkmSOsJgb9BAe+KBQP5BD3PLgcoOQ84t3FSxqsQ==", + "requires": { + "antlr4": "4.7.0", + "commander": "2.11.0", + "eslint": "4.19.1", + "glob": "7.1.2", + "ignore": "3.3.10", + "lodash": "4.17.10" + } + }, + "solidity-coverage": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.5.5.tgz", + "integrity": "sha512-WexTLFZ3NBIWGYpNgWHtFLkASdoGP0i5Q/OJzwoCpHNtG1QrJO/mxUctc5BghP8srwMN8HxCtUJtu/eyGbIOJw==", + "requires": { + "death": "1.1.0", + "ethereumjs-testrpc-sc": "6.1.2", + "istanbul": "0.4.5", + "keccakjs": "0.2.1", + "req-cwd": "1.0.1", + "shelljs": "0.7.8", + "sol-explore": "1.6.2", + "solidity-parser-sc": "0.4.11", + "tree-kill": "1.2.0", + "web3": "0.18.4" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + }, + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + }, + "web3": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", + "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + } + } + }, + "solidity-parser-sc": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz", + "integrity": "sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw==", + "requires": { + "mocha": "4.1.0", + "pegjs": "0.10.0", + "yargs": "4.8.1" + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", + "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "requires": { + "buffer-from": "1.1.0", + "source-map": "0.6.1" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "requires": { + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.4.1", + "lodash": "4.17.10", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.6.1" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "textextensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", + "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "truffle": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.13.tgz", + "integrity": "sha1-vydYaYi0/4RWPt+/MrR5QUCKdq0=", + "dev": true, + "requires": { + "mocha": "4.1.0", + "original-require": "1.0.1", + "solc": "0.4.24" + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "optional": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "optional": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==" + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "2.0.0" + } + }, + "url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "utf8": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", + "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "v8-compile-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", + "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==" + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" + } + }, + "web3": { + "version": "github:ethereum/web3.js#f55cfae489f4a28d7205970bd61ed6e2c05de093", + "requires": { + "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2-cookies": "1.1.0", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" + }, + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + } + } + }, + "web3-core": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.34.tgz", + "integrity": "sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4=", + "requires": { + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-core-requestmanager": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-method": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz", + "integrity": "sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-promievent": "1.0.0-beta.34", + "web3-core-subscriptions": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz", + "integrity": "sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw=", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz", + "integrity": "sha1-Afj2zyrmtvC3DDi64e90G1urIVw=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-providers-http": "1.0.0-beta.34", + "web3-providers-ipc": "1.0.0-beta.34", + "web3-providers-ws": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz", + "integrity": "sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4=", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.34.tgz", + "integrity": "sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg=", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-core-subscriptions": "1.0.0-beta.34", + "web3-eth-abi": "1.0.0-beta.34", + "web3-eth-accounts": "1.0.0-beta.34", + "web3-eth-contract": "1.0.0-beta.34", + "web3-eth-iban": "1.0.0-beta.34", + "web3-eth-personal": "1.0.0-beta.34", + "web3-net": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", + "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", + "requires": { + "bn.js": "4.11.6", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth-accounts": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz", + "integrity": "sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM=", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + } + } + }, + "web3-eth-contract": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz", + "integrity": "sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY=", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-core-promievent": "1.0.0-beta.34", + "web3-core-subscriptions": "1.0.0-beta.34", + "web3-eth-abi": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "web3-eth-personal": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz", + "integrity": "sha1-mvuhZzQuveVCC81YlcP2w0OI8gU=", + "requires": { + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-net": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-net": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.34.tgz", + "integrity": "sha1-QnzqL0MYgUScjjjVIykPFz+f9j0=", + "requires": { + "web3-core": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz", + "integrity": "sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno=", + "requires": { + "web3-core-helpers": "1.0.0-beta.34", + "xhr2": "0.1.4" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz", + "integrity": "sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao=", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz", + "integrity": "sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + } + } + }, + "webpack-addons": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", + "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", + "requires": { + "jscodeshift": "0.4.1" + }, + "dependencies": { + "ast-types": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "jscodeshift": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", + "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", + "requires": { + "async": "1.5.2", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "6.18.0", + "colors": "1.3.0", + "flow-parser": "0.76.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.12.9", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + } + }, + "recast": { + "version": "0.12.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", + "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", + "requires": { + "ast-types": "0.10.1", + "core-js": "2.5.7", + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" + } + } + } + }, + "webpack-cli": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.1.5.tgz", + "integrity": "sha512-CiWQR+1JS77rmyiO6y1q8Kt/O+e8nUUC9YfJ25JtSmzDwbqJV7vIsh3+QKRHVTbTCa0DaVh8iY1LBiagUIDB3g==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "diff": "3.5.0", + "enhanced-resolve": "4.1.0", + "envinfo": "5.10.0", + "glob-all": "3.1.0", + "global-modules": "1.0.0", + "got": "8.3.2", + "import-local": "1.0.0", + "inquirer": "5.2.0", + "interpret": "1.1.0", + "jscodeshift": "0.5.1", + "listr": "0.14.1", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mkdirp": "0.5.1", + "p-each-series": "1.0.0", + "p-lazy": "1.0.0", + "prettier": "1.13.7", + "supports-color": "5.4.0", + "v8-compile-cache": "2.0.0", + "webpack-addons": "1.1.5", + "yargs": "11.1.0", + "yeoman-environment": "2.3.0", + "yeoman-generator": "2.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "requires": { + "debug": "2.6.9", + "nan": "2.10.0", + "typedarray-to-buffer": "3.1.5", + "yaeti": "0.0.6" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" + } + }, + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "4.3.2", + "is-function": "1.0.1", + "parse-headers": "2.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "requires": { + "buffer-to-arraybuffer": "0.0.5", + "object-assign": "4.1.1", + "query-string": "5.1.1", + "simple-get": "2.8.1", + "timed-out": "4.0.1", + "url-set-query": "1.0.0", + "xhr": "2.5.0" + } + }, + "xhr-request-promise": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", + "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", + "requires": { + "xhr-request": "1.1.0" + } + }, + "xhr2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", + "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" + }, + "xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "requires": { + "cookiejar": "2.1.2" + } + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + }, + "yeoman-environment": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.3.0.tgz", + "integrity": "sha512-PHSAkVOqYdcR+C+Uht1SGC4eVD/9OhygYFkYaI66xF8vKIeS1RNYay+umj2ZrQeJ50tF5Q/RSO6qGDz9y3Ifug==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "globby": "8.0.1", + "grouped-queue": "0.3.3", + "inquirer": "5.2.0", + "is-scoped": "1.0.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mem-fs": "1.1.3", + "strip-ansi": "4.0.0", + "text-table": "0.2.0", + "untildify": "3.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globby": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", + "glob": "7.1.2", + "ignore": "3.3.10", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "yeoman-generator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.5.tgz", + "integrity": "sha512-rV6tJ8oYzm4mmdF2T3wjY+Q42jKF2YiiD0VKfJ8/0ZYwmhCKC9Xs2346HVLPj/xE13i68psnFJv7iS6gWRkeAg==", + "requires": { + "async": "2.6.1", + "chalk": "2.4.1", + "cli-table": "0.3.1", + "cross-spawn": "6.0.5", + "dargs": "5.1.0", + "dateformat": "3.0.3", + "debug": "3.1.0", + "detect-conflict": "1.0.1", + "error": "7.0.2", + "find-up": "2.1.0", + "github-username": "4.1.0", + "istextorbinary": "2.2.1", + "lodash": "4.17.10", + "make-dir": "1.3.0", + "mem-fs-editor": "4.0.3", + "minimist": "1.2.0", + "pretty-bytes": "4.0.2", + "read-chunk": "2.1.0", + "read-pkg-up": "3.0.0", + "rimraf": "2.6.2", + "run-async": "2.3.0", + "shelljs": "0.8.2", + "text-table": "0.2.0", + "through2": "2.0.3", + "yeoman-environment": "2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "requires": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + } + } +} diff --git a/package.json b/package.json index d0d8065..70fedbb 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,14 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", + "bignumber.js": "^7.2.1", "chai": "^4.1.2", "chai-as-promised": "^7.1.1", "crypto-js": "^3.1.9-1", "elliptic": "^6.4.0", - "eth-proof": "git@github.com:Shirikatsu/eth-proof.git#log-encoding", + "eth-proof": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#log-encoding", "ethereumjs-block": "^2.0.0", - "ethereumjs-tx": "^1.3.5", + "ethereumjs-tx": "^1.3.6", "ethereumjs-util": "^5.2.0", "ethjs-util": "^0.1.6", "merkle-patricia-tree": "^2.3.1", From ce6fafc44c93965a8bd647370fa087f58cea01c4 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 12 Jul 2018 14:38:31 +0100 Subject: [PATCH 055/203] Removed some of the compiler warnings --- contracts/Ion.sol | 6 +++--- contracts/libraries/PatriciaTrie.sol | 8 ++++---- contracts/libraries/RLP.sol | 18 +++++++++--------- test/helpers/encoder.js | 10 +++++----- test/validation.js | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 4705729..e000836 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -60,7 +60,7 @@ contract Ion { modifier onlyExistingBlocks(bytes32 _id, bytes32 _hash) { bool blockExists = false; - bytes32[] hashes = m_blockhashes[_id]; + bytes32[] memory hashes = m_blockhashes[_id]; for (uint i = 0; i < hashes.length; i++) { if (_hash == hashes[i]) { blockExists = true; @@ -140,10 +140,10 @@ contract Ion { return true; } - function CheckReceiptProof() public { + function CheckReceiptProof() public pure { } - function CheckRootsProof() public { + function CheckRootsProof() public pure { } diff --git a/contracts/libraries/PatriciaTrie.sol b/contracts/libraries/PatriciaTrie.sol index 73cdb6c..4361bbd 100644 --- a/contracts/libraries/PatriciaTrie.sol +++ b/contracts/libraries/PatriciaTrie.sol @@ -4,7 +4,7 @@ import "./RLP.sol"; library PatriciaTrie { - function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) returns (bool) { + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) public returns (bool) { RLP.RLPItem memory nodes = RLP.toRLPItem(_parentNodes); RLP.RLPItem[] memory parentNodes = RLP.toList(nodes); @@ -65,7 +65,7 @@ library PatriciaTrie { } } - function toNibbleArray(bytes b, bool hexPrefixed) private returns (bytes) { + function toNibbleArray(bytes b, bool hexPrefixed) private pure returns (bytes) { bytes memory nibbleArray = new bytes(255); uint8 nibblesFound = 0; @@ -99,11 +99,11 @@ library PatriciaTrie { } function leftShift(byte i, uint8 bits) private pure returns (byte) { - return byte(uint8(i) * 2 ** bits); + return byte(uint8(i) * uint8(2) ** uint8(bits)); } function rightShift(byte i, uint8 bits) private pure returns (byte) { - return byte(uint8(i) / 2 ** bits); + return byte(uint8(i) / uint8(2) ** uint8(bits)); } function bytesToBytes32(bytes b, uint offset) private pure returns (bytes32) { diff --git a/contracts/libraries/RLP.sol b/contracts/libraries/RLP.sol index 7cbbbb8..329ed0e 100644 --- a/contracts/libraries/RLP.sol +++ b/contracts/libraries/RLP.sol @@ -194,7 +194,7 @@ library RLP { /// Warning: This is inefficient, as it requires that the list is read twice. /// @param self The RLP item. /// @return Array of RLPItems. - function toList(RLPItem memory self) internal constant returns (RLPItem[] memory list) { + function toList(RLPItem memory self) internal pure returns (RLPItem[] memory list) { if(!isList(self)) revert(); uint numItems = items(self); @@ -226,7 +226,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toUint(RLPItem memory self) internal constant returns (uint data) { + function toUint(RLPItem memory self) internal pure returns (uint data) { if(!isData(self)) revert(); uint rStartPos; @@ -243,7 +243,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toBool(RLPItem memory self) internal constant returns (bool data) { + function toBool(RLPItem memory self) internal pure returns (bool data) { if(!isData(self)) revert(); uint rStartPos; @@ -264,7 +264,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toByte(RLPItem memory self) internal constant returns (byte data) { + function toByte(RLPItem memory self) internal pure returns (byte data) { if(!isData(self)) revert(); uint rStartPos; @@ -283,7 +283,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toInt(RLPItem memory self) internal constant returns (int data) { + function toInt(RLPItem memory self) internal pure returns (int data) { return int(toUint(self)); } @@ -291,7 +291,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toBytes32(RLPItem memory self) internal constant returns (bytes32 data) { + function toBytes32(RLPItem memory self) internal pure returns (bytes32 data) { return bytes32(toUint(self)); } @@ -299,7 +299,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toAddress(RLPItem memory self) internal constant returns (address data) { + function toAddress(RLPItem memory self) internal pure returns (address data) { if(!isData(self)) revert(); uint rStartPos; @@ -359,7 +359,7 @@ library RLP { } // Get start position and length of the data. - function _decode(RLPItem memory self) private constant returns (uint memPtr, uint len) { + function _decode(RLPItem memory self) private pure returns (uint memPtr, uint len) { if(!isData(self)) revert(); uint b0; @@ -387,7 +387,7 @@ library RLP { } // Assumes that enough memory has been allocated to store in target. - function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private { + function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private view { // Exploiting the fact that 'tgt' was the last thing to be allocated, // we can write entire words, and just overwrite any excess. assembly { diff --git a/test/helpers/encoder.js b/test/helpers/encoder.js index 188e10b..229584c 100644 --- a/test/helpers/encoder.js +++ b/test/helpers/encoder.js @@ -26,7 +26,7 @@ function bytesToHex(bytes) { const block = web3.eth.getBlock(7); -console.log("\n\n\n\nBlock = " + JSON.stringify(block)) +// console.log("\n\n\n\nBlock = " + JSON.stringify(block)) // Decompose the values in the block to hash const parentHash = block.parentHash; const sha3Uncles = block.sha3Uncles; @@ -72,7 +72,7 @@ const encodedHeader = rlp.encode(header); const headerHash = Web3Utils.sha3(encodedHeader); -console.log("\n\n\nRLP-encoded header: " +bytesToHex(encodedHeader)); -console.log("\n\n\nHashed header: " +headerHash) -console.log("\n\n\nExpected hash: " +block.hash) -console.log("\n\n\n" + ((rlp.encode(parentHash)))) \ No newline at end of file +// console.log("\n\n\nRLP-encoded header: " +bytesToHex(encodedHeader)); +// console.log("\n\n\nHashed header: " +headerHash) +// console.log("\n\n\nExpected hash: " +block.hash) +// console.log("\n\n\n" + ((rlp.encode(parentHash)))) \ No newline at end of file diff --git a/test/validation.js b/test/validation.js index 0dd575a..8441022 100644 --- a/test/validation.js +++ b/test/validation.js @@ -29,7 +29,7 @@ function bytesToHex(bytes) { return hex.join(""); } -contract.only('validation.js', (accounts) => { +contract('validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From 65cbd52a3be5b49f6d97b77b799760764db93fe9 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 12 Jul 2018 17:56:27 +0100 Subject: [PATCH 056/203] Working receipt proofs with tests. Tests changed to use blocks from gmainnet.infura instead --- contracts/Ion.sol | 54 +- package-lock.json | 2574 +++++++++++++++++++++++++++------------------ test/ion.js | 193 ++-- 3 files changed, 1718 insertions(+), 1103 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index b6a97ce..54156e8 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -31,7 +31,8 @@ contract Ion { chainId = _id; } - event VerifiedTxProof(bytes32 chainId, bytes32 blockHash); + enum ProofType { TX, RECEIPT } + event VerifiedProof(bytes32 chainId, bytes32 blockHash, uint proofType); /* ======================================================================================================================== @@ -133,17 +134,58 @@ contract Ion { * of this function to only allow if the chain the proof is for is registered to this contract and if the block that * the proof is for has been submitted. */ - function CheckTxProof(bytes32 _id, bytes32 _blockHash, bytes _value, bytes _parentNodes, bytes _path) onlyRegisteredChains(_id) onlyExistingBlocks(_id, _blockHash) public returns (bool) { + function CheckTxProof( + bytes32 _id, + bytes32 _blockHash, + bytes _value, + bytes _parentNodes, + bytes _path + ) + onlyRegisteredChains(_id) + onlyExistingBlocks(_id, _blockHash) + public + returns (bool) + { BlockHeader storage blockHeader = m_blockheaders[_blockHash]; assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.txRootHash) ); - emit VerifiedTxProof(_id, _blockHash); + + emit VerifiedProof(_id, _blockHash, uint(ProofType.TX)); return true; } - function CheckReceiptProof() public { - } + /* + * CheckReceiptProof + * param: _id (bytes32) Unique id of chain submitting block from + * param: _blockHash (bytes32) Block hash of block being submitted + * param: _value (bytes) RLP-encoded receipt object array with fields defined as: https://github.com/ethereumjs/ethereumjs-tx/blob/0358fad36f6ebc2b8bea441f0187f0ff0d4ef2db/index.js#L50 + * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove + * param: _path (bytes) Byte array of the path to the node to be proved + * + * emits: VerifiedTxProof(chainId, blockHash) + * chainId: (bytes32) hash of the chain verifying proof against + * blockHash: (bytes32) hash of the block verifying proof against + * + * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution + * of this function to only allow if the chain the proof is for is registered to this contract and if the block that + * the proof is for has been submitted. + */ + function CheckReceiptProof( + bytes32 _id, + bytes32 _blockHash, + bytes _value, + bytes _parentNodes, + bytes _path + ) + onlyRegisteredChains(_id) + onlyExistingBlocks(_id, _blockHash) + public + returns (bool) + { + BlockHeader storage blockHeader = m_blockheaders[_blockHash]; + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.receiptRootHash) ); - function CheckRootsProof() public { + emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); + return true; } diff --git a/package-lock.json b/package-lock.json index d2de8a8..730cf4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,14 +7,20 @@ "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", - "dev": true + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + }, + "abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "requires": { + "xtend": "4.0.1" + } }, "accepts": { "version": "1.3.5", @@ -26,11 +32,30 @@ "negotiator": "0.6.1" } }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.1.0", @@ -38,11 +63,15 @@ "json-schema-traverse": "0.3.1" } }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" + }, "align-text": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, "requires": { "kind-of": "3.2.2", "longest": "1.0.1", @@ -52,35 +81,35 @@ "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "ansi-escapes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", - "dev": true + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } }, + "antlr4": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.0.tgz", + "integrity": "sha1-KX+VbdwG+DOX/AmQ7PLgzyC/u+4=" + }, "any-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", - "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=", - "dev": true + "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=" }, "anymatch": { "version": "1.3.2", @@ -93,11 +122,24 @@ "normalize-path": "2.1.1" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.5" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "1.0.3" } @@ -106,7 +148,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, "requires": { "arr-flatten": "1.1.0" } @@ -114,14 +155,12 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" }, "array-flatten": { "version": "1.1.1", @@ -133,7 +172,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, "requires": { "array-uniq": "1.0.3" } @@ -141,20 +179,17 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, "asn1": { "version": "0.2.3", @@ -177,14 +212,12 @@ "ast-types": { "version": "0.11.3", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", - "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==", - "dev": true + "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==" }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "async-each": { "version": "1.0.1", @@ -305,7 +338,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-generator": "6.26.1", @@ -331,14 +363,12 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -346,7 +376,6 @@ "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, "requires": { "babel-messages": "6.23.0", "babel-runtime": "6.26.0", @@ -361,14 +390,12 @@ "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -376,7 +403,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -387,7 +413,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, "requires": { "babel-helper-explode-assignable-expression": "6.24.1", "babel-runtime": "6.26.0", @@ -398,7 +423,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -410,7 +434,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -422,7 +445,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -433,7 +455,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, "requires": { "babel-helper-bindify-decorators": "6.24.1", "babel-runtime": "6.26.0", @@ -445,7 +466,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, "requires": { "babel-helper-get-function-arity": "6.24.1", "babel-runtime": "6.26.0", @@ -458,7 +478,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -468,7 +487,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -478,7 +496,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -488,7 +505,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -499,7 +515,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -512,7 +527,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, "requires": { "babel-helper-optimise-call-expression": "6.24.1", "babel-messages": "6.23.0", @@ -526,7 +540,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -544,7 +557,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -552,62 +564,52 @@ "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" }, "babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" }, "babel-plugin-syntax-class-properties": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" }, "babel-plugin-syntax-decorators": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" }, "babel-plugin-syntax-export-extensions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" }, "babel-plugin-syntax-flow": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" }, "babel-plugin-syntax-trailing-function-commas": { "version": "6.22.0", @@ -618,7 +620,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-generators": "6.13.0", @@ -629,7 +630,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-functions": "6.13.0", @@ -640,7 +640,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, "requires": { "babel-plugin-syntax-class-constructor-call": "6.18.0", "babel-runtime": "6.26.0", @@ -651,7 +650,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-plugin-syntax-class-properties": "6.13.0", @@ -663,7 +661,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, "requires": { "babel-helper-explode-class": "6.24.1", "babel-plugin-syntax-decorators": "6.13.0", @@ -676,7 +673,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -685,7 +681,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -694,7 +689,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0", @@ -707,7 +701,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, "requires": { "babel-helper-define-map": "6.26.0", "babel-helper-function-name": "6.24.1", @@ -724,7 +717,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -734,7 +726,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -743,7 +734,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -753,7 +743,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -762,7 +751,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -773,7 +761,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -782,7 +769,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, "requires": { "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", "babel-runtime": "6.26.0", @@ -804,7 +790,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -815,7 +800,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, "requires": { "babel-plugin-transform-es2015-modules-amd": "6.24.1", "babel-runtime": "6.26.0", @@ -826,7 +810,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, "requires": { "babel-helper-replace-supers": "6.24.1", "babel-runtime": "6.26.0" @@ -836,7 +819,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, "requires": { "babel-helper-call-delegate": "6.24.1", "babel-helper-get-function-arity": "6.24.1", @@ -850,7 +832,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -860,7 +841,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -869,7 +849,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -880,7 +859,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -889,7 +867,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -898,7 +875,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -909,7 +885,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, "requires": { "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", "babel-plugin-syntax-exponentiation-operator": "6.13.0", @@ -920,7 +895,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, "requires": { "babel-plugin-syntax-export-extensions": "6.13.0", "babel-runtime": "6.26.0" @@ -930,7 +904,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, "requires": { "babel-plugin-syntax-flow": "6.18.0", "babel-runtime": "6.26.0" @@ -940,7 +913,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, "requires": { "babel-plugin-syntax-object-rest-spread": "6.13.0", "babel-runtime": "6.26.0" @@ -950,7 +922,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, "requires": { "regenerator-transform": "0.10.1" } @@ -1025,7 +996,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", "babel-plugin-transform-es2015-arrow-functions": "6.22.0", @@ -1066,7 +1036,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, "requires": { "babel-plugin-transform-class-constructor-call": "6.24.1", "babel-plugin-transform-export-extensions": "6.22.0", @@ -1077,7 +1046,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, "requires": { "babel-plugin-syntax-dynamic-import": "6.18.0", "babel-plugin-transform-class-properties": "6.24.1", @@ -1089,7 +1057,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, "requires": { "babel-plugin-syntax-trailing-function-commas": "6.22.0", "babel-plugin-transform-async-generator-functions": "6.24.1", @@ -1102,7 +1069,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, "requires": { "babel-core": "6.26.0", "babel-runtime": "6.26.0", @@ -1116,14 +1082,12 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, "requires": { "source-map": "0.5.7" } @@ -1195,14 +1159,12 @@ "babylon": { "version": "7.0.0-beta.42", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz", - "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==", - "dev": true + "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==" }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "bcrypt-pbkdf": { "version": "1.0.1", @@ -1217,12 +1179,10 @@ "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, "bignumber.js": { - "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "dev": true + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" }, "binary-extensions": { "version": "1.11.0", @@ -1234,8 +1194,29 @@ "binaryextensions": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", - "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==", - "dev": true + "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.5", + "safe-buffer": "5.1.1" + } }, "bluebird": { "version": "3.5.1", @@ -1246,8 +1227,7 @@ "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" }, "body-parser": { "version": "1.18.2", @@ -1280,7 +1260,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -1290,7 +1269,6 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", @@ -1300,20 +1278,30 @@ "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } }, "browserify-sha3": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", - "dev": true, "requires": { "js-sha3": "0.3.1" } @@ -1328,17 +1316,45 @@ "electron-to-chromium": "1.3.42" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, "buffer-to-arraybuffer": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", "dev": true }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" }, "bytes": { "version": "3.0.0", @@ -1350,7 +1366,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "dev": true, "requires": { "clone-response": "1.0.2", "get-stream": "3.0.0", @@ -1361,11 +1376,23 @@ "responselike": "1.0.2" } }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, "caniuse-lite": { "version": "1.0.30000823", @@ -1383,7 +1410,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4", @@ -1423,7 +1449,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -1433,8 +1458,7 @@ "chardet": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" }, "check-error": { "version": "1.0.2", @@ -1460,11 +1484,29 @@ "readdirp": "2.1.0" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, "requires": { "restore-cursor": "2.0.0" } @@ -1472,14 +1514,12 @@ "cli-spinners": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", - "dev": true + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" }, "cli-table": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "dev": true, "requires": { "colors": "1.0.3" }, @@ -1487,8 +1527,7 @@ "colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" } } }, @@ -1496,7 +1535,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "dev": true, "requires": { "slice-ansi": "0.0.4", "string-width": "1.0.2" @@ -1505,14 +1543,12 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -1521,7 +1557,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -1532,7 +1567,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -1542,14 +1576,12 @@ "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", - "dev": true, "requires": { "string-width": "2.1.1", "strip-ansi": "4.0.0", @@ -1559,20 +1591,17 @@ "clone": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=" }, "clone-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "1.0.0" } @@ -1580,14 +1609,12 @@ "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" }, "cloneable-readable": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, "requires": { "inherits": "2.0.3", "process-nextick-args": "2.0.0", @@ -1597,20 +1624,17 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -1618,14 +1642,12 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", - "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==", - "dev": true + "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==" }, "combined-stream": { "version": "1.0.6", @@ -1637,22 +1659,35 @@ } }, "commander": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", - "dev": true + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "typedarray": "0.0.6" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "content-disposition": { "version": "0.5.2", @@ -1669,8 +1704,7 @@ "convert-source-map": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" }, "cookie": { "version": "0.3.1", @@ -1692,8 +1726,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cors": { "version": "2.8.4", @@ -1705,11 +1738,35 @@ "vary": "1.1.2" } }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.1", + "sha.js": "2.4.11" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, "requires": { "nice-try": "1.0.4", "path-key": "2.0.1", @@ -1741,14 +1798,12 @@ "crypto-js": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=", - "dev": true + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" }, "dargs": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=", - "dev": true + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" }, "dashdash": { "version": "1.14.1", @@ -1762,20 +1817,17 @@ "date-fns": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", - "dev": true + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" }, "death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", - "dev": true + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" }, "debug": { "version": "2.6.9", @@ -1788,20 +1840,17 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, "requires": { "mimic-response": "1.0.0" } @@ -1818,53 +1867,108 @@ "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "requires": { + "abstract-leveldown": "2.6.3" + } }, - "detect-conflict": { + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.2.8" + }, + "dependencies": { + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-conflict": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", - "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=", - "dev": true + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, "requires": { "repeating": "2.0.1" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "2.0.2" + } }, "dom-walk": { "version": "0.1.1", @@ -1872,11 +1976,20 @@ "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", "dev": true }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "create-hmac": "1.1.7" + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, "ecc-jsbn": { "version": "0.1.1", @@ -1891,8 +2004,7 @@ "editions": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", - "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", - "dev": true + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" }, "ee-first": { "version": "1.1.1", @@ -1903,8 +2015,7 @@ "ejs": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", - "dev": true + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" }, "electron-to-chromium": { "version": "1.3.42", @@ -1915,14 +2026,12 @@ "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, "requires": { "bn.js": "4.11.6", "brorand": "1.1.0", @@ -1936,8 +2045,7 @@ "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, "encodeurl": { "version": "1.0.2", @@ -1945,11 +2053,18 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, "enhanced-resolve": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", - "dev": true, "requires": { "graceful-fs": "4.1.11", "memory-fs": "0.4.1", @@ -1960,7 +2075,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, "requires": { "prr": "1.0.1" } @@ -1969,7 +2083,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, "requires": { "string-template": "0.2.1", "xtend": "4.0.1" @@ -1979,7 +2092,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, "requires": { "is-arrayish": "0.2.1" } @@ -1999,7 +2111,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, "requires": { "esprima": "2.7.3", "estraverse": "1.9.3", @@ -2011,14 +2122,17 @@ "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, "optional": true, "requires": { "amdefine": "1.0.1" @@ -2026,17 +2140,145 @@ } } }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.2", + "concat-stream": "1.6.2", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "3.3.10", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.5", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.2", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.5", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "3.0.1" + } + }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "4.2.0" + } }, "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { "version": "2.0.2", @@ -2064,16 +2306,141 @@ "xhr-request-promise": "0.1.2" } }, + "eth-proof": { + "version": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#35a299bc72d30b72ff6f2a4e0100caaf3516cfe2", + "requires": { + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.5", + "keccak": "1.4.0", + "leveldown": "1.9.0", + "levelup": "1.3.9", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "rlp": "2.0.0", + "web3": "0.19.1" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, + "ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "requires": { + "async": "2.6.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "merkle-patricia-tree": { + "version": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "integrity": "sha512-wJSFtpBHTdtRsqrVH7UoEyQOm0KNqqmTdE3vzZ/FamCe/w3cIhv7+khBiMlNlvRsrhxIhCCeVbshaG/FMz+xiQ==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.5", + "rlp": "2.0.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + } + } + }, + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + }, + "ethereumjs-block": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.0.0.tgz", + "integrity": "sha512-doi2jH6fryGmBMzjxv2XFuJjcOUx4qZCil+qBNNdruNpDtXE1BZvC8Chj+YpuabzzTUZx5op9ob/MjXz3Xk+aw==", + "requires": { + "async": "2.6.1", + "ethereumjs-common": "0.3.1", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "2.3.1" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } + } + }, + "ethereumjs-common": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-0.3.1.tgz", + "integrity": "sha512-o7GIMruAsif5RBe5A+dB3NhHjssYitoriiTzqHweTe5Wh45zL0kbpjPGTBQXo8dUp1QbjML40Cwsu+v7lcU6lA==" + }, "ethereumjs-testrpc-sc": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.2.tgz", "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", - "dev": true, "requires": { "source-map-support": "0.5.4", "webpack-cli": "2.0.12" } }, + "ethereumjs-tx": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.5.tgz", + "integrity": "sha512-cPr0BxitCaffq0qQwZRHJgiNCM/3IIJqkYbweeUCyPwV77S+GlQHou2L3afKEFtfiAjfaa82T9LnSmY/pM8iYQ==", + "requires": { + "ethereum-common": "0.0.18", + "ethereumjs-util": "5.2.0" + } + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.6", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.1", + "secp256k1": "3.5.0" + } + }, "ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -2084,11 +2451,28 @@ "number-to-bn": "1.7.0" } }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, "requires": { "cross-spawn": "5.1.0", "get-stream": "3.0.0", @@ -2103,7 +2487,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, "requires": { "lru-cache": "4.1.2", "shebang-command": "1.2.0", @@ -2115,14 +2498,12 @@ "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -2131,16 +2512,19 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, "requires": { "fill-range": "2.2.3" } }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, "requires": { "homedir-polyfill": "1.0.1" } @@ -2201,7 +2585,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", - "dev": true, "requires": { "chardet": "0.4.2", "iconv-lite": "0.4.19", @@ -2212,7 +2595,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -2226,41 +2608,49 @@ "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-future": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", + "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5" } }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -2288,7 +2678,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, "requires": { "locate-path": "2.0.0" } @@ -2297,16 +2686,25 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "dev": true, "requires": { "readable-stream": "2.3.5" } }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, "flow-parser": { "version": "0.68.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.68.0.tgz", - "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=", - "dev": true + "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=" }, "for-each": { "version": "0.3.2", @@ -2320,14 +2718,12 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, "requires": { "for-in": "1.0.2" } @@ -2365,17 +2761,20 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.5" } }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs-extra": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "jsonfile": "2.4.0", @@ -2393,8 +2792,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.2.3", @@ -2913,33 +3311,85 @@ "string-width": "1.0.2" } }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "ganache-cli": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.0.tgz", + "integrity": "sha512-FdTeyk4uLRHGeFiMe+Qnh4Hc5KiTVqvRVVvLDFJEVVKC1P1yHhEgZeh9sp1KhuvxSrxToxgJS25UapYQwH4zHw==", + "dev": true, + "requires": { + "source-map-support": "0.5.4", + "webpack-cli": "2.0.12" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } } } }, - "ganache-cli": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.0.tgz", - "integrity": "sha512-FdTeyk4uLRHGeFiMe+Qnh4Hc5KiTVqvRVVvLDFJEVVKC1P1yHhEgZeh9sp1KhuvxSrxToxgJS25UapYQwH4zHw==", - "dev": true, - "requires": { - "source-map-support": "0.5.4", - "webpack-cli": "2.0.12" - } - }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" }, "get-func-name": { "version": "2.0.0", @@ -2950,8 +3400,7 @@ "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "getpass": { "version": "0.1.7", @@ -2966,7 +3415,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", - "dev": true, "requires": { "got": "7.1.0", "is-plain-obj": "1.1.0" @@ -2976,7 +3424,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, "requires": { "decompress-response": "3.3.0", "duplexer3": "0.1.4", @@ -2997,14 +3444,12 @@ "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" }, "p-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, "requires": { "p-finally": "1.0.0" } @@ -3012,25 +3457,27 @@ "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, "requires": { "prepend-http": "1.0.4" } } } }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, "github-username": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", - "dev": true, "requires": { "gh-got": "6.0.0" } @@ -3039,7 +3486,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -3053,7 +3499,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", - "dev": true, "requires": { "glob": "7.1.2", "yargs": "1.2.6" @@ -3063,7 +3508,6 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", - "dev": true, "requires": { "minimist": "0.1.0" } @@ -3074,7 +3518,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" @@ -3084,7 +3527,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, "requires": { "is-glob": "2.0.1" } @@ -3103,7 +3545,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, "requires": { "global-prefix": "1.0.2", "is-windows": "1.0.2", @@ -3114,7 +3555,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, "requires": { "expand-tilde": "2.0.2", "homedir-polyfill": "1.0.1", @@ -3132,7 +3572,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, "requires": { "array-union": "1.0.2", "glob": "7.1.2", @@ -3144,8 +3583,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -3153,7 +3591,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/got/-/got-8.3.0.tgz", "integrity": "sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==", - "dev": true, "requires": { "@sindresorhus/is": "0.7.0", "cacheable-request": "2.1.4", @@ -3177,8 +3614,7 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graceful-readlink": { "version": "1.0.1", @@ -3190,7 +3626,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", - "dev": true, "requires": { "lodash": "4.17.5" } @@ -3205,7 +3640,6 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, "requires": { "async": "1.5.2", "optimist": "0.6.1", @@ -3217,7 +3651,6 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, "requires": { "amdefine": "1.0.1" } @@ -3258,35 +3691,44 @@ "has-color": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" }, "has-to-string-tag-x": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, "requires": { "has-symbol-support-x": "1.4.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, "hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, "requires": { "inherits": "2.0.3", "minimalistic-assert": "1.0.0" @@ -3307,14 +3749,12 @@ "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, "requires": { "hash.js": "1.1.3", "minimalistic-assert": "1.0.0", @@ -3331,7 +3771,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" @@ -3341,7 +3780,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, "requires": { "parse-passwd": "1.0.0" } @@ -3349,14 +3787,12 @@ "hosted-git-info": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", - "dev": true + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" }, "http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" }, "http-errors": { "version": "1.6.2", @@ -3392,20 +3828,27 @@ "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, "requires": { "repeating": "2.0.1" } @@ -3414,7 +3857,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -3423,20 +3865,17 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.1.0.tgz", "integrity": "sha512-kn7N70US1MSZHZHSGJLiZ7iCwwncc7b0gc68YtlX29OjI3Mp0tSVV+snVXpZ1G+ONS3Ac9zd1m6hve2ibLDYfA==", - "dev": true, "requires": { "ansi-escapes": "3.0.0", "chalk": "2.3.2", @@ -3456,14 +3895,12 @@ "interpret": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" }, "into-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, "requires": { "from2": "2.3.0", "p-is-promise": "1.1.0" @@ -3480,8 +3917,7 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { "version": "1.6.0", @@ -3492,8 +3928,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "1.0.1", @@ -3508,14 +3943,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, "requires": { "builtin-modules": "1.1.1" } @@ -3523,14 +3956,12 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, "requires": { "is-primitive": "2.0.0" } @@ -3538,20 +3969,17 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -3559,8 +3987,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-function": { "version": "1.0.1", @@ -3572,7 +3999,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -3580,14 +4006,12 @@ "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", - "dev": true + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -3595,14 +4019,12 @@ "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" }, "is-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz", "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", - "dev": true, "requires": { "symbol-observable": "0.2.4" }, @@ -3610,46 +4032,65 @@ "symbol-observable": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", - "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", - "dev": true + "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=" } } }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "1.0.2" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" }, "is-scoped": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", - "dev": true, "requires": { "scoped-regex": "1.0.0" } @@ -3657,8 +4098,7 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-typedarray": { "version": "1.0.0", @@ -3669,32 +4109,27 @@ "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -3709,7 +4144,6 @@ "version": "0.4.5", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, "requires": { "abbrev": "1.0.9", "async": "1.5.2", @@ -3717,7 +4151,7 @@ "esprima": "2.7.3", "glob": "5.0.15", "handlebars": "4.0.11", - "js-yaml": "3.11.0", + "js-yaml": "3.12.0", "mkdirp": "0.5.1", "nopt": "3.0.6", "once": "1.4.0", @@ -3730,14 +4164,12 @@ "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, "requires": { "inflight": "1.0.6", "inherits": "2.0.3", @@ -3749,20 +4181,17 @@ "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" }, "supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, "requires": { "has-flag": "1.0.0" } @@ -3773,7 +4202,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true, "requires": { "binaryextensions": "2.1.1", "editions": "1.3.4", @@ -3784,41 +4212,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, "requires": { "has-to-string-tag-x": "1.4.1", "is-object": "1.0.1" } }, - "jade": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, - "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", - "dev": true - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", - "dev": true - } - } - }, "js-sha3": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", - "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=", - "dev": true + "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" }, "js-tokens": { "version": "3.0.2", @@ -3826,10 +4228,9 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "dev": true, + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "requires": { "argparse": "1.0.10", "esprima": "4.0.0" @@ -3846,7 +4247,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.0.tgz", "integrity": "sha512-JAcQINNMFpdzzpKJN8k5xXjF3XDuckB1/48uScSzcnNyK199iWEc9AxKL9OoX5144M2w5zEx9Qs4/E/eBZZUlw==", - "dev": true, "requires": { "babel-plugin-transform-flow-strip-types": "6.22.0", "babel-preset-es2015": "6.24.1", @@ -3868,8 +4268,7 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" }, "json-bigint-string": { "version": "1.0.0", @@ -3880,14 +4279,12 @@ "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, "json-parse-better-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", - "dev": true + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==" }, "json-schema": { "version": "0.2.3", @@ -3898,8 +4295,12 @@ "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json-stringify-safe": { "version": "5.0.1", @@ -3916,14 +4317,12 @@ "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, "requires": { "graceful-fs": "4.1.11" } @@ -3940,11 +4339,21 @@ "verror": "1.10.0" } }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "1.3.0", + "inherits": "2.0.3", + "nan": "2.10.0", + "safe-buffer": "5.1.1" + } + }, "keccakjs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", - "dev": true, "requires": { "browserify-sha3": "0.0.1", "sha3": "1.2.0" @@ -3954,7 +4363,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, "requires": { "json-buffer": "3.0.0" } @@ -3963,7 +4371,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -3972,7 +4379,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, "requires": { "graceful-fs": "4.1.11" } @@ -3981,23 +4387,155 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, "optional": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "1.0.0" } }, + "level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + }, + "level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "requires": { + "inherits": "2.0.3", + "level-errors": "1.0.5", + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "leveldown": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-1.9.0.tgz", + "integrity": "sha512-3MwcrnCUIuFiKp/jSrG1UqDTV4k1yH8f5HH6T9dpqCKG+lRxcfo2KwAqbzTT+TTKfCbaATeHMy9mm1y6sI3ZvA==", + "requires": { + "abstract-leveldown": "2.7.2", + "bindings": "1.3.0", + "fast-future": "1.0.2", + "nan": "2.7.0", + "prebuild-install": "2.5.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + } + } + }, + "levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "requires": { + "deferred-leveldown": "1.2.2", + "level-codec": "7.0.1", + "level-errors": "1.0.5", + "level-iterator-stream": "1.3.1", + "prr": "1.0.1", + "semver": "5.4.1", + "xtend": "4.0.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + } + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "1.1.2", "type-check": "0.3.2" @@ -4007,7 +4545,6 @@ "version": "0.13.0", "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz", "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-truncate": "0.2.1", @@ -4031,20 +4568,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -4057,7 +4591,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4067,7 +4600,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, "requires": { "chalk": "1.1.3" } @@ -4076,7 +4608,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4084,22 +4615,19 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, "listr-silent-renderer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" }, "listr-update-renderer": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-truncate": "0.2.1", @@ -4114,20 +4642,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -4140,7 +4665,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4149,14 +4673,12 @@ "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" }, "log-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, "requires": { "chalk": "1.1.3" } @@ -4165,7 +4687,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4173,8 +4694,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, @@ -4182,7 +4702,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-cursor": "1.0.2", @@ -4193,20 +4712,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -4219,7 +4735,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -4228,7 +4743,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4237,14 +4751,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -4254,7 +4766,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4262,8 +4773,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, @@ -4271,7 +4781,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "4.0.0", @@ -4282,8 +4791,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" } } }, @@ -4291,7 +4799,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, "requires": { "big.js": "3.2.0", "emojis-list": "2.1.0", @@ -4302,7 +4809,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, "requires": { "p-locate": "2.0.0", "path-exists": "3.0.0" @@ -4350,8 +4856,7 @@ "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" }, "lodash.create": { "version": "3.1.1", @@ -4391,7 +4896,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, "requires": { "chalk": "2.3.2" } @@ -4400,7 +4904,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", - "dev": true, "requires": { "ansi-escapes": "1.4.0", "cli-cursor": "1.0.2" @@ -4409,14 +4912,12 @@ "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, "cli-cursor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -4424,14 +4925,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -4442,8 +4941,7 @@ "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, "loose-envify": { "version": "1.3.1", @@ -4456,28 +4954,39 @@ "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" }, "lru-cache": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "dev": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" } }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" + }, "make-dir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", - "dev": true, "requires": { "pify": "3.0.0" } }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -4488,7 +4997,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -4497,7 +5005,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", - "dev": true, "requires": { "through2": "2.0.3", "vinyl": "1.2.0", @@ -4508,7 +5015,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-3.0.2.tgz", "integrity": "sha1-3Qpuryu4prN3QAZ6pUnrUwEFr58=", - "dev": true, "requires": { "commondir": "1.0.1", "deep-extend": "0.4.2", @@ -4525,26 +5031,22 @@ "clone": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" }, "clone-stats": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" }, "replace-ext": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" }, "vinyl": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, "requires": { "clone": "2.1.1", "clone-buffer": "1.0.0", @@ -4556,11 +5058,33 @@ } } }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "requires": { + "abstract-leveldown": "2.7.2", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + } + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, "requires": { "errno": "0.1.7", "readable-stream": "2.3.5" @@ -4569,8 +5093,7 @@ "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", - "dev": true + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" }, "merge-descriptors": { "version": "1.0.1", @@ -4578,6 +5101,21 @@ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, + "merkle-patricia-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", + "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.5", + "rlp": "2.0.0", + "semaphore": "1.1.0" + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -4588,7 +5126,6 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -4629,14 +5166,12 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, "mimic-response": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", - "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", - "dev": true + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" }, "min-document": { "version": "2.19.0", @@ -4650,20 +5185,17 @@ "minimalistic-assert": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", - "dev": true + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "1.1.11" } @@ -4671,14 +5203,12 @@ "minimist": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", - "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=", - "dev": true + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -4686,8 +5216,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, @@ -4775,7 +5304,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, "requires": { "array-differ": "1.0.0", "array-union": "1.0.2", @@ -4786,14 +5314,12 @@ "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "nan": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "nano-json-stream-parser": { "version": "0.1.2", @@ -4801,6 +5327,11 @@ "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -4810,26 +5341,30 @@ "neo-async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", - "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==", - "dev": true + "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==" }, "nice-try": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", - "dev": true + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" + }, + "node-abi": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", + "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "requires": { + "semver": "5.5.0" + } }, "node-dir": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", - "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=", - "dev": true + "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" }, "nomnom": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "dev": true, "requires": { "chalk": "0.4.0", "underscore": "1.6.0" @@ -4838,14 +5373,12 @@ "ansi-styles": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" }, "chalk": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, "requires": { "ansi-styles": "1.0.0", "has-color": "0.1.7", @@ -4855,16 +5388,19 @@ "strip-ansi": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" } } }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, "requires": { "abbrev": "1.0.9" } @@ -4873,7 +5409,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, "requires": { "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", @@ -4885,7 +5420,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, "requires": { "remove-trailing-separator": "1.1.0" } @@ -4894,7 +5428,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, "requires": { "prepend-http": "2.0.0", "query-string": "5.1.1", @@ -4905,16 +5438,25 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, "requires": { "path-key": "2.0.1" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "number-to-bn": { "version": "1.7.0", @@ -4935,14 +5477,17 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" @@ -4961,7 +5506,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1.0.2" } @@ -4970,7 +5514,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -4979,7 +5522,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, "requires": { "minimist": "0.0.10", "wordwrap": "0.0.3" @@ -4988,14 +5530,12 @@ "minimist": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" } } }, @@ -5003,7 +5543,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, "requires": { "deep-is": "0.1.3", "fast-levenshtein": "2.0.6", @@ -5017,7 +5556,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-cursor": "1.0.2", @@ -5028,20 +5566,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -5054,7 +5589,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -5062,14 +5596,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -5079,7 +5611,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -5087,8 +5618,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, @@ -5101,14 +5631,12 @@ "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, "requires": { "execa": "0.7.0", "lcid": "1.0.0", @@ -5118,8 +5646,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "output-file-sync": { "version": "1.1.2", @@ -5135,14 +5662,12 @@ "p-cancelable": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.0.tgz", - "integrity": "sha512-/AodqPe1y/GYbhSlnMjxukLGQfQIgsmjSy2CXCNB96kg4ozKvmlovuHEKICToOO/yS3LLWgrWI1dFtFfrePS1g==", - "dev": true + "integrity": "sha512-/AodqPe1y/GYbhSlnMjxukLGQfQIgsmjSy2CXCNB96kg4ozKvmlovuHEKICToOO/yS3LLWgrWI1dFtFfrePS1g==" }, "p-each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", - "dev": true, "requires": { "p-reduce": "1.0.0" } @@ -5150,26 +5675,22 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-is-promise": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" }, "p-lazy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", - "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=", - "dev": true + "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" }, "p-limit": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "dev": true, "requires": { "p-try": "1.0.0" } @@ -5178,7 +5699,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, "requires": { "p-limit": "1.2.0" } @@ -5186,20 +5706,17 @@ "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, "requires": { "p-finally": "1.0.0" } @@ -5207,14 +5724,12 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", @@ -5236,7 +5751,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, "requires": { "error-ex": "1.3.1", "json-parse-better-errors": "1.0.1" @@ -5245,8 +5759,7 @@ "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" }, "parseurl": { "version": "1.3.2", @@ -5257,26 +5770,27 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" }, "path-to-regexp": { "version": "0.1.7", @@ -5288,7 +5802,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, "requires": { "pify": "3.0.0" } @@ -5302,8 +5815,7 @@ "pegjs": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", - "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=", - "dev": true + "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" }, "performance-now": { "version": "2.1.0", @@ -5314,59 +5826,84 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "2.0.4" } }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" + }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.7.0", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "prettier": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz", - "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==", - "dev": true + "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==" }, "pretty-bytes": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process": { "version": "0.5.2", @@ -5377,8 +5914,12 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" }, "proxy-addr": { "version": "2.0.3", @@ -5393,14 +5934,21 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } }, "punycode": { "version": "1.4.1", @@ -5418,7 +5966,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, "requires": { "decode-uri-component": "0.2.0", "object-assign": "4.1.1", @@ -5429,7 +5976,6 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -5439,7 +5985,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -5448,7 +5993,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -5459,7 +6003,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -5490,11 +6033,33 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "read-chunk": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", - "dev": true, "requires": { "pify": "3.0.0", "safe-buffer": "5.1.1" @@ -5504,7 +6069,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, "requires": { "load-json-file": "4.0.0", "normalize-package-data": "2.4.0", @@ -5515,7 +6079,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, "requires": { "find-up": "2.1.0", "read-pkg": "3.0.0" @@ -5525,7 +6088,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", - "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -5553,7 +6115,6 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.5.tgz", "integrity": "sha512-GNFQGQrqW1R8w9XhhgYIN8H7ePPp088D+svHlb7DdP5DCqNDqTwH7lt378EouM+L18kCwkmqpAz1unLqpPhHmw==", - "dev": true, "requires": { "ast-types": "0.11.3", "esprima": "4.0.0", @@ -5565,7 +6126,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, "requires": { "resolve": "1.5.0" } @@ -5573,8 +6133,7 @@ "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", - "dev": true + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" }, "regenerator-runtime": { "version": "0.11.1", @@ -5585,7 +6144,6 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -5596,16 +6154,19 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, "requires": { "is-equal-shallow": "0.1.3" } }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==" + }, "regexpu-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, "requires": { "regenerate": "1.3.3", "regjsgen": "0.2.0", @@ -5615,14 +6176,12 @@ "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" }, "regjsparser": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, "requires": { "jsesc": "0.5.0" } @@ -5630,26 +6189,22 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, "requires": { "is-finite": "1.0.2" } @@ -5657,14 +6212,12 @@ "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" }, "req-cwd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", - "dev": true, "requires": { "req-from": "1.0.1" } @@ -5673,7 +6226,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", - "dev": true, "requires": { "resolve-from": "2.0.0" }, @@ -5681,8 +6233,7 @@ "resolve-from": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" } } }, @@ -5719,26 +6270,38 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-from-string": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", - "dev": true + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + } + } }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, "requires": { "path-parse": "1.0.5" } @@ -5747,7 +6310,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, "requires": { "resolve-from": "3.0.0" } @@ -5756,7 +6318,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, "requires": { "expand-tilde": "2.0.2", "global-modules": "1.0.0" @@ -5765,14 +6326,12 @@ "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, "requires": { "lowercase-keys": "1.0.0" } @@ -5781,7 +6340,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, "requires": { "onetime": "2.0.1", "signal-exit": "3.0.2" @@ -5791,7 +6349,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4" @@ -5800,14 +6357,26 @@ "rimraf": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "rlp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.0.0.tgz", + "integrity": "sha1-nbOE/0uJqPYVY9kjldhiWxjzr7A=" }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, "requires": { "is-promise": "2.1.0" } @@ -5815,14 +6384,12 @@ "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" }, "rx-lite-aggregates": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, "requires": { "rx-lite": "4.0.8" } @@ -5831,7 +6398,6 @@ "version": "5.5.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", "integrity": "sha512-Hxo2ac8gRQjwjtKgukMIwBRbq5+KAeEV5hXM4obYBOAghev41bDQWgFH4svYiU9UnQ5kNww2LgfyBdevCd2HXA==", - "dev": true, "requires": { "symbol-observable": "1.0.1" } @@ -5839,20 +6405,37 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "scoped-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" + }, + "secp256k1": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.0.tgz", + "integrity": "sha512-e5QIJl8W7Y4tT6LHffVcZAxJjvpgE5Owawv6/XCYPQljE9aP2NFFddQ8OYMKhdLshNu88FfL3qCN3/xYkXGRsA==", + "requires": { + "bindings": "1.3.0", + "bip66": "1.1.5", + "bn.js": "4.11.6", + "create-hash": "1.2.0", + "drbg.js": "1.0.1", + "elliptic": "6.4.0", + "nan": "2.10.0", + "safe-buffer": "5.1.1" + } }, - "scoped-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", - "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=", - "dev": true + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "send": { "version": "0.16.2", @@ -5903,8 +6486,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-immediate-shim": { "version": "1.0.1", @@ -5919,11 +6501,19 @@ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", "dev": true }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, "sha3": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.0.tgz", "integrity": "sha1-aYnxtwpJhwWHajc+LGKs6WqpOZo=", - "dev": true, "requires": { "nan": "2.10.0" } @@ -5932,7 +6522,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, "requires": { "shebang-regex": "1.0.0" } @@ -5940,43 +6529,32 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "shelljs": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", - "dev": true, "requires": { "glob": "7.1.2", "interpret": "1.1.0", "rechoir": "0.6.2" } }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "simple-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", - "dev": true + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" }, "simple-get": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz", "integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==", - "dev": true, "requires": { "decompress-response": "3.3.0", "once": "1.4.0", @@ -5986,20 +6564,17 @@ "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" }, "slide": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" }, "sntp": { "version": "2.1.0", @@ -6013,14 +6588,12 @@ "sol-explore": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", - "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=", - "dev": true + "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=" }, "solc": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.23.tgz", "integrity": "sha512-AT7anLHY6uIRg2It6N0UlCHeZ7YeecIkUhnlirrCgCPCUevtnoN48BxvgigN/4jJTRljv5oFhAJtI6gvHzT5DQ==", - "dev": true, "requires": { "fs-extra": "0.30.0", "memorystream": "0.3.1", @@ -6032,20 +6605,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1", @@ -6056,7 +6626,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, "requires": { "path-exists": "2.1.0", "pinkie-promise": "2.0.1" @@ -6066,7 +6635,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -6075,7 +6643,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", @@ -6088,7 +6655,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, "requires": { "lcid": "1.0.0" } @@ -6097,7 +6663,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, "requires": { "error-ex": "1.3.1" } @@ -6106,7 +6671,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, "requires": { "pinkie-promise": "2.0.1" } @@ -6115,7 +6679,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -6125,14 +6688,12 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, "requires": { "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", @@ -6143,7 +6704,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, "requires": { "find-up": "1.1.2", "read-pkg": "1.1.0" @@ -6153,7 +6713,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -6164,7 +6723,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -6172,20 +6730,17 @@ "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" }, "yargs": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, "requires": { "cliui": "3.2.0", "decamelize": "1.2.0", @@ -6207,7 +6762,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, "requires": { "camelcase": "3.0.0", "lodash.assign": "4.2.0" @@ -6215,11 +6769,30 @@ } } }, + "solhint": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.2.1.tgz", + "integrity": "sha512-3B0ydhkOlicyyTmKnwJC6kiwdJUXvbbDYXcy8m7rznoQPgzzkmSOsJgb9BAe+KBQP5BD3PLgcoOQ84t3FSxqsQ==", + "requires": { + "antlr4": "4.7.0", + "commander": "2.11.0", + "eslint": "4.19.1", + "glob": "7.1.2", + "ignore": "3.3.10", + "lodash": "4.17.10" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } + } + }, "solidity-coverage": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.4.14.tgz", - "integrity": "sha512-4IizUjKsBpdIe5cVB/jfjuwO9On91JLxxCyID9poSW9owaQaXRHGlQltWUFbLlAbzb0dBsPscRnv2byDbKYQTA==", - "dev": true, + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.5.5.tgz", + "integrity": "sha512-WexTLFZ3NBIWGYpNgWHtFLkASdoGP0i5Q/OJzwoCpHNtG1QrJO/mxUctc5BghP8srwMN8HxCtUJtu/eyGbIOJw==", "requires": { "death": "1.1.0", "ethereumjs-testrpc-sc": "6.1.2", @@ -6228,7 +6801,8 @@ "req-cwd": "1.0.1", "shelljs": "0.7.8", "sol-explore": "1.6.2", - "solidity-parser-sc": "0.4.6", + "solidity-parser-sc": "0.4.11", + "tree-kill": "1.2.0", "web3": "0.18.4" }, "dependencies": { @@ -6236,22 +6810,32 @@ "version": "0.7.8", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, "requires": { "glob": "7.1.2", "interpret": "1.1.0", "rechoir": "0.6.2" } + }, + "web3": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", + "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } } } }, "solidity-parser-sc": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.6.tgz", - "integrity": "sha512-+fu+4L4XomonLf/BvG0hv/otIpWr7wFB0X/QHzfQP68ER+FrQ8vou11/OPsOqc7yHWhowi0oe4JcKFZgAEUThw==", - "dev": true, + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz", + "integrity": "sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw==", "requires": { - "mocha": "2.5.3", + "mocha": "4.1.0", "pegjs": "0.10.0", "yargs": "4.8.1" }, @@ -6259,20 +6843,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1", @@ -6280,51 +6861,41 @@ } }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { - "ms": "0.7.1" + "ms": "2.0.0" } }, "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, "requires": { "path-exists": "2.1.0", "pinkie-promise": "2.0.1" } }, - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimatch": "0.3.0" - } + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -6333,7 +6904,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", @@ -6342,51 +6912,27 @@ "strip-bom": "2.0.0" } }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - }, "mocha": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", - "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", "requires": { - "commander": "2.3.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", - "growl": "1.9.2", - "jade": "0.26.3", + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" + "supports-color": "4.4.0" } }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, "requires": { "lcid": "1.0.0" } @@ -6395,7 +6941,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, "requires": { "error-ex": "1.3.1" } @@ -6404,7 +6949,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, "requires": { "pinkie-promise": "2.0.1" } @@ -6413,7 +6957,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -6423,14 +6966,12 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, "requires": { "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", @@ -6441,7 +6982,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, "requires": { "find-up": "1.1.2", "read-pkg": "1.1.0" @@ -6451,7 +6991,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -6462,34 +7001,32 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } }, "supports-color": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", - "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", - "dev": true + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "2.0.0" + } }, "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" }, "yargs": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, "requires": { "cliui": "3.2.0", "decamelize": "1.2.0", @@ -6511,7 +7048,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, "requires": { "camelcase": "3.0.0", "lodash.assign": "4.2.0" @@ -6523,7 +7059,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, "requires": { "is-plain-obj": "1.1.0" } @@ -6531,14 +7066,12 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", - "dev": true, "requires": { "source-map": "0.6.1" } @@ -6547,7 +7080,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, "requires": { "spdx-expression-parse": "3.0.0", "spdx-license-ids": "3.0.0" @@ -6556,14 +7088,12 @@ "spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "2.1.0", "spdx-license-ids": "3.0.0" @@ -6572,14 +7102,12 @@ "spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.14.1", @@ -6607,7 +7135,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", - "dev": true, "requires": { "any-observable": "0.2.0" } @@ -6615,20 +7142,17 @@ "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" @@ -6638,7 +7162,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -6653,7 +7176,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "3.0.0" } @@ -6662,7 +7184,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, "requires": { "is-utf8": "0.2.1" } @@ -6671,7 +7192,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", - "dev": true, "requires": { "first-chunk-stream": "2.0.0", "strip-bom": "2.0.0" @@ -6680,23 +7200,25 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "dev": true, "requires": { "is-hex-prefixed": "1.0.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, "supports-color": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -6704,20 +7226,76 @@ "symbol-observable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.2", + "lodash": "4.17.5", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + } + } }, "tapable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.6.1" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.5", + "to-buffer": "1.1.1", + "xtend": "4.0.1" + } }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "dev": true, "requires": { "os-tmpdir": "1.0.2", "rimraf": "2.2.8" @@ -6726,26 +7304,22 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "textextensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", - "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==", - "dev": true + "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, "requires": { "readable-stream": "2.3.5", "xtend": "4.0.1" @@ -6754,29 +7328,26 @@ "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "requires": { "os-tmpdir": "1.0.2" } }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" }, - "to-iso-string": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", - "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", - "dev": true - }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", @@ -6786,6 +7357,11 @@ "punycode": "1.4.1" } }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" + }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -6795,8 +7371,7 @@ "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, "truffle": { "version": "4.1.7", @@ -6813,7 +7388,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -6829,7 +7403,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "1.1.2" } @@ -6850,11 +7423,15 @@ "mime-types": "2.1.18" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, "optional": true, "requires": { "source-map": "0.5.7", @@ -6866,14 +7443,12 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, "optional": true }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, "optional": true, "requires": { "center-align": "0.1.3", @@ -6885,21 +7460,18 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, "optional": true }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, "optional": true }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, "optional": true, "requires": { "camelcase": "1.2.1", @@ -6914,7 +7486,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, "optional": true }, "ultron": { @@ -6926,8 +7497,7 @@ "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" }, "unpipe": { "version": "1.0.0", @@ -6938,14 +7508,12 @@ "untildify": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz", - "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", - "dev": true + "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=" }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, "requires": { "prepend-http": "2.0.0" } @@ -6959,8 +7527,7 @@ "url-to-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, "user-home": { "version": "1.1.1", @@ -6971,14 +7538,12 @@ "utf8": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", - "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=", - "dev": true + "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", @@ -6995,8 +7560,7 @@ "v8-compile-cache": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz", - "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==", - "dev": true + "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==" }, "v8flags": { "version": "2.1.1", @@ -7011,7 +7575,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true, "requires": { "spdx-correct": "3.0.0", "spdx-expression-parse": "3.0.0" @@ -7038,7 +7601,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, "requires": { "clone": "1.0.3", "clone-stats": "0.0.1", @@ -7049,7 +7611,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -7062,22 +7623,27 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, "web3": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", - "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", - "dev": true, + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", + "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", "requires": { - "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "bignumber.js": "4.1.0", "crypto-js": "3.1.8", "utf8": "2.1.2", "xhr2": "0.1.4", "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "bignumber.js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" + } } }, "web3-core-helpers": { @@ -7162,7 +7728,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", - "dev": true, "requires": { "jscodeshift": "0.4.1" }, @@ -7170,20 +7735,17 @@ "ast-types": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", - "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==", - "dev": true + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" }, "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, "jscodeshift": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", - "dev": true, "requires": { "async": "1.5.2", "babel-plugin-transform-flow-strip-types": "6.22.0", @@ -7206,7 +7768,6 @@ "version": "0.12.9", "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", - "dev": true, "requires": { "ast-types": "0.10.1", "core-js": "2.5.3", @@ -7221,7 +7782,6 @@ "version": "2.0.12", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.12.tgz", "integrity": "sha512-kMi6NquWwUhmQok2IFrtAEIbaVvujzYvtDGb5WElkwylbLboDsCgizv8IjSi/Q6SQRJ8Crayl1JCBnIJ3rU4Rg==", - "dev": true, "requires": { "chalk": "2.3.2", "cross-spawn": "6.0.5", @@ -7254,7 +7814,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, "requires": { "isexe": "2.0.0" } @@ -7262,27 +7821,36 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "2.1.1" + } }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, "optional": true }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1" @@ -7291,14 +7859,12 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -7307,7 +7873,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -7318,7 +7883,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -7328,14 +7892,20 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "0.5.1" + } }, "write-file-atomic": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "imurmurhash": "0.1.4", @@ -7392,38 +7962,32 @@ "xhr2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", - "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=", - "dev": true + "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" }, "xmlhttprequest": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", - "dev": true + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", - "dev": true, "requires": { "cliui": "4.0.0", "decamelize": "1.2.0", @@ -7443,7 +8007,6 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, "requires": { "camelcase": "4.1.0" } @@ -7452,7 +8015,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.0.5.tgz", "integrity": "sha512-6/W7/B54OPHJXob0n0+pmkwFsirC8cokuQkPSmT/D0lCcSxkKtg/BA6ZnjUBIwjuGqmw3DTrT4en++htaUju5g==", - "dev": true, "requires": { "chalk": "2.3.2", "debug": "3.1.0", @@ -7473,7 +8035,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -7482,7 +8043,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, "requires": { "ansi-escapes": "3.0.0", "chalk": "2.3.2", @@ -7506,7 +8066,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.3.tgz", "integrity": "sha512-mODmrZ26a94djmGZZuIiomSGlN4wULdou29ZwcySupb2e9FdvoCl7Ps2FqHFjEHio3kOl/iBeaNqrnx3C3NwWg==", - "dev": true, "requires": { "async": "2.6.0", "chalk": "2.3.2", @@ -7539,7 +8098,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, "requires": { "lodash": "4.17.5" } @@ -7548,7 +8106,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, "requires": { "lru-cache": "4.1.2", "shebang-command": "1.2.0", @@ -7559,7 +8116,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -7567,14 +8123,12 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "7.1.2" } diff --git a/test/ion.js b/test/ion.js index 5a38239..49bfc79 100644 --- a/test/ion.js +++ b/test/ion.js @@ -27,45 +27,73 @@ const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" const TESTBLOCK = { - difficulty: 2, - extraData: '0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00', - gasLimit: 5635559972940396, - gasUsed: 273138, - hash: '0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4', - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - miner: '0x0000000000000000000000000000000000000000', - mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', - nonce: '0x0000000000000000', - number: 5446, - parentHash: '0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284', - receiptsRoot: '0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1', - sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - size: 2027, - stateRoot: '0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967', - timestamp: 1531327572, - totalDifficulty: 10893, - transactions: - [ '0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3', - '0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5', - '0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8', - '0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6', - '0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8', - '0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1', - '0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446', - '0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462', - '0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e', - '0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314', - '0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d', - '0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede', - '0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc' ], - transactionsRoot: '0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35', + difficulty: 12549329517745, + extraData: "0xd783010303844765746887676f312e352e31856c696e7578", + gasLimit: 3141592, + gasUsed: 63000, + hash: "0x95c3a05973fec7bf98f1131a72e607b4eba171d0576571cf83ee7162bbcdb7d9", + logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + miner: "0x95581ea0c5b362933f3523138f54d51eae817211", + mixHash: "0xa01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6", + nonce: "0x1c080c4ec6f2553b", + number: 1000002, + parentHash: "0xcb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4f", + receiptsRoot: "0x97097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647", + sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + size: 883, + stateRoot: "0x643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5", + timestamp: 1455404078, + totalDifficulty: 7135227569124568698, + transactions: ["0x2bd653c639c086ad1c6e468d2cbdba76fc144f747373be6d2db7854d0d0e36e7", "0x7e3abff232dd5fc72db441807bcd59d9f17311a960a8f6ff6d0e693c22fa1eb2", "0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893"], + transactionsRoot: "0xdbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2", uncles: [] } -const TESTRLPENCODING = "0xf9025fa0aa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0b347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967a0cb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35a01d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002821546871405830e4c2a6c83042af2845b463454b861d88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" -const TEST_NODE_VALUE = "0xf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a" -const TEST_PATH = "0x80" -const TEST_PARENT_NODES = "0xf8c3f851a0448f4ee6a987bf17a91096e25247c3d7d78dbd08afddb5cfd4186d6a9f36bbc080808080808080a0c47289442eb85e0ca1f12c5ac6168f15513036935879931655dadfad3586dcb78080808080808080f86e30b86bf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a" +const TESTRLPENCODING = "0xf90217a0cb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495581ea0c5b362933f3523138f54d51eae817211a0643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5a0dbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2a097097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000860b69de53fcb1830f4242832fefd882f6188456bfb42e98d783010303844765746887676f312e352e31856c696e7578a0a01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6881c080c4ec6f2553b" +const TEST_PATH = "0x02" + +const TEST_TX_VALUE = "0xf8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" +const TEST_TX_NODES = "0xf9011df851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" + +const TEST_RECEIPT_VALUE = "0xf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" +const TEST_RECEIPT_NODES = "0xf901d8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" + +//{ difficulty: 2, +// extraData: '0xd88301080b846765746888676f312e31302e32856c696e757800000000000000a317eac1407c2095a544b7574618e307f4a3308489c9570a87424fd8057714b20701902291849b8586a1d5044282a638017429bfcd36cd01d145515ce3fac5b201', +// gasLimit: 447846308142, +// gasUsed: 1395032, +// hash: '0x53e7275992ff72155dbacfde26881872d7b322afe47b104c7e96079761100a55', +// logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', +// miner: '0x0000000000000000000000000000000000000000', +// mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', +// nonce: '0x0000000000000000', +// number: 15108, +// parentHash: '0x07844784b5ed519502da2708ecbc1a3f918bae7b3daba06bd55e08f3dcaa42c9', +// receiptsRoot: '0x6fc7cc2a8c59c0e2c84fe806d652e636d1a513b9c3cefbe0b53920c5787a1e2c', +// sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', +// size: 5758, +// stateRoot: '0x732b314700d866f88c612c8ae3cc74c91f2e873b66ae13eb8cb5f54780441d14', +// timestamp: 1531404477, +// totalDifficulty: 30217, +// transactions: +// [ '0xb8aece2b5060358b4eb788a64e240bd29fa82c6edd277b4b7d58c9a8b6b57959' ], +// transactionsRoot: '0xf79d0f0f21b250c65ce2817fde4f2d4bf2edb23de4b1f06550a8f2fa8e34aa4e', +// uncles: [] } +//EP Root hash = 0xf79d0f0f21b250c65ce2817fde4f2d4bf2edb23de4b1f06550a8f2fa8e34aa4e +//PATH = 0x80 +//RLP ENCODED NODE = 0xf9141d822080b91417f91414820c5f85174876e800836691b78080b913bd608060405234801561001057600080fd5b5060405160208061139d8339810160405251600055611369806100346000396000f30060806040526004361061007f5763ffffffff60e060020a600035041663550325b581146100845780635a0235e4146100ae5780636b4f9b9d14610110578063927a32e3146101605780639a8a0592146101965780639e43d86b146101ab578063affd8be9146101c3578063bec205b9146102b3578063fecc37c31461038f575b600080fd5b34801561009057600080fd5b5061009c6004356103aa565b60408051918252519081900360200190f35b3480156100ba57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261010e9482359460248035953695946064949201919081908401838280828437509497506103c99650505050505050565b005b34801561011c57600080fd5b5061012860043561056e565b6040518082606080838360005b8381101561014d578181015183820152602001610135565b5050505090500191505060405180910390f35b34801561016c57600080fd5b506101786004356105b5565b60408051938452602084019290925282820152519081900360600190f35b3480156101a257600080fd5b5061009c6105d6565b3480156101b757600080fd5b5061010e6004356105dc565b3480156101cf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061071b9650505050505050565b604080519115158252519081900360200190f35b3480156102bf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610a9a9650505050505050565b34801561039b57600080fd5b5061009c600435602435610deb565b60018054829081106103b857fe5b600091825260209091200154905081565b60606000808581805b60015481101561040e5760018054829081106103ea57fe5b600091825260209091200154831415610406576001915061040e565b6001016103d2565b811515610465576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61047661047188610e1b565b610e6e565b9550866040518082805190602001908083835b602083106104a85780518252601f199092019160209182019101610489565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209750505088861490506104e357600080fd5b6000888152600360205260408120875190955061051f9161051891899190811061050957fe5b90602001906020020151610f23565b6001610f77565b8455855161053890610518908890600490811061050957fe5b6001850155855161055490610518908890600590811061050957fe5b60028501556105638989611005565b505050505050505050565b6105766112e6565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b6000805482141561065d576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106e657600180548391908390811061067c57fe5b60009182526020909120015414156106de576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b600101610661565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b60015481101561075e57600180548290811061073a57fe5b600091825260209091200154831415610756576001915061075e565b600101610722565b8115156107b5576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b81548110156108045781818154811015156107e057fe5b6000918252602090912001548414156107fc5760019250610804565b6001016107c9565b82151561085b576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600101546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108ff5781810151838201526020016108e7565b50505050905090810190601f16801561092c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561095f578181015183820152602001610947565b50505050905090810190601f16801561098c5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156109bf5781810151838201526020016109a7565b50505050905090810190601f1680156109ec5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610a0e57600080fd5b505af4158015610a22573d6000803e3d6000fd5b505050506040513d6020811015610a3857600080fd5b50511515610a4257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f60005b60408051938452602084019290925282820152519081900360600190a15060019e9d5050505050505050505050505050565b6000808681805b600154811015610add576001805482908110610ab957fe5b600091825260209091200154831415610ad55760019150610add565b600101610aa1565b811515610b34576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b8154811015610b83578181815481101515610b5f57fe5b600091825260209091200154841415610b7b5760019250610b83565b600101610b48565b821515610bda576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600201546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610c7e578181015183820152602001610c66565b50505050905090810190601f168015610cab5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610cde578181015183820152602001610cc6565b50505050905090810190601f168015610d0b5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610d3e578181015183820152602001610d26565b50505050905090810190601f168015610d6b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610d8d57600080fd5b505af4158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b50511515610dc157fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f6001610a68565b600260205281600052604060002081815481101515610e0657fe5b90600052602060002001600091509150505481565b610e23611305565b81516000811515610e495760408051808201909152600080825260208201529250610e67565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e7a61131c565b6000610e8585611065565b1515610e9057600080fd5b610e998561108f565b925082604051908082528060200260200182016040528015610ed557816020015b610ec2611305565b815260200190600190039081610eba5790505b509350610ee1856110ff565b91505b610eed82611138565b15610f1b57610efb82611157565b8482815181101515610f0957fe5b60209081029091010152600101610ee4565b505050919050565b6020810151606090801515610f37576105af565b806040519080825280601f01601f191660200182016040528015610f65578160200160208202803883390190505b5091506105af83600001518383611199565b600080805b6020811015610ffd578060080285828601815181101515610f9957fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610f7c565b509392505050565b6000828152600260205260408120905b815481101561104d578154839083908390811061102e57fe5b600091825260209091200154141561104557600080fd5b600101611015565b50805460018101825560009182526020909120015550565b60008082602001516000141561107e57600091506105af565b5050515160c060009190911a101590565b6000806000806000806110a187611065565b15156110b057600095506110f5565b8651805160001a955093506110c4876111d9565b840192506001876020015185010391505b8183116110f1576110e583611259565b909201916001016110d5565b8095505b5050505050919050565b61110761131c565b600061111283611065565b151561111d57600080fd5b611126836111d9565b83519383529092016020820152919050565b6000611142611305565b50508051602080820151915192015191011190565b61115f611305565b60008061116b84611138565b1561007f578360200151915061118082611259565b8284526020808501829052838201908601529050610e67565b60006020601f83010484602085015b8284146111c6576020840282810151908201526001909301926111a8565b6000865160200187015250505050505050565b60008060008360200151600014156111f45760009250610e67565b50508151805160001a9060808210156112105760009250610e67565b60b882108061122b575060c0821015801561122b575060f882105b156112395760019250610e67565b60c082101561124e5760b51982019250610e67565b5060f5190192915050565b8051600090811a608081101561127257600191506105af565b60b881101561128757607e19810191506105af565b60c08110156112b057600183015160b76020839003016101000a9004810160b5190191506105af565b60f88110156112c55760be19810191506105af565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280611330611305565b81526020016000815250905600a165627a7a7230582024e7bd39ca02a13e7b30d3f8eabcff1f54aa2b2794c25da896d910015790ad590029ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075820bf9a0cf066fe78ea2e58000322d541b37763dc8d5daad8b301e63d0d2e5bdc3f2fe6ca048f44173b406c4ebd09b4f52174d00e6019820ea92f1caa5dd49d2f5652671ad +//HASHED NODE = 0xf79d0f0f21b250c65ce2817fde4f2d4bf2edb23de4b1f06550a8f2fa8e34aa4e +//EXTENSION NODE WITH PATHPTR = 2 +//EP TX VALUE = 0xf91414820c5f85174876e800836691b78080b913bd608060405234801561001057600080fd5b5060405160208061139d8339810160405251600055611369806100346000396000f30060806040526004361061007f5763ffffffff60e060020a600035041663550325b581146100845780635a0235e4146100ae5780636b4f9b9d14610110578063927a32e3146101605780639a8a0592146101965780639e43d86b146101ab578063affd8be9146101c3578063bec205b9146102b3578063fecc37c31461038f575b600080fd5b34801561009057600080fd5b5061009c6004356103aa565b60408051918252519081900360200190f35b3480156100ba57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261010e9482359460248035953695946064949201919081908401838280828437509497506103c99650505050505050565b005b34801561011c57600080fd5b5061012860043561056e565b6040518082606080838360005b8381101561014d578181015183820152602001610135565b5050505090500191505060405180910390f35b34801561016c57600080fd5b506101786004356105b5565b60408051938452602084019290925282820152519081900360600190f35b3480156101a257600080fd5b5061009c6105d6565b3480156101b757600080fd5b5061010e6004356105dc565b3480156101cf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061071b9650505050505050565b604080519115158252519081900360200190f35b3480156102bf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610a9a9650505050505050565b34801561039b57600080fd5b5061009c600435602435610deb565b60018054829081106103b857fe5b600091825260209091200154905081565b60606000808581805b60015481101561040e5760018054829081106103ea57fe5b600091825260209091200154831415610406576001915061040e565b6001016103d2565b811515610465576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61047661047188610e1b565b610e6e565b9550866040518082805190602001908083835b602083106104a85780518252601f199092019160209182019101610489565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209750505088861490506104e357600080fd5b6000888152600360205260408120875190955061051f9161051891899190811061050957fe5b90602001906020020151610f23565b6001610f77565b8455855161053890610518908890600490811061050957fe5b6001850155855161055490610518908890600590811061050957fe5b60028501556105638989611005565b505050505050505050565b6105766112e6565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b6000805482141561065d576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106e657600180548391908390811061067c57fe5b60009182526020909120015414156106de576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b600101610661565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b60015481101561075e57600180548290811061073a57fe5b600091825260209091200154831415610756576001915061075e565b600101610722565b8115156107b5576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b81548110156108045781818154811015156107e057fe5b6000918252602090912001548414156107fc5760019250610804565b6001016107c9565b82151561085b576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600101546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108ff5781810151838201526020016108e7565b50505050905090810190601f16801561092c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561095f578181015183820152602001610947565b50505050905090810190601f16801561098c5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156109bf5781810151838201526020016109a7565b50505050905090810190601f1680156109ec5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610a0e57600080fd5b505af4158015610a22573d6000803e3d6000fd5b505050506040513d6020811015610a3857600080fd5b50511515610a4257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f60005b60408051938452602084019290925282820152519081900360600190a15060019e9d5050505050505050505050505050565b6000808681805b600154811015610add576001805482908110610ab957fe5b600091825260209091200154831415610ad55760019150610add565b600101610aa1565b811515610b34576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b8154811015610b83578181815481101515610b5f57fe5b600091825260209091200154841415610b7b5760019250610b83565b600101610b48565b821515610bda576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600201546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610c7e578181015183820152602001610c66565b50505050905090810190601f168015610cab5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610cde578181015183820152602001610cc6565b50505050905090810190601f168015610d0b5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610d3e578181015183820152602001610d26565b50505050905090810190601f168015610d6b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610d8d57600080fd5b505af4158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b50511515610dc157fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f6001610a68565b600260205281600052604060002081815481101515610e0657fe5b90600052602060002001600091509150505481565b610e23611305565b81516000811515610e495760408051808201909152600080825260208201529250610e67565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e7a61131c565b6000610e8585611065565b1515610e9057600080fd5b610e998561108f565b925082604051908082528060200260200182016040528015610ed557816020015b610ec2611305565b815260200190600190039081610eba5790505b509350610ee1856110ff565b91505b610eed82611138565b15610f1b57610efb82611157565b8482815181101515610f0957fe5b60209081029091010152600101610ee4565b505050919050565b6020810151606090801515610f37576105af565b806040519080825280601f01601f191660200182016040528015610f65578160200160208202803883390190505b5091506105af83600001518383611199565b600080805b6020811015610ffd578060080285828601815181101515610f9957fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610f7c565b509392505050565b6000828152600260205260408120905b815481101561104d578154839083908390811061102e57fe5b600091825260209091200154141561104557600080fd5b600101611015565b50805460018101825560009182526020909120015550565b60008082602001516000141561107e57600091506105af565b5050515160c060009190911a101590565b6000806000806000806110a187611065565b15156110b057600095506110f5565b8651805160001a955093506110c4876111d9565b840192506001876020015185010391505b8183116110f1576110e583611259565b909201916001016110d5565b8095505b5050505050919050565b61110761131c565b600061111283611065565b151561111d57600080fd5b611126836111d9565b83519383529092016020820152919050565b6000611142611305565b50508051602080820151915192015191011190565b61115f611305565b60008061116b84611138565b1561007f578360200151915061118082611259565b8284526020808501829052838201908601529050610e67565b60006020601f83010484602085015b8284146111c6576020840282810151908201526001909301926111a8565b6000865160200187015250505050505050565b60008060008360200151600014156111f45760009250610e67565b50508151805160001a9060808210156112105760009250610e67565b60b882108061122b575060c0821015801561122b575060f882105b156112395760019250610e67565b60c082101561124e5760b51982019250610e67565b5060f5190192915050565b8051600090811a608081101561127257600191506105af565b60b881101561128757607e19810191506105af565b60c08110156112b057600183015160b76020839003016101000a9004810160b5190191506105af565b60f88110156112c55760be19810191506105af565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280611330611305565b81526020016000815250905600a165627a7a7230582024e7bd39ca02a13e7b30d3f8eabcff1f54aa2b2794c25da896d910015790ad590029ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075820bf9a0cf066fe78ea2e58000322d541b37763dc8d5daad8b301e63d0d2e5bdc3f2fe6ca048f44173b406c4ebd09b4f52174d00e6019820ea92f1caa5dd49d2f5652671ad +//EP TX PATH = 0x80 +//EP TX PARENT NODES = 0xf91420f9141d822080b91417f91414820c5f85174876e800836691b78080b913bd608060405234801561001057600080fd5b5060405160208061139d8339810160405251600055611369806100346000396000f30060806040526004361061007f5763ffffffff60e060020a600035041663550325b581146100845780635a0235e4146100ae5780636b4f9b9d14610110578063927a32e3146101605780639a8a0592146101965780639e43d86b146101ab578063affd8be9146101c3578063bec205b9146102b3578063fecc37c31461038f575b600080fd5b34801561009057600080fd5b5061009c6004356103aa565b60408051918252519081900360200190f35b3480156100ba57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261010e9482359460248035953695946064949201919081908401838280828437509497506103c99650505050505050565b005b34801561011c57600080fd5b5061012860043561056e565b6040518082606080838360005b8381101561014d578181015183820152602001610135565b5050505090500191505060405180910390f35b34801561016c57600080fd5b506101786004356105b5565b60408051938452602084019290925282820152519081900360600190f35b3480156101a257600080fd5b5061009c6105d6565b3480156101b757600080fd5b5061010e6004356105dc565b3480156101cf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061071b9650505050505050565b604080519115158252519081900360200190f35b3480156102bf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610a9a9650505050505050565b34801561039b57600080fd5b5061009c600435602435610deb565b60018054829081106103b857fe5b600091825260209091200154905081565b60606000808581805b60015481101561040e5760018054829081106103ea57fe5b600091825260209091200154831415610406576001915061040e565b6001016103d2565b811515610465576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61047661047188610e1b565b610e6e565b9550866040518082805190602001908083835b602083106104a85780518252601f199092019160209182019101610489565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209750505088861490506104e357600080fd5b6000888152600360205260408120875190955061051f9161051891899190811061050957fe5b90602001906020020151610f23565b6001610f77565b8455855161053890610518908890600490811061050957fe5b6001850155855161055490610518908890600590811061050957fe5b60028501556105638989611005565b505050505050505050565b6105766112e6565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b6000805482141561065d576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106e657600180548391908390811061067c57fe5b60009182526020909120015414156106de576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b600101610661565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b60015481101561075e57600180548290811061073a57fe5b600091825260209091200154831415610756576001915061075e565b600101610722565b8115156107b5576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b81548110156108045781818154811015156107e057fe5b6000918252602090912001548414156107fc5760019250610804565b6001016107c9565b82151561085b576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600101546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108ff5781810151838201526020016108e7565b50505050905090810190601f16801561092c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561095f578181015183820152602001610947565b50505050905090810190601f16801561098c5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156109bf5781810151838201526020016109a7565b50505050905090810190601f1680156109ec5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610a0e57600080fd5b505af4158015610a22573d6000803e3d6000fd5b505050506040513d6020811015610a3857600080fd5b50511515610a4257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f60005b60408051938452602084019290925282820152519081900360600190a15060019e9d5050505050505050505050505050565b6000808681805b600154811015610add576001805482908110610ab957fe5b600091825260209091200154831415610ad55760019150610add565b600101610aa1565b811515610b34576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b8154811015610b83578181815481101515610b5f57fe5b600091825260209091200154841415610b7b5760019250610b83565b600101610b48565b821515610bda576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600201546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610c7e578181015183820152602001610c66565b50505050905090810190601f168015610cab5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610cde578181015183820152602001610cc6565b50505050905090810190601f168015610d0b5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610d3e578181015183820152602001610d26565b50505050905090810190601f168015610d6b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610d8d57600080fd5b505af4158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b50511515610dc157fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f6001610a68565b600260205281600052604060002081815481101515610e0657fe5b90600052602060002001600091509150505481565b610e23611305565b81516000811515610e495760408051808201909152600080825260208201529250610e67565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e7a61131c565b6000610e8585611065565b1515610e9057600080fd5b610e998561108f565b925082604051908082528060200260200182016040528015610ed557816020015b610ec2611305565b815260200190600190039081610eba5790505b509350610ee1856110ff565b91505b610eed82611138565b15610f1b57610efb82611157565b8482815181101515610f0957fe5b60209081029091010152600101610ee4565b505050919050565b6020810151606090801515610f37576105af565b806040519080825280601f01601f191660200182016040528015610f65578160200160208202803883390190505b5091506105af83600001518383611199565b600080805b6020811015610ffd578060080285828601815181101515610f9957fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610f7c565b509392505050565b6000828152600260205260408120905b815481101561104d578154839083908390811061102e57fe5b600091825260209091200154141561104557600080fd5b600101611015565b50805460018101825560009182526020909120015550565b60008082602001516000141561107e57600091506105af565b5050515160c060009190911a101590565b6000806000806000806110a187611065565b15156110b057600095506110f5565b8651805160001a955093506110c4876111d9565b840192506001876020015185010391505b8183116110f1576110e583611259565b909201916001016110d5565b8095505b5050505050919050565b61110761131c565b600061111283611065565b151561111d57600080fd5b611126836111d9565b83519383529092016020820152919050565b6000611142611305565b50508051602080820151915192015191011190565b61115f611305565b60008061116b84611138565b1561007f578360200151915061118082611259565b8284526020808501829052838201908601529050610e67565b60006020601f83010484602085015b8284146111c6576020840282810151908201526001909301926111a8565b6000865160200187015250505050505050565b60008060008360200151600014156111f45760009250610e67565b50508151805160001a9060808210156112105760009250610e67565b60b882108061122b575060c0821015801561122b575060f882105b156112395760019250610e67565b60c082101561124e5760b51982019250610e67565b5060f5190192915050565b8051600090811a608081101561127257600191506105af565b60b881101561128757607e19810191506105af565b60c08110156112b057600183015160b76020839003016101000a9004810160b5190191506105af565b60f88110156112c55760be19810191506105af565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280611330611305565b81526020016000815250905600a165627a7a7230582024e7bd39ca02a13e7b30d3f8eabcff1f54aa2b2794c25da896d910015790ad590029ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075820bf9a0cf066fe78ea2e58000322d541b37763dc8d5daad8b301e63d0d2e5bdc3f2fe6ca048f44173b406c4ebd09b4f52174d00e6019820ea92f1caa5dd49d2f5652671ad +//PATH = 0x80 +//RLP ENCODED NODE = 0xf90112822080b9010cf901090183154958b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0 +//HASHED NODE = 0x6fc7cc2a8c59c0e2c84fe806d652e636d1a513b9c3cefbe0b53920c5787a1e2c +//EXTENSION NODE WITH PATHPTR = 2 +//EP RECEIPT VALUE = 0xf901090183154958b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0 +//EP RECEIPT PATH = 0x80 +//EP RECEIPT PARENT NODES = 0xf90115f90112822080b9010cf901090183154958b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0 contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { @@ -137,93 +165,84 @@ contract('Ion.js', (accounts) => { await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); - await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_NODE_VALUE, TEST_PARENT_NODES, TEST_PATH); + await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); }) -// it('Check EP Proofs', async () => { -// const ion = await Ion.new(DEPLOYEDCHAINID); -// -// // Building transactions in a block for better trie constructions -// for (let i = 0; i < 10; i++) { -// web3.eth.sendTransaction({from: web3.eth.accounts[0], to: ion.address, value:1}) -// } -// -// block = web3.eth.getBlock(5446); -// blockNumber = block.number; -// -// block.difficulty = block.difficulty.toNumber(); -// block.totalDifficulty = block.totalDifficulty.toNumber(); -// console.log(block); -// -// while (block.transactions < 1) { -// console.log("No transactions found for block: " + blockNumber.toString()); -// console.log("Trying again..."); -// blockNumber -= 1; -// block = web3.eth.getBlock(blockNumber); -// } -// -// txHash = block.transactions[0]; -// transaction = web3.eth.getTransaction(txHash); +// it('Check Infura Proofs', async () => { // -// var eP = new EP(web3.currentProvider); +// var eP = new EP(new Web3.providers.HttpProvider("https://gmainnet.infura.io")); // -// await eP.getTransactionTrieRoot(txHash).then( (root) => { -// console.log("EP Root hash = 0x" + root.toString('hex')) -// }) // // var txValue; // var txPath; // var txParentNodes; -// await eP.getTransactionProof(txHash).then( (proof) => { +// await eP.getTransactionProof("0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893").then( (proof) => { // verified = EP.transaction(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); // assert(verified); // // txValue = rlp.encode(proof.value); -// txPath = proof.path; +// txPath = rlp.encode(proof.path); // txParentNodes = rlp.encode(proof.parentNodes); // }) // -// console.log("EP VALUE = 0x" + txValue.toString('hex')); -// console.log("EP PATH = 0x" + txPath.toString('hex')); -// console.log("EP PARENT NODES = 0x" + txParentNodes.toString('hex')); +// +// console.log("EP TX VALUE = 0x" + txValue.toString('hex')); +// console.log("EP TX PATH = 0x" + txPath.toString('hex')); +// console.log("EP TX PARENT NODES = 0x" + txParentNodes.toString('hex')); // // }) -// it('Check Infura Proofs', async () => { + it('Fail Tx Proof', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await ion.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + + // Fail with wrong block hash + await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + + // Fail with wrong path + await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, "0xff").should.be.rejected; + }) + +// it('Check EP Receipt Proofs', async () => { // // var eP = new EP(new Web3.providers.HttpProvider("https://gmainnet.infura.io")); // -// await eP.getTransactionProof("0xb53f752216120e8cbe18783f41c6d960254ad59fac16229d4eaec5f7591319de").then( (proof) => { -// verified = EP.transaction(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); +// await eP.getReceiptTrieRoot("0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893").then( (root) => { +// console.log("EP Root hash = 0x" + root.toString('hex')) +// }) +// +// var txValue; +// var txPath; +// var txParentNodes; +// await eP.getReceiptProof("0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893").then( (proof) => { +// verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); // assert(verified); // // txValue = rlp.encode(proof.value); -// txPath = rlp.encode(proof.path); +// txPath = proof.path; // txParentNodes = rlp.encode(proof.parentNodes); // }) // +// console.log("EP RECEIPT VALUE = 0x" + txValue.toString('hex')); +// console.log("EP RECEIPT PATH = 0x" + txPath.toString('hex')); +// console.log("EP RECEIPT PARENT NODES = 0x" + txParentNodes.toString('hex')); // // }) - it('Fail Tx Proof', async () => { + it('Check Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); await ion.RegisterChain(TESTCHAINID); await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); - // Fail with wrong chain ID - await ion.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_NODE_VALUE, TEST_PARENT_NODES, TEST_PATH).should.be.rejected; - - // Fail with wrong block hash - await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_NODE_VALUE, TEST_PARENT_NODES, TEST_PATH).should.be.rejected; - - // Fail with wrong path - await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_NODE_VALUE, TEST_PARENT_NODES, "0xff").should.be.rejected; - }) - - it('Check Receipt Proof', () => { - + await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH); }) it('Fail Receipt Proof', () => { From dafdc681dc1f8d455a6d44493e2dc75b76d8db9e Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 13 Jul 2018 14:38:02 +0100 Subject: [PATCH 057/203] Added a single peer poa network and fixed up all the tests --- contracts/libraries/PatriciaTrie.sol | 2 +- ion-cli/setup.json | 3 +- package-lock.json | 918 +++++++++++++++--- package.json | 35 +- poa-network/{ => multi-peer}/accounts.txt | 0 poa-network/{ => multi-peer}/boot.key | 0 poa-network/{ => multi-peer}/genesis.json | 0 poa-network/multi-peer/node1/geth/LOCK | 0 .../node1/geth/chaindata/000002.ldb | Bin 0 -> 988 bytes .../multi-peer/node1/geth/chaindata/CURRENT | 1 + .../multi-peer/node1/geth/chaindata/LOCK | 0 .../multi-peer/node1/geth/chaindata/LOG | 18 + .../node1/geth/chaindata/MANIFEST-000004 | Bin 0 -> 215 bytes .../node1/geth/lightchaindata/000002.ldb | Bin 0 -> 988 bytes .../node1/geth/lightchaindata/000005.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000008.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000011.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000014.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000017.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000020.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000023.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000026.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000029.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000032.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000035.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000038.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000041.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000044.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000047.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000050.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000053.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000056.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000059.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000062.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000065.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000068.ldb | Bin 0 -> 988 bytes .../node1/geth/lightchaindata/CURRENT | 1 + .../multi-peer/node1/geth/lightchaindata/LOCK | 0 .../multi-peer/node1/geth/lightchaindata/LOG | 244 +++++ .../node1/geth/lightchaindata/MANIFEST-000067 | Bin 0 -> 2746 bytes poa-network/multi-peer/node1/geth/nodekey | 1 + .../multi-peer/node1/geth/nodes/000086.ldb | Bin 0 -> 352635 bytes .../multi-peer/node1/geth/nodes/CURRENT | 1 + poa-network/multi-peer/node1/geth/nodes/LOCK | 0 poa-network/multi-peer/node1/geth/nodes/LOG | 333 +++++++ .../node1/geth/nodes/MANIFEST-000085 | Bin 0 -> 862 bytes .../multi-peer/node1/geth/transactions.rlp | Bin 0 -> 31607 bytes ...--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 0 .../{ => multi-peer}/node1/password.txt | 0 poa-network/multi-peer/node2/geth/LOCK | 0 .../multi-peer/node2/geth/chaindata/CURRENT | 1 + .../multi-peer/node2/geth/chaindata/LOCK | 0 .../multi-peer/node2/geth/chaindata/LOG | 6 + .../node2/geth/chaindata/MANIFEST-000000 | Bin 0 -> 54 bytes .../node2/geth/lightchaindata/000002.ldb | Bin 0 -> 987 bytes .../node2/geth/lightchaindata/000005.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000008.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000011.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000014.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000017.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000020.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000023.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000026.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000029.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000032.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000035.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000038.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000041.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000044.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000047.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000050.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000053.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000056.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000059.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000062.ldb | Bin 0 -> 356 bytes .../node2/geth/lightchaindata/000065.ldb | Bin 0 -> 987 bytes .../node2/geth/lightchaindata/CURRENT | 1 + .../multi-peer/node2/geth/lightchaindata/LOCK | 0 .../multi-peer/node2/geth/lightchaindata/LOG | 233 +++++ .../node2/geth/lightchaindata/MANIFEST-000064 | Bin 0 -> 2627 bytes poa-network/multi-peer/node2/geth/nodekey | 1 + .../multi-peer/node2/geth/nodes/000078.ldb | Bin 0 -> 225108 bytes .../multi-peer/node2/geth/nodes/CURRENT | 1 + poa-network/multi-peer/node2/geth/nodes/LOCK | 0 poa-network/multi-peer/node2/geth/nodes/LOG | 299 ++++++ .../node2/geth/nodes/MANIFEST-000077 | Bin 0 -> 852 bytes .../multi-peer/node2/geth/transactions.rlp | 0 ...--8671e5e08d74f338ee1c462340842346d797afd3 | 0 .../{ => multi-peer}/node2/password.txt | 0 poa-network/single-peer/accounts.txt | 2 + poa-network/single-peer/genesis.json | 30 + poa-network/single-peer/node1/geth/LOCK | 0 .../node1/geth/chaindata/000002.ldb | Bin 0 -> 794 bytes .../single-peer/node1/geth/chaindata/CURRENT | 1 + .../single-peer/node1/geth/chaindata/LOCK | 0 .../single-peer/node1/geth/chaindata/LOG | 16 + .../node1/geth/chaindata/MANIFEST-000004 | Bin 0 -> 217 bytes .../node1/geth/lightchaindata/000002.ldb | Bin 0 -> 987 bytes .../node1/geth/lightchaindata/000005.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000008.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000011.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000014.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000017.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000020.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000023.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000026.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000029.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000032.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000035.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000038.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000041.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000044.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000047.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000050.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000053.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/000056.ldb | Bin 0 -> 356 bytes .../node1/geth/lightchaindata/CURRENT | 1 + .../node1/geth/lightchaindata/LOCK | 0 .../single-peer/node1/geth/lightchaindata/LOG | 267 +++++ .../node1/geth/lightchaindata/MANIFEST-000070 | Bin 0 -> 2270 bytes poa-network/single-peer/node1/geth/nodekey | 1 + .../single-peer/node1/geth/nodes/000098.ldb | Bin 0 -> 1327685 bytes .../single-peer/node1/geth/nodes/CURRENT | 1 + poa-network/single-peer/node1/geth/nodes/LOCK | 0 poa-network/single-peer/node1/geth/nodes/LOG | 379 ++++++++ .../node1/geth/nodes/MANIFEST-000097 | Bin 0 -> 862 bytes .../single-peer/node1/geth/transactions.rlp | Bin 0 -> 637035 bytes ...--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 1 + poa-network/single-peer/node1/password.txt | 1 + test/helpers/merkle.js | 5 + test/merkle.js | 2 +- test/validation.js | 96 +- 132 files changed, 2719 insertions(+), 183 deletions(-) rename poa-network/{ => multi-peer}/accounts.txt (100%) rename poa-network/{ => multi-peer}/boot.key (100%) rename poa-network/{ => multi-peer}/genesis.json (100%) create mode 100644 poa-network/multi-peer/node1/geth/LOCK create mode 100644 poa-network/multi-peer/node1/geth/chaindata/000002.ldb create mode 100644 poa-network/multi-peer/node1/geth/chaindata/CURRENT create mode 100644 poa-network/multi-peer/node1/geth/chaindata/LOCK create mode 100644 poa-network/multi-peer/node1/geth/chaindata/LOG create mode 100644 poa-network/multi-peer/node1/geth/chaindata/MANIFEST-000004 create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000002.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000005.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000008.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000011.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000014.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000017.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000020.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000023.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000026.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000029.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000032.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000035.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000038.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000041.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000044.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000047.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000050.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000053.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000056.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000059.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000062.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000065.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000068.ldb create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/CURRENT create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/LOCK create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/LOG create mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/MANIFEST-000067 create mode 100644 poa-network/multi-peer/node1/geth/nodekey create mode 100644 poa-network/multi-peer/node1/geth/nodes/000086.ldb create mode 100644 poa-network/multi-peer/node1/geth/nodes/CURRENT create mode 100644 poa-network/multi-peer/node1/geth/nodes/LOCK create mode 100644 poa-network/multi-peer/node1/geth/nodes/LOG create mode 100644 poa-network/multi-peer/node1/geth/nodes/MANIFEST-000085 create mode 100755 poa-network/multi-peer/node1/geth/transactions.rlp rename poa-network/{ => multi-peer}/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d (100%) rename poa-network/{ => multi-peer}/node1/password.txt (100%) create mode 100644 poa-network/multi-peer/node2/geth/LOCK create mode 100644 poa-network/multi-peer/node2/geth/chaindata/CURRENT create mode 100644 poa-network/multi-peer/node2/geth/chaindata/LOCK create mode 100644 poa-network/multi-peer/node2/geth/chaindata/LOG create mode 100644 poa-network/multi-peer/node2/geth/chaindata/MANIFEST-000000 create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000002.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000005.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000008.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000011.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000014.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000017.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000020.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000023.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000026.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000029.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000032.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000035.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000038.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000041.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000044.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000047.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000050.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000053.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000056.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000059.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000062.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000065.ldb create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/CURRENT create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/LOCK create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/LOG create mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/MANIFEST-000064 create mode 100644 poa-network/multi-peer/node2/geth/nodekey create mode 100644 poa-network/multi-peer/node2/geth/nodes/000078.ldb create mode 100644 poa-network/multi-peer/node2/geth/nodes/CURRENT create mode 100644 poa-network/multi-peer/node2/geth/nodes/LOCK create mode 100644 poa-network/multi-peer/node2/geth/nodes/LOG create mode 100644 poa-network/multi-peer/node2/geth/nodes/MANIFEST-000077 create mode 100755 poa-network/multi-peer/node2/geth/transactions.rlp rename poa-network/{ => multi-peer}/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 (100%) rename poa-network/{ => multi-peer}/node2/password.txt (100%) create mode 100644 poa-network/single-peer/accounts.txt create mode 100644 poa-network/single-peer/genesis.json create mode 100644 poa-network/single-peer/node1/geth/LOCK create mode 100644 poa-network/single-peer/node1/geth/chaindata/000002.ldb create mode 100644 poa-network/single-peer/node1/geth/chaindata/CURRENT create mode 100644 poa-network/single-peer/node1/geth/chaindata/LOCK create mode 100644 poa-network/single-peer/node1/geth/chaindata/LOG create mode 100644 poa-network/single-peer/node1/geth/chaindata/MANIFEST-000004 create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000002.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000005.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000008.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000011.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000014.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000017.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000020.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000023.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000026.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000029.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000032.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000035.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000038.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000041.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000044.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000047.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000050.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000053.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000056.ldb create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/CURRENT create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/LOCK create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/LOG create mode 100644 poa-network/single-peer/node1/geth/lightchaindata/MANIFEST-000070 create mode 100644 poa-network/single-peer/node1/geth/nodekey create mode 100644 poa-network/single-peer/node1/geth/nodes/000098.ldb create mode 100644 poa-network/single-peer/node1/geth/nodes/CURRENT create mode 100644 poa-network/single-peer/node1/geth/nodes/LOCK create mode 100644 poa-network/single-peer/node1/geth/nodes/LOG create mode 100644 poa-network/single-peer/node1/geth/nodes/MANIFEST-000097 create mode 100755 poa-network/single-peer/node1/geth/transactions.rlp create mode 100644 poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d create mode 100644 poa-network/single-peer/node1/password.txt diff --git a/contracts/libraries/PatriciaTrie.sol b/contracts/libraries/PatriciaTrie.sol index 4361bbd..ffb467e 100644 --- a/contracts/libraries/PatriciaTrie.sol +++ b/contracts/libraries/PatriciaTrie.sol @@ -4,7 +4,7 @@ import "./RLP.sol"; library PatriciaTrie { - function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) public returns (bool) { + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) public view returns (bool) { RLP.RLPItem memory nodes = RLP.toRLPItem(_parentNodes); RLP.RLPItem[] memory parentNodes = RLP.toList(nodes); diff --git a/ion-cli/setup.json b/ion-cli/setup.json index 0c6eafb..bf6032c 100644 --- a/ion-cli/setup.json +++ b/ion-cli/setup.json @@ -5,5 +5,6 @@ "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", "rpc-from":"http://127.0.0.1:8501", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f" } diff --git a/package-lock.json b/package-lock.json index 16f70ae..133c62c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -141,6 +141,17 @@ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -237,7 +248,8 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true }, "assign-symbols": { "version": "1.0.0", @@ -257,6 +269,13 @@ "lodash": "4.17.10" } }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true, + "optional": true + }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -282,6 +301,37 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.11.0", + "convert-source-map": "1.5.1", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.10", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -888,6 +938,63 @@ "babel-types": "6.26.0" } }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "3.2.8", + "invariant": "2.2.4", + "semver": "5.4.1" + } + }, "babel-preset-es2015": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", @@ -1123,9 +1230,16 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, "bignumber.js": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", - "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true, + "optional": true }, "binaryextensions": { "version": "2.1.1", @@ -1154,6 +1268,12 @@ "safe-buffer": "5.1.2" } }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", @@ -1270,6 +1390,16 @@ "parse-asn1": "5.1.1" } }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000865", + "electron-to-chromium": "1.3.52" + } + }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", @@ -1381,6 +1511,12 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, + "caniuse-lite": { + "version": "1.0.30000865", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", + "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1400,6 +1536,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, "requires": { "assertion-error": "1.1.0", "check-error": "1.0.2", @@ -1413,10 +1550,17 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, "requires": { "check-error": "1.0.2" } }, + "chai-bignumber": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/chai-bignumber/-/chai-bignumber-2.0.2.tgz", + "integrity": "sha512-BIdRNjRaoRj4bMsZLKbIZPMNKqmwnzNiyxqBYDSs6dFOCs9w8OHPuUE8e1bH60i1IhOzT0NjLtCD+lKEWB1KTQ==", + "dev": true + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -1437,7 +1581,26 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } }, "chownr": { "version": "1.0.1", @@ -1682,11 +1845,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -1774,9 +1932,9 @@ } }, "crypto-js": { - "version": "3.1.9-1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", - "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" }, "dargs": { "version": "5.1.0", @@ -1836,6 +1994,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, "requires": { "type-detect": "4.0.8" } @@ -2057,6 +2216,12 @@ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" }, + "electron-to-chromium": { + "version": "1.3.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", + "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", + "dev": true + }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", @@ -2357,7 +2522,7 @@ } }, "eth-proof": { - "version": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#98e4ee11051d3a9b0e4b1f06bce8098e627a5d55", + "version": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#35a299bc72d30b72ff6f2a4e0100caaf3516cfe2", "requires": { "ethereumjs-block": "1.7.1", "ethereumjs-tx": "1.3.6", @@ -2369,16 +2534,6 @@ "web3": "0.19.1" }, "dependencies": { - "bignumber.js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", - "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" - }, - "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" - }, "ethereum-common": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", @@ -2416,18 +2571,6 @@ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" } } - }, - "web3": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", - "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", - "requires": { - "bignumber.js": "4.1.0", - "crypto-js": "3.1.8", - "utf8": "2.1.2", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - } } } }, @@ -3212,11 +3355,546 @@ "rimraf": "2.6.2" } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -3254,7 +3932,8 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true }, "get-stream": { "version": "3.0.0", @@ -3898,6 +4577,16 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -5620,6 +6309,17 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, "p-cancelable": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", @@ -5793,7 +6493,8 @@ "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true }, "pbkdf2": { "version": "3.0.16", @@ -6125,6 +6826,19 @@ } } }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" + } + }, "recast": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.2.tgz", @@ -6566,6 +7280,13 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "optional": true + }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -7344,7 +8065,8 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true }, "type-is": { "version": "1.6.16", @@ -7570,6 +8292,12 @@ } } }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, "utf8": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", @@ -7595,6 +8323,15 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==" }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", @@ -7643,23 +8380,15 @@ } }, "web3": { - "version": "github:ethereum/web3.js#f55cfae489f4a28d7205970bd61ed6e2c05de093", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", + "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", "requires": { - "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", + "bignumber.js": "4.1.0", "crypto-js": "3.1.8", "utf8": "2.1.2", - "xhr2-cookies": "1.1.0", + "xhr2": "0.1.4", "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "bignumber.js": { - "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" - }, - "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" - } } }, "web3-core": { @@ -7754,36 +8483,11 @@ } } }, - "web3-eth": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.34.tgz", - "integrity": "sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg=", - "requires": { - "underscore": "1.8.3", - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-core-subscriptions": "1.0.0-beta.34", - "web3-eth-abi": "1.0.0-beta.34", - "web3-eth-accounts": "1.0.0-beta.34", - "web3-eth-contract": "1.0.0-beta.34", - "web3-eth-iban": "1.0.0-beta.34", - "web3-eth-personal": "1.0.0-beta.34", - "web3-net": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - } - } - }, "web3-eth-abi": { "version": "1.0.0-beta.34", "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", + "dev": true, "requires": { "bn.js": "4.11.6", "underscore": "1.8.3", @@ -7794,12 +8498,14 @@ "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true } } }, @@ -7842,28 +8548,6 @@ } } }, - "web3-eth-contract": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz", - "integrity": "sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY=", - "requires": { - "underscore": "1.8.3", - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-core-promievent": "1.0.0-beta.34", - "web3-core-subscriptions": "1.0.0-beta.34", - "web3-eth-abi": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - } - } - }, "web3-eth-iban": { "version": "1.0.0-beta.34", "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", @@ -7880,28 +8564,6 @@ } } }, - "web3-eth-personal": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz", - "integrity": "sha1-mvuhZzQuveVCC81YlcP2w0OI8gU=", - "requires": { - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-net": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-net": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.34.tgz", - "integrity": "sha1-QnzqL0MYgUScjjjVIykPFz+f9j0=", - "requires": { - "web3-core": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, "web3-providers-http": { "version": "1.0.0-beta.34", "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz", @@ -8352,14 +9014,6 @@ "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" }, - "xhr2-cookies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", - "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", - "requires": { - "cookiejar": "2.1.2" - } - }, "xmlhttprequest": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", diff --git a/package.json b/package.json index 70fedbb..d6001d6 100644 --- a/package.json +++ b/package.json @@ -8,26 +8,26 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", - "bignumber.js": "^7.2.1", - "chai": "^4.1.2", - "chai-as-promised": "^7.1.1", - "crypto-js": "^3.1.9-1", - "elliptic": "^6.4.0", - "eth-proof": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#log-encoding", + "eth-proof": "git@github.com:Shirikatsu/eth-proof.git#log-encoding", "ethereumjs-block": "^2.0.0", - "ethereumjs-tx": "^1.3.6", - "ethereumjs-util": "^5.2.0", - "ethjs-util": "^0.1.6", + "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", "rlp": "^2.0.0", "solc": "^0.4.23", "solhint": "^1.1.10", "solidity-coverage": "^0.5.0 ", - "web3": "github:ethereum/web3.js", - "web3-eth": "^1.0.0-beta.34", "web3-eth-accounts": "^1.0.0-beta.34" }, "devDependencies": { + "babel-cli": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-preset-env": "^1.6.1", + "babel-preset-es2015": "^6.24.1", + "babel-register": "^6.26.0", + "bluebird": "^3.5.1", + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", + "chai-bignumber": "^2.0.2", "ganache-cli": "^6.0.0", "json-bigint-string": "^1.0.0", "solidity-coverage": "^0.4.0", @@ -36,16 +36,15 @@ "web3-utils": "^1.0.0-beta.33" }, "scripts": { - "clean": "npm clean cache --force && rm -r ./build/contracts/*", - "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --gasLimit 0xFFFFFFF --gasPrice 0 --network-id 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpca": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpcb": "ganache-cli --port 8546 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 5678 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", "deploy": "truffle deploy", - "depclique": "truffle deploy --network clique", + "deploya": "truffle deploy --network testrpca", + "deployb": "truffle deploy --network testrpcb", "test": "truffle test --network clique", "coverage": "solidity-coverage", - "lint": "solhint contracts/**/*.sol", - "genbin": "solc --overwrite --bin ./contracts/* -o abi", - "genabi": "solc --overwrite --abi ./contracts/* -o abi", - "abigen": "abigen --bin=abi/Validation.bin --abi=abi/Validation.abi --pkg=validation --out=validation.go" + "lint": "solhint contracts/**/*.sol" } } diff --git a/poa-network/accounts.txt b/poa-network/multi-peer/accounts.txt similarity index 100% rename from poa-network/accounts.txt rename to poa-network/multi-peer/accounts.txt diff --git a/poa-network/boot.key b/poa-network/multi-peer/boot.key similarity index 100% rename from poa-network/boot.key rename to poa-network/multi-peer/boot.key diff --git a/poa-network/genesis.json b/poa-network/multi-peer/genesis.json similarity index 100% rename from poa-network/genesis.json rename to poa-network/multi-peer/genesis.json diff --git a/poa-network/multi-peer/node1/geth/LOCK b/poa-network/multi-peer/node1/geth/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/poa-network/multi-peer/node1/geth/chaindata/000002.ldb b/poa-network/multi-peer/node1/geth/chaindata/000002.ldb new file mode 100644 index 0000000000000000000000000000000000000000..9306c979453e2b1d499d9f78ca63b25137a5fda6 GIT binary patch literal 988 zcmeC={}9Tc(amT%XJS*&_TtxhZAWHA9eb=RZMnAPkGAK-z|Q?28)UN{FtRX!!H>=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsYv@=3rCln<)0UEwmj~b#I4WqmM;D#35?8~4g$cmY_X$k6$8VL ze?DyUeArktg6mc@voNyqZes~tQ1_65p@ET+VL@FmJEN*e0~mnv05DP+7{A=FULM_0 zkr7!K#CfcvJL$o+r+@MU*g*2aK+MfxGRwkEzk)%LIW04%B(+E{C$%g!CnZVGsT9c1 z%mXIT{9HFyX^lN>G9XQ0Lo+uX`YA5Lz{z}v@joY{2E%r+d0;6Qqb&WqZ2A+~#Xzd@ NgYe%C-72N-w*kGpN%8;y literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/chaindata/CURRENT b/poa-network/multi-peer/node1/geth/chaindata/CURRENT new file mode 100644 index 0000000..cacca75 --- /dev/null +++ b/poa-network/multi-peer/node1/geth/chaindata/CURRENT @@ -0,0 +1 @@ +MANIFEST-000004 diff --git a/poa-network/multi-peer/node1/geth/chaindata/LOCK b/poa-network/multi-peer/node1/geth/chaindata/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/poa-network/multi-peer/node1/geth/chaindata/LOG b/poa-network/multi-peer/node1/geth/chaindata/LOG new file mode 100644 index 0000000..b60b280 --- /dev/null +++ b/poa-network/multi-peer/node1/geth/chaindata/LOG @@ -0,0 +1,18 @@ +=============== Jul 13, 2018 (BST) =============== +13:56:18.180795 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:56:18.242233 db@open opening +13:56:18.242787 version@stat F·[] S·0B[] Sc·[] +13:56:18.256947 db@janitor F·2 G·0 +13:56:18.256978 db@open done T·14.717208ms +=============== Jul 13, 2018 (BST) =============== +13:56:18.332475 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:56:18.332632 version@stat F·[] S·0B[] Sc·[] +13:56:18.332654 db@open opening +13:56:18.332701 journal@recovery F·1 +13:56:18.335364 journal@recovery recovering @1 +13:56:18.343305 memdb@flush created L0@2 N·14 S·988B "9\x9c\x91..\x1dj\xe0,v4":"\xdb7C..b\xf5\xdc,v5" +13:56:18.345866 version@stat F·[1] S·988B[988B] Sc·[0.25] +13:56:18.361872 db@janitor F·3 G·0 +13:56:18.361936 db@open done T·29.262546ms +13:56:20.660995 db@close closing +13:56:20.661091 db@close done T·95.091µs diff --git a/poa-network/multi-peer/node1/geth/chaindata/MANIFEST-000004 b/poa-network/multi-peer/node1/geth/chaindata/MANIFEST-000004 new file mode 100644 index 0000000000000000000000000000000000000000..ebb5815c1a8d3d07176af1adcccc61c8983e9474 GIT binary patch literal 215 zcmaDb>0;0Y21Z7yoYb<^oRlOzr^=Gl^338?=ltA)#G=HK{30f1W>yw{b_S+9>>8GH zCN}kKFMgfZc4S7>vB$d7mTO!7XnQ^k?A-scK{o3FBMSo=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsYv@=3rCln<)0UEwmj~b#I4WqmM;D#35?8~4g$cmY_X$k6$8VL ze?DyUeArktg6mc@voNyqZes~tQ1_65p@ET+VL@FmJEN*e0~mnv05DP+7{A=FULM_0 zkr7!K#CfcvJL$o+r+@MU*g*2aK+MfxGRwkEzk)%LIW04%B(+E{C$%g!CnZVGsT9c1 z%mXIT{9HFyX^lN>G9XQ0Lo+uX`YA5Lz{z}v@joY{2E%r+d0;6Qqb&WqZ2A+~#Xzd@ NgYe%C-72N-w*kGpN%8;y literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000005.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000005.ldb new file mode 100644 index 0000000000000000000000000000000000000000..c480fadcbb16ef1d519c30d62f4bb8b6d6608498 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=&~ggKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0QHestpET3 literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000008.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000008.ldb new file mode 100644 index 0000000000000000000000000000000000000000..d2b26a1513df62490165abb9178df47524827180 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(5igKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7araSq}muu(H6 uxR{8GFmN)bG5+Ud)L=LX5{1|jQh)Z?Q%3!nOkyA*{2=^yL$^w)`)vRx>RJN; literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000011.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000011.ldb new file mode 100644 index 0000000000000000000000000000000000000000..df591285ec4a5126c6edcfcaadbe0d6cdbf90ba3 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(2hgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(8jgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c40gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0Gb3^x&QzG literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000020.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000020.ldb new file mode 100644 index 0000000000000000000000000000000000000000..0f885d9e99a6ddfd068f3d58435204b29fb142a7 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cA2gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c71gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cD3gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qiLgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm8l$aRU zK%$&L%*|leYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qoNgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qlMgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmH7Hgo`4N=yuF zAW=>r=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r05HB;{Qv*} literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000038.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000038.ldb new file mode 100644 index 0000000000000000000000000000000000000000..a05ec3826f2c34a6199189d16cc0a8392e95cf55 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qrOgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*08mI;GXMYp literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000041.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000041.ldb new file mode 100644 index 0000000000000000000000000000000000000000..c8f05dd77cbe3eac74780b6ebaab315d0e462feb GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANm$gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm?x!EOeQgq5PlH;yP;d9)crO9n~Yko literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000044.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000044.ldb new file mode 100644 index 0000000000000000000000000000000000000000..627147b4d7b2f480a6a51150b612a39211a8ccf9 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANs&gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANp%gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANv(gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0AdtcNB{r; literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000053.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000053.ldb new file mode 100644 index 0000000000000000000000000000000000000000..32548614e07c2dcfdabd893cf97d080abd9721d4 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HL=gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0A*QPO8@`> literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000056.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000056.ldb new file mode 100644 index 0000000000000000000000000000000000000000..3c07eed7394d4b6511ac7fd9c724fdf5e2425875 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HR?gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HO>gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HU@gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*09BbYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV6gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*07G9|3jhEB literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000068.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000068.ldb new file mode 100644 index 0000000000000000000000000000000000000000..f48d4b29e87d26a984acaf0bf636776b9e8b3e37 GIT binary patch literal 988 zcmeC={}9Tc(amT%XJS*&_TtxhZAWHA9eb=RZMnAPkGAK-z|Q?28)UN{FtRX!!H>=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yasx8Sr-sa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsYv@=3rCln<)0UEwmj~b#I4WqmM;D#35?8~4g$cmY_X$k6$8VL ze?DyUeArktg6mc@voNyqZes~tQ1_65p@ET+VL@FmJEN*e0~mnv05DP+7&DbGHbys8 zWJDGQaUSdFPI@ry>7P6SHjun95OXt_%(8IPuV7GQPRq_T4N8J3`i5i(2a+Fii L1·0 S·2KiB Q·23 +=============== Jul 12, 2018 (BST) =============== +14:39:49.043595 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:39:49.043714 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] +14:39:49.043726 db@open opening +14:39:49.043774 journal@recovery F·1 +14:39:49.044218 journal@recovery recovering @15 +14:39:49.051759 memdb@flush created L0@17 N·1 S·356B "eth..\x0e/(,v24":"eth..\x0e/(,v24" +14:39:49.051955 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] +14:39:49.074956 db@janitor F·8 G·0 +14:39:49.074982 db@open done T·31.248066ms +14:39:49.075058 table@compaction L0·6 -> L1·0 S·2KiB Q·25 +=============== Jul 12, 2018 (BST) =============== +15:37:17.901222 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:37:17.901345 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] +15:37:17.901358 db@open opening +15:37:17.901422 journal@recovery F·1 +15:37:17.901807 journal@recovery recovering @18 +15:37:17.910921 memdb@flush created L0@20 N·1 S·356B "eth..\x0e/(,v26":"eth..\x0e/(,v26" +15:37:17.911100 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] +15:37:17.925999 db@janitor F·9 G·0 +15:37:17.926024 db@open done T·24.657115ms +15:37:17.927614 table@compaction L0·7 -> L1·0 S·3KiB Q·28 +=============== Jul 12, 2018 (BST) =============== +15:48:30.010524 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:48:30.010703 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] +15:48:30.010717 db@open opening +15:48:30.010770 journal@recovery F·1 +15:48:30.018151 journal@recovery recovering @21 +15:48:30.031309 memdb@flush created L0@23 N·1 S·356B "eth..\x0e/(,v28":"eth..\x0e/(,v28" +15:48:30.031687 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] +15:48:30.059073 db@janitor F·10 G·0 +15:48:30.059100 db@open done T·48.376085ms +15:48:30.060310 table@compaction L0·8 -> L1·0 S·3KiB Q·29 +=============== Jul 12, 2018 (BST) =============== +16:05:26.776033 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:05:26.776165 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] +16:05:26.776176 db@open opening +16:05:26.776224 journal@recovery F·1 +16:05:26.776677 journal@recovery recovering @24 +16:05:26.785455 memdb@flush created L0@26 N·1 S·356B "eth..\x0e/(,v30":"eth..\x0e/(,v30" +16:05:26.785678 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] +16:05:26.809759 db@janitor F·11 G·0 +16:05:26.809855 table@compaction L0·9 -> L1·0 S·3KiB Q·31 +16:05:26.810715 db@open done T·33.614932ms +=============== Jul 12, 2018 (BST) =============== +16:23:47.424425 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:23:47.424527 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] +16:23:47.424540 db@open opening +16:23:47.424591 journal@recovery F·1 +16:23:47.425123 journal@recovery recovering @27 +16:23:47.439219 memdb@flush created L0@29 N·1 S·356B "eth..\x0e/(,v32":"eth..\x0e/(,v32" +16:23:47.439454 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] +16:23:47.467206 db@janitor F·12 G·0 +16:23:47.467230 db@open done T·42.681537ms +16:23:47.467849 table@compaction L0·10 -> L1·0 S·4KiB Q·33 +=============== Jul 12, 2018 (BST) =============== +16:40:10.371686 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:40:10.371817 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] +16:40:10.371830 db@open opening +16:40:10.371907 journal@recovery F·1 +16:40:10.373766 journal@recovery recovering @30 +16:40:10.389761 memdb@flush created L0@32 N·1 S·356B "eth..\x0e/(,v34":"eth..\x0e/(,v34" +16:40:10.389933 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] +16:40:10.418773 db@janitor F·13 G·0 +16:40:10.418797 db@open done T·46.959609ms +16:40:10.418858 table@compaction L0·11 -> L1·0 S·4KiB Q·35 +=============== Jul 12, 2018 (BST) =============== +16:57:38.090757 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:57:38.090908 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] +16:57:38.090921 db@open opening +16:57:38.091001 journal@recovery F·1 +16:57:38.092562 journal@recovery recovering @33 +16:57:38.106295 memdb@flush created L0@35 N·1 S·356B "eth..\x0e/(,v36":"eth..\x0e/(,v36" +16:57:38.106774 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] +16:57:38.131109 db@janitor F·14 G·0 +16:57:38.131133 db@open done T·40.204748ms +16:57:38.131179 table@compaction L0·12 -> L1·0 S·4KiB Q·37 +=============== Jul 13, 2018 (BST) =============== +11:03:46.000460 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:03:46.000607 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] +11:03:46.000618 db@open opening +11:03:46.000698 journal@recovery F·1 +11:03:46.001141 journal@recovery recovering @36 +11:03:46.008992 memdb@flush created L0@38 N·1 S·356B "eth..\x0e/(,v38":"eth..\x0e/(,v38" +11:03:46.009166 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] +11:03:46.023882 db@janitor F·15 G·0 +11:03:46.023908 db@open done T·23.28332ms +11:03:46.024537 table@compaction L0·13 -> L1·0 S·5KiB Q·39 +=============== Jul 13, 2018 (BST) =============== +11:20:09.899511 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:20:09.899673 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] +11:20:09.899691 db@open opening +11:20:09.899783 journal@recovery F·1 +11:20:09.900184 journal@recovery recovering @39 +11:20:09.912744 memdb@flush created L0@41 N·1 S·356B "eth..\x0e/(,v40":"eth..\x0e/(,v40" +11:20:09.912997 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] +11:20:09.941221 db@janitor F·16 G·0 +11:20:09.941251 db@open done T·41.550282ms +11:20:09.941342 table@compaction L0·14 -> L1·0 S·5KiB Q·41 +=============== Jul 13, 2018 (BST) =============== +11:22:02.901675 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:22:02.901852 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] +11:22:02.901876 db@open opening +11:22:02.901980 journal@recovery F·1 +11:22:02.902709 journal@recovery recovering @42 +11:22:02.918141 memdb@flush created L0@44 N·1 S·356B "eth..\x0e/(,v42":"eth..\x0e/(,v42" +11:22:02.918398 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] +11:22:02.946853 db@janitor F·17 G·0 +11:22:02.946899 db@open done T·45.011878ms +11:22:02.947647 table@compaction L0·15 -> L1·0 S·5KiB Q·43 +=============== Jul 13, 2018 (BST) =============== +11:28:34.344769 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:28:34.344929 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] +11:28:34.344947 db@open opening +11:28:34.345034 journal@recovery F·1 +11:28:34.345498 journal@recovery recovering @45 +11:28:34.352995 memdb@flush created L0@47 N·1 S·356B "eth..\x0e/(,v44":"eth..\x0e/(,v44" +11:28:34.354854 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] +11:28:34.373782 db@janitor F·18 G·0 +11:28:34.373820 db@open done T·28.864466ms +11:28:34.373958 table@compaction L0·16 -> L1·0 S·6KiB Q·45 +=============== Jul 13, 2018 (BST) =============== +11:41:20.358038 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:20.358169 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] +11:41:20.358188 db@open opening +11:41:20.358254 journal@recovery F·1 +11:41:20.358733 journal@recovery recovering @48 +11:41:20.366548 memdb@flush created L0@50 N·1 S·356B "eth..\x0e/(,v46":"eth..\x0e/(,v46" +11:41:20.366758 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] +11:41:20.381196 db@janitor F·19 G·0 +11:41:20.381237 db@open done T·23.03988ms +11:41:20.382138 table@compaction L0·17 -> L1·0 S·6KiB Q·47 +=============== Jul 13, 2018 (BST) =============== +13:24:29.055504 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:24:29.055677 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] +13:24:29.055701 db@open opening +13:24:29.055813 journal@recovery F·1 +13:24:29.061531 journal@recovery recovering @51 +13:24:29.070331 memdb@flush created L0@53 N·1 S·356B "eth..\x0e/(,v48":"eth..\x0e/(,v48" +13:24:29.070583 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] +13:24:29.087336 db@janitor F·20 G·0 +13:24:29.087367 db@open done T·31.654841ms +13:24:29.088359 table@compaction L0·18 -> L1·0 S·6KiB Q·49 +=============== Jul 13, 2018 (BST) =============== +13:27:13.482710 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:27:13.483399 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] +13:27:13.483562 db@open opening +13:27:13.483961 journal@recovery F·1 +13:27:13.491317 journal@recovery recovering @54 +13:27:13.501450 memdb@flush created L0@56 N·1 S·356B "eth..\x0e/(,v50":"eth..\x0e/(,v50" +13:27:13.511084 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:27:13.531538 db@janitor F·21 G·0 +13:27:13.531638 db@open done T·48.031341ms +13:27:13.531939 table@compaction L0·19 -> L1·0 S·7KiB Q·51 +=============== Jul 13, 2018 (BST) =============== +13:35:11.452220 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:35:11.452980 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:35:11.453145 db@open opening +13:35:11.453637 journal@recovery F·1 +13:35:11.454941 journal@recovery recovering @57 +13:35:11.464221 memdb@flush created L0@59 N·1 S·356B "eth..\x0e/(,v52":"eth..\x0e/(,v52" +13:35:11.465727 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] +13:35:11.483720 db@janitor F·22 G·0 +13:35:11.483834 db@open done T·30.575071ms +13:35:11.484083 table@compaction L0·20 -> L1·0 S·7KiB Q·53 +=============== Jul 13, 2018 (BST) =============== +13:51:52.767069 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:51:52.767205 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] +13:51:52.767224 db@open opening +13:51:52.767319 journal@recovery F·1 +13:51:52.767953 journal@recovery recovering @60 +13:51:52.776595 memdb@flush created L0@62 N·1 S·356B "eth..\x0e/(,v54":"eth..\x0e/(,v54" +13:51:52.776772 version@stat F·[21] S·7KiB[7KiB] Sc·[5.25] +13:51:52.792457 db@janitor F·23 G·0 +13:51:52.792484 db@open done T·25.251519ms +13:51:52.793412 table@compaction L0·21 -> L1·0 S·7KiB Q·55 +=============== Jul 13, 2018 (BST) =============== +13:56:18.257512 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:56:18.257637 version@stat F·[21] S·7KiB[7KiB] Sc·[5.25] +13:56:18.257653 db@open opening +13:56:18.257722 journal@recovery F·1 +13:56:18.259357 journal@recovery recovering @63 +13:56:18.266802 memdb@flush created L0@65 N·1 S·356B "eth..\x0e/(,v56":"eth..\x0e/(,v56" +13:56:18.268594 version@stat F·[22] S·8KiB[8KiB] Sc·[5.50] +13:56:18.287066 db@janitor F·24 G·0 +13:56:18.287093 db@open done T·29.432209ms +13:56:18.287861 table@compaction L0·22 -> L1·0 S·8KiB Q·57 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/MANIFEST-000067 b/poa-network/multi-peer/node1/geth/lightchaindata/MANIFEST-000067 new file mode 100644 index 0000000000000000000000000000000000000000..4fd88fd9fe3bb9cc90b188bab7c874980cd24800 GIT binary patch literal 2746 zcmc)F%`3wJ9LMqRZ>F!vV#&iEka?JgZ7dI4D`gzG*-2@su^*;AXog&nBuYvy4$6sx za-tLmg(w%46FU%2JMDlArTG2@pNsGL`|j0e?&ivOkgX_&usWrNgM)VOOhTOwO{kr* z$ao+gNW|hAZ$_8a&D8O#ajA(>HLgxZY(uf=aA?GKetgzEZ9rKGnHmtb4rL`|szq2U%1X#ojj+`yD!{C1lD( z*gTY#kV%tdt9xsGVfAPt6k$F@%YUfK1m fVdwC{6#7oz)mW-ZQXXS(Xkj2c_?}cU{~mt;S7`=K literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node1/geth/nodekey b/poa-network/multi-peer/node1/geth/nodekey new file mode 100644 index 0000000..d8c4eb5 --- /dev/null +++ b/poa-network/multi-peer/node1/geth/nodekey @@ -0,0 +1 @@ +eca9ca1438314a1cfdb786668e7876efbc6535c278f86ab6b0417d5d93b4822b \ No newline at end of file diff --git a/poa-network/multi-peer/node1/geth/nodes/000086.ldb b/poa-network/multi-peer/node1/geth/nodes/000086.ldb new file mode 100644 index 0000000000000000000000000000000000000000..ce100a8bbd5f7a7da55a31ee3b31cd3ba7a34757 GIT binary patch literal 352635 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 z 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 L1·0 S·16KiB Q·2021 +11:27:24.017458 table@build created L1@8 N·9 S·411B "n:/..ver,v1968":"version,v1" +11:27:24.017515 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:27:24.024914 table@compaction committed F-1 S-16KiB Ke·0 D·2010 T·21.885965ms +11:27:24.025012 table@remove removed @5 +11:27:24.025058 table@remove removed @2 +=============== Jul 12, 2018 (BST) =============== +11:34:08.348817 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:34:08.349286 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:34:08.349338 db@open opening +11:34:08.349538 journal@recovery F·1 +11:34:08.360736 journal@recovery recovering @6 +11:34:08.381586 memdb@flush created L0@9 N·982 S·7KiB "n:/..ver,v2988":"n:\xdc..ong,v2031" +11:34:08.384067 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] +11:34:08.399373 db@janitor F·4 G·0 +11:34:08.399408 db@open done T·50.032306ms +=============== Jul 12, 2018 (BST) =============== +11:53:49.125828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:53:49.125995 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] +11:53:49.126008 db@open opening +11:53:49.126052 journal@recovery F·1 +11:53:49.127385 journal@recovery recovering @10 +11:53:49.145327 memdb@flush created L0@12 N·3192 S·25KiB "n:/..ver,v6186":"n:\xdc..ong,v3015" +11:53:49.148934 version@stat F·[2 1] S·33KiB[33KiB 411B] Sc·[0.50 0.00] +11:53:49.175177 db@janitor F·5 G·0 +11:53:49.175228 db@open done T·49.210646ms +11:53:49.178029 table@compaction L0·2 -> L1·1 S·33KiB Q·6197 +11:53:49.187821 table@build created L1@15 N·9 S·412B "n:/..ver,v6186":"version,v1" +11:53:49.187864 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] +11:53:49.202969 table@compaction committed F-2 S-33KiB Ke·0 D·4174 T·24.897024ms +11:53:49.203108 table@remove removed @12 +11:53:49.203636 table@remove removed @9 +11:53:49.203769 table@remove removed @8 +=============== Jul 12, 2018 (BST) =============== +14:17:44.688701 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:17:44.689805 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] +14:17:44.689868 db@open opening +14:17:44.690063 journal@recovery F·1 +14:17:44.695883 journal@recovery recovering @13 +14:17:44.757316 memdb@flush created L0@16 N·10756 S·84KiB "n:/..ver,v16902":"n:\xdc..ong,v6200" +14:17:44.759028 version@stat F·[1 1] S·85KiB[84KiB 412B] Sc·[0.25 0.00] +14:17:44.786504 db@janitor F·4 G·0 +14:17:44.786549 db@open done T·96.656953ms +=============== Jul 12, 2018 (BST) =============== +14:39:51.282920 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:39:51.283067 version@stat F·[1 1] S·85KiB[84KiB 412B] Sc·[0.25 0.00] +14:39:51.283079 db@open opening +14:39:51.283127 journal@recovery F·1 +14:39:51.284732 journal@recovery recovering @17 +14:39:51.311699 memdb@flush created L0@19 N·3576 S·28KiB "n:/..ver,v20523":"n:\xdc..ong,v16961" +14:39:51.313974 version@stat F·[2 1] S·113KiB[113KiB 412B] Sc·[0.50 0.00] +14:39:51.335982 db@janitor F·5 G·0 +14:39:51.336021 db@open done T·52.932737ms +14:39:51.338270 table@compaction L0·2 -> L1·1 S·113KiB Q·20531 +14:39:51.354265 table@build created L1@22 N·9 S·411B "n:/..ver,v20523":"version,v1" +14:39:51.354323 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +14:39:51.361842 table@compaction committed F-2 S-113KiB Ke·0 D·14332 T·23.52416ms +14:39:51.361965 table@remove removed @19 +14:39:51.362037 table@remove removed @16 +14:39:51.362077 table@remove removed @15 +=============== Jul 12, 2018 (BST) =============== +15:37:20.197501 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:37:20.197779 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +15:37:20.197799 db@open opening +15:37:20.197907 journal@recovery F·1 +15:37:20.200023 journal@recovery recovering @20 +15:37:20.229689 memdb@flush created L0@23 N·9077 S·71KiB "n:/..ver,v29551":"n:\xdc..ong,v20538" +15:37:20.231484 version@stat F·[1 1] S·72KiB[71KiB 411B] Sc·[0.25 0.00] +15:37:20.251005 db@janitor F·4 G·0 +15:37:20.251043 db@open done T·53.232225ms +=============== Jul 12, 2018 (BST) =============== +15:48:32.385325 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:48:32.385492 version@stat F·[1 1] S·72KiB[71KiB 411B] Sc·[0.25 0.00] +15:48:32.385540 db@open opening +15:48:32.385604 journal@recovery F·1 +15:48:32.387030 journal@recovery recovering @24 +15:48:32.405585 memdb@flush created L0@26 N·1846 S·14KiB "n:/..ver,v31425":"n:\xdc..ong,v29612" +15:48:32.413016 version@stat F·[2 1] S·87KiB[86KiB 411B] Sc·[0.50 0.00] +15:48:32.439667 db@janitor F·5 G·0 +15:48:32.439756 db@open done T·54.201389ms +15:48:32.443897 table@compaction L0·2 -> L1·1 S·87KiB Q·31456 +15:48:32.463628 table@build created L1@29 N·9 S·411B "n:/..ver,v31425":"version,v1" +15:48:32.463710 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +15:48:32.474610 table@compaction committed F-2 S-86KiB Ke·0 D·10923 T·30.674873ms +15:48:32.475446 table@remove removed @26 +15:48:32.475684 table@remove removed @23 +15:48:32.475888 table@remove removed @22 +=============== Jul 12, 2018 (BST) =============== +16:05:29.136315 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:05:29.136476 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +16:05:29.136490 db@open opening +16:05:29.136531 journal@recovery F·1 +16:05:29.137978 journal@recovery recovering @27 +16:05:29.150419 memdb@flush created L0@30 N·2756 S·22KiB "n:/..ver,v34160":"n:\xdc..ong,v31463" +16:05:29.154204 version@stat F·[1 1] S·22KiB[22KiB 411B] Sc·[0.25 0.00] +16:05:29.169283 db@janitor F·4 G·0 +16:05:29.169318 db@open done T·32.818144ms +=============== Jul 12, 2018 (BST) =============== +16:23:49.780860 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:23:49.781083 version@stat F·[1 1] S·22KiB[22KiB 411B] Sc·[0.25 0.00] +16:23:49.781094 db@open opening +16:23:49.781139 journal@recovery F·1 +16:23:49.783143 journal@recovery recovering @31 +16:23:49.798476 memdb@flush created L0@33 N·2969 S·23KiB "n:/..ver,v37138":"n:\xdc..ong,v34222" +16:23:49.800475 version@stat F·[2 1] S·46KiB[45KiB 411B] Sc·[0.50 0.00] +16:23:49.816411 db@janitor F·5 G·0 +16:23:49.816455 db@open done T·35.352587ms +16:23:49.819583 table@compaction L0·2 -> L1·1 S·46KiB Q·37183 +16:23:49.830423 table@build created L1@36 N·9 S·414B "n:/..ver,v37138":"version,v1" +16:23:49.830470 version@stat F·[0 1] S·414B[0B 414B] Sc·[0.00 0.00] +16:23:49.837858 table@compaction committed F-2 S-45KiB Ke·0 D·5725 T·18.203746ms +16:23:49.837969 table@remove removed @33 +16:23:49.838055 table@remove removed @30 +16:23:49.838127 table@remove removed @29 +=============== Jul 12, 2018 (BST) =============== +16:40:12.766097 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:40:12.766286 version@stat F·[0 1] S·414B[0B 414B] Sc·[0.00 0.00] +16:40:12.766303 db@open opening +16:40:12.766353 journal@recovery F·1 +16:40:12.767975 journal@recovery recovering @34 +16:40:12.788242 memdb@flush created L0@37 N·2691 S·21KiB "n:/..ver,v39825":"n:\xdc..ong,v37186" +16:40:12.790316 version@stat F·[1 1] S·21KiB[21KiB 414B] Sc·[0.25 0.00] +16:40:12.807288 db@janitor F·4 G·0 +16:40:12.807344 db@open done T·41.030612ms +=============== Jul 12, 2018 (BST) =============== +16:57:40.476499 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:57:40.476704 version@stat F·[1 1] S·21KiB[21KiB 414B] Sc·[0.25 0.00] +16:57:40.476721 db@open opening +16:57:40.476773 journal@recovery F·1 +16:57:40.478538 journal@recovery recovering @38 +16:57:40.498173 memdb@flush created L0@40 N·2859 S·22KiB "n:/..ver,v42662":"n:\xdc..ong,v39883" +16:57:40.500177 version@stat F·[2 1] S·44KiB[44KiB 414B] Sc·[0.50 0.00] +16:57:40.516286 db@janitor F·5 G·0 +16:57:40.516360 db@open done T·39.628863ms +16:57:40.519300 table@compaction L0·2 -> L1·1 S·44KiB Q·42735 +16:57:40.541025 table@build created L1@43 N·9 S·410B "n:/..ver,v42662":"version,v1" +16:57:40.541082 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +16:57:40.548370 table@compaction committed F-2 S-44KiB Ke·0 D·5550 T·29.0303ms +16:57:40.548461 table@remove removed @40 +16:57:40.548509 table@remove removed @37 +16:57:40.548546 table@remove removed @36 +21:32:14.584473 memdb@flush N·43076 S·3MiB +21:32:14.692832 memdb@flush created L0@45 N·43076 S·339KiB "n:/..ver,v85802":"n:\xdc..ong,v42742" +21:32:14.692986 version@stat F·[1 1] S·339KiB[339KiB 410B] Sc·[0.25 0.00] +21:32:14.700477 memdb@flush committed F·1 T·115.839092ms +21:32:14.703567 journal@remove removed @41 +=============== Jul 13, 2018 (BST) =============== +02:05:39.815476 memdb@flush N·43069 S·3MiB +02:05:39.872158 memdb@flush created L0@47 N·43069 S·339KiB "n:/..ver,v128805":"n:\xdc..ong,v85814" +02:05:39.872235 version@stat F·[2 1] S·678KiB[678KiB 410B] Sc·[0.50 0.00] +02:05:39.879305 memdb@flush committed F·1 T·63.555708ms +02:05:39.880183 journal@remove removed @44 +06:37:33.787625 memdb@flush N·43071 S·3MiB +06:37:33.893979 memdb@flush created L0@49 N·43071 S·339KiB "n:/..ver,v171892":"n:\xdc..ong,v128889" +06:37:33.894267 version@stat F·[3 1] S·1018KiB[1017KiB 410B] Sc·[0.75 0.00] +06:37:33.902288 memdb@flush committed F·1 T·114.464773ms +06:37:33.906695 journal@remove removed @46 +=============== Jul 13, 2018 (BST) =============== +11:03:48.235622 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:03:48.235894 version@stat F·[3 1] S·1018KiB[1017KiB 410B] Sc·[0.75 0.00] +11:03:48.235928 db@open opening +11:03:48.236034 journal@recovery F·1 +11:03:48.240081 journal@recovery recovering @48 +11:03:48.351031 memdb@flush created L0@50 N·40869 S·322KiB "n:/..ver,v212809":"n:\xdc..ong,v171953" +11:03:48.355511 version@stat F·[4 1] S·1MiB[1MiB 410B] Sc·[1.00 0.00] +11:03:48.386506 db@janitor F·7 G·0 +11:03:48.386588 db@open done T·150.644258ms +11:03:48.386779 table@compaction L0·4 -> L1·1 S·1MiB Q·212821 +11:03:48.552028 table@build created L1@53 N·9 S·410B "n:/..ver,v212809":"version,v1" +11:03:48.552698 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +11:03:48.563808 table@compaction committed F-4 S-1MiB Ke·0 D·170085 T·176.390695ms +11:03:48.563964 table@remove removed @50 +11:03:48.564085 table@remove removed @49 +11:03:48.564184 table@remove removed @47 +11:03:48.564276 table@remove removed @45 +11:03:48.564312 table@remove removed @43 +=============== Jul 13, 2018 (BST) =============== +11:20:12.172435 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:20:12.172632 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +11:20:12.172647 db@open opening +11:20:12.172701 journal@recovery F·1 +11:20:12.174313 journal@recovery recovering @51 +11:20:12.246336 memdb@flush created L0@54 N·2676 S·21KiB "n:/..ver,v215430":"n:\xdc..ong,v212828" +11:20:12.248717 version@stat F·[1 1] S·21KiB[21KiB 410B] Sc·[0.25 0.00] +11:20:12.275257 db@janitor F·4 G·0 +11:20:12.275381 db@open done T·102.722613ms +=============== Jul 13, 2018 (BST) =============== +11:22:05.338759 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:22:05.338930 version@stat F·[1 1] S·21KiB[21KiB 410B] Sc·[0.25 0.00] +11:22:05.338942 db@open opening +11:22:05.338994 journal@recovery F·1 +11:22:05.340616 journal@recovery recovering @55 +11:22:05.396300 memdb@flush created L0@57 N·326 S·2KiB "n:/..ver,v215775":"n:\xdc..ong,v215506" +11:22:05.398077 version@stat F·[2 1] S·24KiB[24KiB 410B] Sc·[0.50 0.00] +11:22:05.414879 db@janitor F·5 G·0 +11:22:05.414913 db@open done T·75.962832ms +11:22:05.420289 table@compaction L0·2 -> L1·1 S·24KiB Q·215825 +11:22:05.434036 table@build created L1@60 N·9 S·401B "n:/..ver,v215775":"version,v1" +11:22:05.434096 version@stat F·[0 1] S·401B[0B 401B] Sc·[0.00 0.00] +11:22:05.462717 table@compaction committed F-2 S-24KiB Ke·0 D·3002 T·42.360212ms +11:22:05.462903 table@remove removed @57 +11:22:05.462991 table@remove removed @54 +11:22:05.463079 table@remove removed @53 +=============== Jul 13, 2018 (BST) =============== +11:28:36.626934 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:28:36.627111 version@stat F·[0 1] S·401B[0B 401B] Sc·[0.00 0.00] +11:28:36.627126 db@open opening +11:28:36.627182 journal@recovery F·1 +11:28:36.628843 journal@recovery recovering @58 +11:28:36.669496 memdb@flush created L0@61 N·992 S·8KiB "n:/..ver,v216740":"n:\xdc..ong,v215836" +11:28:36.671600 version@stat F·[1 1] S·8KiB[8KiB 401B] Sc·[0.25 0.00] +11:28:36.695725 db@janitor F·4 G·0 +11:28:36.695752 db@open done T·68.61716ms +=============== Jul 13, 2018 (BST) =============== +11:41:22.637074 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:22.637293 version@stat F·[1 1] S·8KiB[8KiB 401B] Sc·[0.25 0.00] +11:41:22.637310 db@open opening +11:41:22.637367 journal@recovery F·1 +11:41:22.638986 journal@recovery recovering @62 +11:41:22.703922 memdb@flush created L0@64 N·2080 S·16KiB "n:/..ver,v218865":"n:\xdc..ong,v216821" +11:41:22.705642 version@stat F·[2 1] S·25KiB[24KiB 401B] Sc·[0.50 0.00] +11:41:22.721609 db@janitor F·5 G·0 +11:41:22.724802 db@open done T·87.477513ms +11:41:22.728946 table@compaction L0·2 -> L1·1 S·25KiB Q·218899 +11:41:22.740990 table@build created L1@67 N·9 S·408B "n:/..ver,v218865":"version,v1" +11:41:22.741188 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] +11:41:22.759699 table@compaction committed F-2 S-24KiB Ke·0 D·3072 T·30.552034ms +11:41:22.760600 table@remove removed @64 +11:41:22.761139 table@remove removed @61 +11:41:22.761635 table@remove removed @60 +=============== Jul 13, 2018 (BST) =============== +13:24:31.284459 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:24:31.284658 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] +13:24:31.284683 db@open opening +13:24:31.284735 journal@recovery F·1 +13:24:31.286418 journal@recovery recovering @65 +13:24:31.369979 memdb@flush created L0@68 N·16357 S·129KiB "n:/..ver,v235239":"n:\xdc..ong,v218917" +13:24:31.372433 version@stat F·[1 1] S·129KiB[129KiB 408B] Sc·[0.25 0.00] +13:24:31.394761 db@janitor F·4 G·0 +13:24:31.394830 db@open done T·110.133266ms +=============== Jul 13, 2018 (BST) =============== +13:27:15.742235 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:27:15.743321 version@stat F·[1 1] S·129KiB[129KiB 408B] Sc·[0.25 0.00] +13:27:15.743503 db@open opening +13:27:15.743822 journal@recovery F·1 +13:27:15.751341 journal@recovery recovering @69 +13:27:15.810920 memdb@flush created L0@71 N·394 S·3KiB "n:/..ver,v235588":"n:\xdc..ong,v235275" +13:27:15.820870 version@stat F·[2 1] S·132KiB[132KiB 408B] Sc·[0.50 0.00] +13:27:15.839116 db@janitor F·5 G·0 +13:27:15.839339 db@open done T·95.783547ms +13:27:15.849542 table@compaction L0·2 -> L1·1 S·132KiB Q·235652 +13:27:15.883921 table@build created L1@74 N·9 S·413B "n:/..ver,v235588":"version,v1" +13:27:15.884019 version@stat F·[0 1] S·413B[0B 413B] Sc·[0.00 0.00] +13:27:15.891314 table@compaction committed F-2 S-132KiB Ke·0 D·16751 T·41.628392ms +13:27:15.891618 table@remove removed @71 +13:27:15.891721 table@remove removed @68 +13:27:15.891789 table@remove removed @67 +=============== Jul 13, 2018 (BST) =============== +13:35:13.735863 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:35:13.736583 version@stat F·[0 1] S·413B[0B 413B] Sc·[0.00 0.00] +13:35:13.736659 db@open opening +13:35:13.736879 journal@recovery F·1 +13:35:13.741447 journal@recovery recovering @72 +13:35:13.797063 memdb@flush created L0@75 N·153 S·1KiB "n:/..ail,v235686":"n:\xdc..ong,v235655" +13:35:13.804399 version@stat F·[1 1] S·1KiB[1KiB 413B] Sc·[0.25 0.00] +13:35:13.828011 db@janitor F·4 G·0 +13:35:13.828164 db@open done T·91.465186ms +13:35:15.051483 table@compaction L0·1 -> L1·1 S·1KiB Q·235831 +13:35:15.061764 table@build created L1@78 N·9 S·420B "n:/..ver,v235588":"version,v1" +13:35:15.062042 version@stat F·[0 1] S·420B[0B 420B] Sc·[0.00 0.00] +13:35:15.076736 table@compaction committed F-1 S-1KiB Ke·0 D·153 T·25.084612ms +13:35:15.077060 table@remove removed @75 +13:35:15.077330 table@remove removed @74 +=============== Jul 13, 2018 (BST) =============== +13:51:55.002019 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:51:55.002206 version@stat F·[0 1] S·420B[0B 420B] Sc·[0.00 0.00] +13:51:55.002219 db@open opening +13:51:55.002266 journal@recovery F·1 +13:51:55.004461 journal@recovery recovering @76 +13:51:55.029814 memdb@flush created L0@79 N·3645 S·137KiB "n:\x00..ail,v237491":"n:\xff..ing,v237554" +13:51:55.031961 version@stat F·[1 1] S·137KiB[137KiB 420B] Sc·[0.25 0.00] +13:51:55.048183 db@janitor F·4 G·0 +13:51:55.048215 db@open done T·45.987338ms +13:51:55.890342 table@compaction L0·1 -> L1·1 S·137KiB Q·239485 +13:51:55.906745 table@build created L1@82 N·2789 S·128KiB "n:\x00..ail,v237491":"version,v1" +13:51:55.906887 version@stat F·[0 1] S·128KiB[0B 128KiB] Sc·[0.00 0.00] +13:51:55.925112 table@compaction committed F-1 S-9KiB Ke·0 D·865 T·34.729153ms +13:51:55.925522 table@remove removed @79 +13:51:55.925786 table@remove removed @78 +=============== Jul 13, 2018 (BST) =============== +13:56:20.471399 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:56:20.471552 version@stat F·[0 1] S·128KiB[0B 128KiB] Sc·[0.00 0.00] +13:56:20.471567 db@open opening +13:56:20.471609 journal@recovery F·1 +13:56:20.472908 journal@recovery recovering @80 +13:56:20.542136 memdb@flush created L0@83 N·6533 S·242KiB "n:\x00..ing,v245815":"n:\xff..ing,v244816" +13:56:20.543934 version@stat F·[1 1] S·370KiB[242KiB 128KiB] Sc·[0.25 0.00] +13:56:20.559735 db@janitor F·4 G·0 +13:56:20.559777 db@open done T·88.197042ms +13:56:20.693865 table@compaction L0·1 -> L1·1 S·370KiB Q·245999 +13:56:20.712228 table@build created L1@86 N·7473 S·344KiB "n:\x00..ing,v245815":"version,v1" +13:56:20.712304 version@stat F·[0 1] S·344KiB[0B 344KiB] Sc·[0.00 0.00] +13:56:20.719453 table@compaction committed F-1 S-25KiB Ke·0 D·1849 T·25.531715ms +13:56:20.724192 table@remove removed @83 +13:56:20.724394 table@remove removed @82 +13:56:20.727645 db@close closing +13:56:20.727690 db@close done T·44.056µs diff --git a/poa-network/multi-peer/node1/geth/nodes/MANIFEST-000085 b/poa-network/multi-peer/node1/geth/nodes/MANIFEST-000085 new file mode 100644 index 0000000000000000000000000000000000000000..ad17958f5f75b41405238ad037bafb2a3008b009 GIT binary patch literal 862 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 JMrI}!1^~s!4paaD literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000002.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000002.ldb new file mode 100644 index 0000000000000000000000000000000000000000..c5bc9bfa773d6ad0b7dece0e64f30b64e9513800 GIT binary patch literal 987 zcmeC={}9Tc(amT%XJS*&_TtxhZAWHA9eb=RZMnAPkGAK-z|Q?28)UN{FtRX!!H>=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsGqfv7>Ai1H+Dg zK5X-R*jO}z>sB+fFtYM)V+mYP_mF|1fsv76L0vFAqpC>*7=W?>Fisg5oxKCJ(%|NPo4l9NM0C-xfx7mS-9y}FeoyoW#*Km7U|`rmZj#TB&7arv71c>qzP=O@YRJI#6=i5neQYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=&~ggKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0QHestpET3 literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000008.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000008.ldb new file mode 100644 index 0000000000000000000000000000000000000000..d2b26a1513df62490165abb9178df47524827180 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(5igKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7araSq}muu(H6 uxR{8GFmN)bG5+Ud)L=LX5{1|jQh)Z?Q%3!nOkyA*{2=^yL$^w)`)vRx>RJN; literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000011.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000011.ldb new file mode 100644 index 0000000000000000000000000000000000000000..df591285ec4a5126c6edcfcaadbe0d6cdbf90ba3 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(2hgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(8jgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c40gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0Gb3^x&QzG literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000020.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000020.ldb new file mode 100644 index 0000000000000000000000000000000000000000..0f885d9e99a6ddfd068f3d58435204b29fb142a7 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cA2gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c71gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cD3gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qiLgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm8l$aRU zK%$&L%*|leYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qoNgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qlMgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmH7Hgo`4N=yuF zAW=>r=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r05HB;{Qv*} literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000038.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000038.ldb new file mode 100644 index 0000000000000000000000000000000000000000..a05ec3826f2c34a6199189d16cc0a8392e95cf55 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qrOgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*08mI;GXMYp literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000041.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000041.ldb new file mode 100644 index 0000000000000000000000000000000000000000..c8f05dd77cbe3eac74780b6ebaab315d0e462feb GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANm$gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm?x!EOeQgq5PlH;yP;d9)crO9n~Yko literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000044.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000044.ldb new file mode 100644 index 0000000000000000000000000000000000000000..627147b4d7b2f480a6a51150b612a39211a8ccf9 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANs&gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANp%gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANv(gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0AdtcNB{r; literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000053.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000053.ldb new file mode 100644 index 0000000000000000000000000000000000000000..32548614e07c2dcfdabd893cf97d080abd9721d4 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HL=gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0A*QPO8@`> literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000056.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000056.ldb new file mode 100644 index 0000000000000000000000000000000000000000..3c07eed7394d4b6511ac7fd9c724fdf5e2425875 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HR?gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HO>gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HU@gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*09Bb=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yasH{-NVsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsGqfv7>Ai1H+Dg zK5X-R*jO}z>sB+fFtYM)V+mYP_mF|1fsv76L0vFAqpC>*7=W?>Fisg5e|={<9Nkcn z5m^|-d90&5>A|$8fAR#_K=Q&s%*|jj%fd~+f3fmGuM N;lCTYRZ87&0|27!N`(Lb literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/CURRENT b/poa-network/multi-peer/node2/geth/lightchaindata/CURRENT new file mode 100644 index 0000000..5d746f2 --- /dev/null +++ b/poa-network/multi-peer/node2/geth/lightchaindata/CURRENT @@ -0,0 +1 @@ +MANIFEST-000064 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/LOCK b/poa-network/multi-peer/node2/geth/lightchaindata/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/LOG b/poa-network/multi-peer/node2/geth/lightchaindata/LOG new file mode 100644 index 0000000..00afeb7 --- /dev/null +++ b/poa-network/multi-peer/node2/geth/lightchaindata/LOG @@ -0,0 +1,233 @@ +=============== Jul 12, 2018 (BST) =============== +11:09:03.617505 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:09:03.638619 db@open opening +11:09:03.639109 version@stat F·[] S·0B[] Sc·[] +11:09:03.659830 db@janitor F·2 G·0 +11:09:03.659867 db@open done T·21.106833ms +=============== Jul 12, 2018 (BST) =============== +11:24:28.339167 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:24:28.339267 version@stat F·[] S·0B[] Sc·[] +11:24:28.339277 db@open opening +11:24:28.339319 journal@recovery F·1 +11:24:28.339676 journal@recovery recovering @1 +11:24:28.347346 memdb@flush created L0@2 N·14 S·987B "9\x9c\x91..\x1dj\xe0,v4":"\xdb7C..b\xf5\xdc,v5" +11:24:28.347554 version@stat F·[1] S·987B[987B] Sc·[0.25] +11:24:28.366952 db@janitor F·3 G·0 +11:24:28.366980 db@open done T·27.695431ms +=============== Jul 12, 2018 (BST) =============== +11:27:21.708765 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:27:21.708882 version@stat F·[1] S·987B[987B] Sc·[0.25] +11:27:21.708892 db@open opening +11:27:21.708937 journal@recovery F·1 +11:27:21.709348 journal@recovery recovering @3 +11:27:21.717125 memdb@flush created L0@5 N·1 S·356B "eth..\x0e/(,v16":"eth..\x0e/(,v16" +11:27:21.717337 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] +11:27:21.747896 db@janitor F·4 G·0 +11:27:21.747933 db@open done T·39.033522ms +=============== Jul 12, 2018 (BST) =============== +11:34:06.126463 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:34:06.126604 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] +11:34:06.126618 db@open opening +11:34:06.126667 journal@recovery F·1 +11:34:06.127050 journal@recovery recovering @6 +11:34:06.134863 memdb@flush created L0@8 N·1 S·356B "eth..\x0e/(,v18":"eth..\x0e/(,v18" +11:34:06.135048 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] +11:34:06.150716 db@janitor F·5 G·0 +11:34:06.150741 db@open done T·24.114611ms +=============== Jul 12, 2018 (BST) =============== +11:53:46.820694 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:53:46.820798 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] +11:53:46.820810 db@open opening +11:53:46.820864 journal@recovery F·1 +11:53:46.821297 journal@recovery recovering @9 +11:53:46.831626 memdb@flush created L0@11 N·1 S·356B "eth..\x0e/(,v20":"eth..\x0e/(,v20" +11:53:46.831818 version@stat F·[4] S·2KiB[2KiB] Sc·[1.00] +11:53:46.846405 db@janitor F·6 G·0 +11:53:46.846432 db@open done T·25.614964ms +11:53:46.847063 table@compaction L0·4 -> L1·0 S·2KiB Q·22 +=============== Jul 12, 2018 (BST) =============== +14:17:42.392536 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:17:42.395630 version@stat F·[4] S·2KiB[2KiB] Sc·[1.00] +14:17:42.395645 db@open opening +14:17:42.395694 journal@recovery F·1 +14:17:42.395969 journal@recovery recovering @12 +14:17:42.413553 memdb@flush created L0@14 N·1 S·356B "eth..\x0e/(,v22":"eth..\x0e/(,v22" +14:17:42.414591 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] +14:17:42.442813 db@janitor F·7 G·0 +14:17:42.442842 db@open done T·47.187651ms +14:17:42.442909 table@compaction L0·5 -> L1·0 S·2KiB Q·23 +=============== Jul 12, 2018 (BST) =============== +14:39:49.043706 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:39:49.043821 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] +14:39:49.043835 db@open opening +14:39:49.043899 journal@recovery F·1 +14:39:49.044289 journal@recovery recovering @15 +14:39:49.051780 memdb@flush created L0@17 N·1 S·356B "eth..\x0e/(,v24":"eth..\x0e/(,v24" +14:39:49.052391 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] +14:39:49.081746 db@janitor F·8 G·0 +14:39:49.081769 db@open done T·37.92478ms +=============== Jul 12, 2018 (BST) =============== +15:37:17.901222 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:37:17.901345 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] +15:37:17.901358 db@open opening +15:37:17.901421 journal@recovery F·1 +15:37:17.901850 journal@recovery recovering @18 +15:37:17.910929 memdb@flush created L0@20 N·1 S·356B "eth..\x0e/(,v26":"eth..\x0e/(,v26" +15:37:17.911100 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] +15:37:17.925999 db@janitor F·9 G·0 +15:37:17.926024 db@open done T·24.65714ms +15:37:17.927077 table@compaction L0·7 -> L1·0 S·3KiB Q·27 +=============== Jul 12, 2018 (BST) =============== +15:48:30.025065 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:48:30.025198 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] +15:48:30.025211 db@open opening +15:48:30.025278 journal@recovery F·1 +15:48:30.025786 journal@recovery recovering @21 +15:48:30.038226 memdb@flush created L0@23 N·1 S·356B "eth..\x0e/(,v28":"eth..\x0e/(,v28" +15:48:30.038417 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] +15:48:30.066147 db@janitor F·10 G·0 +15:48:30.066173 db@open done T·40.953875ms +15:48:30.066226 table@compaction L0·8 -> L1·0 S·3KiB Q·29 +=============== Jul 12, 2018 (BST) =============== +16:05:26.776151 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:05:26.776271 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] +16:05:26.776283 db@open opening +16:05:26.776346 journal@recovery F·1 +16:05:26.776757 journal@recovery recovering @24 +16:05:26.787652 memdb@flush created L0@26 N·1 S·356B "eth..\x0e/(,v30":"eth..\x0e/(,v30" +16:05:26.789490 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] +16:05:26.816798 db@janitor F·11 G·0 +16:05:26.816853 db@open done T·40.562165ms +16:05:26.817677 table@compaction L0·9 -> L1·0 S·3KiB Q·31 +=============== Jul 12, 2018 (BST) =============== +16:23:47.409548 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:23:47.409692 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] +16:23:47.409705 db@open opening +16:23:47.409772 journal@recovery F·1 +16:23:47.410167 journal@recovery recovering @27 +16:23:47.423566 memdb@flush created L0@29 N·1 S·356B "eth..\x0e/(,v32":"eth..\x0e/(,v32" +16:23:47.423748 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] +16:23:47.446201 db@janitor F·12 G·0 +16:23:47.446221 db@open done T·36.509905ms +16:23:47.446274 table@compaction L0·10 -> L1·0 S·4KiB Q·33 +=============== Jul 12, 2018 (BST) =============== +16:40:10.390435 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:40:10.390563 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] +16:40:10.390577 db@open opening +16:40:10.390649 journal@recovery F·1 +16:40:10.391101 journal@recovery recovering @30 +16:40:10.411407 memdb@flush created L0@32 N·1 S·356B "eth..\x0e/(,v34":"eth..\x0e/(,v34" +16:40:10.411625 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] +16:40:10.440987 db@janitor F·13 G·0 +16:40:10.441011 db@open done T·50.42733ms +16:40:10.441063 table@compaction L0·11 -> L1·0 S·4KiB Q·35 +=============== Jul 12, 2018 (BST) =============== +16:57:38.124701 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:57:38.124826 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] +16:57:38.124838 db@open opening +16:57:38.124894 journal@recovery F·1 +16:57:38.125141 journal@recovery recovering @33 +16:57:38.138032 memdb@flush created L0@35 N·1 S·356B "eth..\x0e/(,v36":"eth..\x0e/(,v36" +16:57:38.138332 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] +16:57:38.159988 db@janitor F·14 G·0 +16:57:38.160014 db@open done T·35.167225ms +16:57:38.160670 table@compaction L0·12 -> L1·0 S·4KiB Q·37 +=============== Jul 13, 2018 (BST) =============== +11:03:46.000460 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:03:46.000607 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] +11:03:46.000618 db@open opening +11:03:46.000698 journal@recovery F·1 +11:03:46.001141 journal@recovery recovering @36 +11:03:46.008992 memdb@flush created L0@38 N·1 S·356B "eth..\x0e/(,v38":"eth..\x0e/(,v38" +11:03:46.009163 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] +11:03:46.023882 db@janitor F·15 G·0 +11:03:46.023908 db@open done T·23.283363ms +11:03:46.023980 table@compaction L0·13 -> L1·0 S·5KiB Q·39 +=============== Jul 13, 2018 (BST) =============== +11:20:09.942969 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:20:09.943598 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] +11:20:09.943626 db@open opening +11:20:09.943722 journal@recovery F·1 +11:20:09.947317 journal@recovery recovering @39 +11:20:09.958460 memdb@flush created L0@41 N·1 S·356B "eth..\x0e/(,v40":"eth..\x0e/(,v40" +11:20:09.959885 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] +11:20:09.975584 db@janitor F·16 G·0 +11:20:09.975619 db@open done T·31.977474ms +11:20:09.976379 table@compaction L0·14 -> L1·0 S·5KiB Q·41 +=============== Jul 13, 2018 (BST) =============== +11:22:02.953772 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:22:02.954444 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] +11:22:02.954479 db@open opening +11:22:02.954598 journal@recovery F·1 +11:22:02.966261 journal@recovery recovering @42 +11:22:02.978212 memdb@flush created L0@44 N·1 S·356B "eth..\x0e/(,v42":"eth..\x0e/(,v42" +11:22:02.978765 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] +11:22:02.999921 db@janitor F·17 G·0 +11:22:02.999956 db@open done T·45.466851ms +11:22:03.000743 table@compaction L0·15 -> L1·0 S·5KiB Q·43 +=============== Jul 13, 2018 (BST) =============== +11:28:34.365499 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:28:34.365667 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] +11:28:34.365687 db@open opening +11:28:34.365776 journal@recovery F·1 +11:28:34.367127 journal@recovery recovering @45 +11:28:34.380594 memdb@flush created L0@47 N·1 S·356B "eth..\x0e/(,v44":"eth..\x0e/(,v44" +11:28:34.380999 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] +11:28:34.403500 db@janitor F·18 G·0 +11:28:34.403536 db@open done T·37.840488ms +11:28:34.403948 table@compaction L0·16 -> L1·0 S·6KiB Q·45 +=============== Jul 13, 2018 (BST) =============== +11:41:30.386027 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:30.386185 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] +11:41:30.386203 db@open opening +11:41:30.386272 journal@recovery F·1 +11:41:30.386659 journal@recovery recovering @48 +11:41:30.394072 memdb@flush created L0@50 N·1 S·356B "eth..\x0e/(,v46":"eth..\x0e/(,v46" +11:41:30.394334 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] +11:41:30.410389 db@janitor F·19 G·0 +11:41:30.410973 db@open done T·24.760035ms +11:41:30.411851 table@compaction L0·17 -> L1·0 S·6KiB Q·47 +=============== Jul 13, 2018 (BST) =============== +13:24:39.113379 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:24:39.113565 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] +13:24:39.113598 db@open opening +13:24:39.113722 journal@recovery F·1 +13:24:39.114072 journal@recovery recovering @51 +13:24:39.121664 memdb@flush created L0@53 N·1 S·356B "eth..\x0e/(,v48":"eth..\x0e/(,v48" +13:24:39.121894 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] +13:24:39.136887 db@janitor F·20 G·0 +13:24:39.136917 db@open done T·23.308508ms +13:24:39.137816 table@compaction L0·18 -> L1·0 S·6KiB Q·49 +=============== Jul 13, 2018 (BST) =============== +13:52:02.783904 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:52:02.784074 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] +13:52:02.784090 db@open opening +13:52:02.784191 journal@recovery F·1 +13:52:02.784731 journal@recovery recovering @54 +13:52:02.792399 memdb@flush created L0@56 N·1 S·356B "eth..\x0e/(,v50":"eth..\x0e/(,v50" +13:52:02.792962 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:52:02.812311 db@janitor F·21 G·0 +13:52:02.812344 db@open done T·28.246007ms +13:52:02.813292 table@compaction L0·19 -> L1·0 S·7KiB Q·51 +=============== Jul 13, 2018 (BST) =============== +13:54:48.028647 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:54:48.028894 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:54:48.028938 db@open opening +13:54:48.029064 journal@recovery F·1 +13:54:48.033855 journal@recovery recovering @57 +13:54:48.047941 memdb@flush created L0@59 N·1 S·356B "eth..\x0e/(,v52":"eth..\x0e/(,v52" +13:54:48.048867 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] +13:54:48.066743 db@janitor F·22 G·0 +13:54:48.066802 db@open done T·37.834349ms +13:54:48.066923 table@compaction L0·20 -> L1·0 S·7KiB Q·53 +=============== Jul 13, 2018 (BST) =============== +13:56:28.259191 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:56:28.259335 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] +13:56:28.259356 db@open opening +13:56:28.259431 journal@recovery F·1 +13:56:28.259674 journal@recovery recovering @60 +13:56:28.267252 memdb@flush created L0@62 N·1 S·356B "eth..\x0e/(,v54":"eth..\x0e/(,v54" +13:56:28.267455 version@stat F·[21] S·7KiB[7KiB] Sc·[5.25] +13:56:28.283089 db@janitor F·23 G·0 +13:56:28.283173 db@open done T·23.806964ms +13:56:28.283266 table@compaction L0·21 -> L1·0 S·7KiB Q·55 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/MANIFEST-000064 b/poa-network/multi-peer/node2/geth/lightchaindata/MANIFEST-000064 new file mode 100644 index 0000000000000000000000000000000000000000..9369821faad1fcdeac1e6ac332f6f63fe209349b GIT binary patch literal 2627 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åDKpB@N6q_Y4h+hPcQRBbDD%QXW^9FTkcO~ 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ⅈ8MB6`D=DiJ1!rTvT8@!bBU8bRqY`@=|WZy*}z+{lGK_zS|r^H z+s10Zx_s;{?Ccuo4zO ztxtveMlZeXQTFde$053%jdrJsxr<&B5^Wx@#`e81M?F+iBL6T+9MDblrSJWFRw~^< zaV#TX4?B>a*sv=>5P`%eKp%Wg0I9|SZ7Tpa$nrrJZ%#xSQOFn#k0kssM!kP2ZC1oG z{X_XA|2Gp-VI6}7YQ@uFvzY#;j3Gztjo!N{nZv$uwe7dqH z1sq8pe7aKi2lmWt=TnBejDON`QoBO!Mp2Nk4)$a=XS?MjH7N~kZ`X6ptB`W?EIh@m?yqnvnzAXlusyeY2%tV6!ohN( z@WRQHtLEm~G82`vyL*AQ1+hU3UG8ns!}3yxl0R>?hQGjS7)71lyb>t^Cfx_&0K(}oA65YM2$F{ETsJG;!b^2=H|+}7=!fRi zXbpO~)5Se?^3zfu>~&g#>iX&uDlP zKl}9J_Ey1lyMQ8@gdtBOUHAua0o=?hj4-XxSb0Hg-`3;cU`g8Yjk~{|@VIi73O!## z$Tn8kv}4rs^sd1rCycx(;BT>1<9g^+P5GT!;$2c7TiuutzYuaeyjLir02tM1ncyxh z*q~|6hzVg-*3Bsr(nB8488~33zBOg)?e>($%dvUpLx- zFWw`&k4?XU%6IlaecDf*FPeIIEp~`vlSpNLxbY#bYYr*yvXEQ{1R|Yo2j3pSV#w*$ zm79>%Var9HiTh=6Ioh`Xl+fkQ!tUrJW`=J6jd=26Gj>|p@2t{2j{<#>Ke!!V*8P%C z-y20EGXwBWDZoTxl>wMYwr*&g2wNVqRv(2or9G6U&6%_kvBgY&vRuobF;}f$7wi*c zxT8|hL2TDBn^J`+h_XAs8r?LlNv!thWA=mUd!rbz;)AJX3(^BvuLG!g!j$TYX;Y(Y zAuQlcDS${u$kKzOD}&K8mwKN)jFab!iy2$&amq8sclb-t#Pm~jMovO;N&flOKZ;-d2WNjJbU%NoWY zMoIf}LP}nPN}H<*QvLNdx}MMwX%1H7g!Bqemq{tw#EL4SbJ?gyXVcxBFHc8SVJRvo z?IcCO3hqwegrlLCL9viu@K|o3R;NVV2tC#s|mC3oOY*)!$oGGp%13 zeCTnYGMtm!qJUH(k0MIWu`bW4qu>Rd?53hYj33)1UXe~|_>bx+CYspRCi1)Y$>dH+0b;y!UcO?<-tx2KT!MCq(@Q! zRAfB#2r%*}P*~IcXZ`$_GRybsaPQY0E+JIAtgIYk9lu++i#Rhm8NA&Tzgx-A zZW6D%eTF#iAIG%dTm5$KPN2e_`B1wm*kyCew*W+Fu-3^jyt_LCR$qf&g4pKwjf>cf zGw0aXeO7=X9hYxBAD`PhiCt87i`yS=ng&;2LC7%bQ0Z~0I22cE- ztq4{%?ssS43BhW&Fm>MiIOI_B0}OB&y8})L+qYdX&QU6D?%XXUeAsyJtxK-v8s;o&!5m-gy!YO1`e9;3ITL+He1sP-FU&OdE6=+v zT9z6ug@pY%WxyST$iwa*V5>m<4dQ8Y2&?3tf1XvOpskhr?FqU8DgLgadxJC=){rxePV+?8edRch9mmvmwGZx@*aClNN4%$np$ zfJ+Vfe})Q%FdULR7&8lmjX4uQ>aQ&^lz#NWs=UMRd?TFWn}k)uyog5>wcC)ZZ~8st zpsa--{wlFQ?GOA+aI6@QO7$hf23li`0{GS6$g*KJ1pOSwynZtlQH&R`?HhsZXMjjM z5Mp+7I&uPU3jzgBXPW}&k4f(6d@4@Zty7$sX^hf3KUzuOe9uYJ8l%%f4)OcV#X`^% zaoEm-8ZKzF980{COZ`yzdXfzyrf7!=Z;>8>-0d&UNmc2~%#e7fb*9#j2f5IMKfCW= zm?C*x`p>xG-KVDUh^)5~Tic@bpXjSa*%_qAK4R~myyAAGR~xiDe99zc2fHF3Sdcto z4J^n9Q$Kh_ZLC5NPc`@M@ScCkm0|PXdD)Prvu!edwC8uDsY{$+Y8qR*5_@ekLo12y zA5q-j5=^pF1}gv3u&8E|pFa);_())+10f9S9k6?HOe~ARv4ILXxw+DTej^ue!#5yU zl4C})mBo)+tho(_c~nyae}wt9jkIZ`JU47lYolj8?)YxR)Pq5`T!Oe&ek7u4v?EfR z`CtRKUl3JR5%Zx#W?)Qv;gZjmA7twvYPD>!)U>>GP}KO0h8iNC1l1h0muJWxMB95O z7rbz`b@l}1YUZepGW0aSvnDe8Dsz7KCy8=-T@P4o7kqoz)b}v#0n(0v_TMht+96Lb z0dX=83kVF@BMpE(<7g0wHx}q4{{`h!KU_N={wo@=`-bs$_9&UVxSPNAuSfN6x|tMi z?$k%>8lyF7>OLeBzpe3Ge~Ob@zq4;zyNLdkA z9+z>-bQLuexNI zX&c6uzTZkz5$-R4KSIX?d*@IDVW1!(^%CCe}3RBnt%H*%XwN3&xVI@fH%_G!Q zeYM`t{EM?#kRpjawkCbSQ~~w~VRR&+&~-xi zwENz5Y~K!#?W=EM`%>f#)F(=!3e1ngPN%cfP-@@38i}F6D^%Xd8rd89PKh;7-^RzX z&x@=~j$kSAR?yJoiu87ki&FSo#mG4dWUzaH74pkOo`zhp3+;+^@NAecii9C6ElNv- z%V+uBM@;!*WWc8C(8qj;DLIVYWjwo&sIF@;suaF?*;5nbv-DN)sY-ro0Fuz~dl%ei z!V}D)azhLBOa2x28wLmBf5}sb<^N7zYKR`>dvY14o}Dyr%R% zL}VZHX!})6Fa@}wRHNqW+_!yy$6667t*u`_xaw6?`GaYLc7R`p_uHy(z!k6&sju)D zA@#j< zt^)Tz=R|XFA1F%3|Jtqqh&WiZcNq26kDv-{vt%h@5?>n;b~ z0wdy<{4OzSVTziM4N8axak9uMAH!X1X;j3TMJs}vKHS|eMHKoGS3*rAj6e&(e6Xdp zl3+{2^dkbm(n4U@a-gTQk8YDCMsuOf$X=)=ao(^qLGajmE?*K!hE|~vjlLW8JkZ$Q zR+LZ)Z%-L(iOA!Xbasd2BWRanaq$AjDk`iMX5%IlgACbXIpYEB^Q&NaI5RxBFJwa*kR&MDzD$}Mu@4v8U!z3fs&^J#qdZ>+G#6?gFr>E97Gb#+qZ3f8n!V+P6xN_h_-iVt0r6@*LTh;9-jAfAhU9MP{ zrJ^vKlv9``B!aTj{CT~oRl!C<@fME|64l2dDz4MHGA zi?P++-F^Irn(V$_Yk=bVZlPmn(n|jp_MK;7zaT%h4U+*4LU?-#Ip*Dq0v64pPz%?b zq>nqLt8PDTspzwDnMaEXUQJL;CHbW~$_JE5gx1@|(Un@3Wzt&uWC!Jj`L*(Y+svw+ zf-i^^A1C{P+#OIoLX+DZNgs@pJaXUUipqU#aF$j1ZU~F8kb?UjVu+@bHiuP=ZKdP4 zsQieik(w5!{df-UtG*DxJNhLEGqQe-cAU|pEMNvXrZtio2 zPY|>OKi8dtD0HLtfikMb0QRRcRgJH&{PoTbg_mZgQkIrd)$ulV$+}+nJV!RCUS9(q5>Si#kB)~ekf}=5b~6qB3}_y zy})mi#PmsC)okM!YbI_Y@NM>bl`CgLG$~3$t0CixzFb4Z_|2i+@Ug|muq9r}PSpht z_{D}WyhDL~1P=HHpJ`XvZvlJ^0b~S9U{km&R@-Dth{8EjJG`q=oz}JVLOI2BQ@14m zEs8fl=fdz%migRw-mia%m7cfNLol;R*g`St1$tcL9;F3QlHo(5X$j3{h@XH6+OAj+ zsmDZ>(cFugTNCsaOKfk&M_ms0$%KCec;cmotQ|!tV_@WedUiJU);8!(3Qp3GMaR*o z@*J}-tTaX?Ho@*Ncbf#lQb-mIM+R!%zd7XvW35KWzJBFnZ7|?^eh=~OtMK6MRw~wz z1dMm-D8?+py>*|Kte^CFl*vYu&!asBr^Vp#k9wn#gTm9dPdQgdZ7Z6 z)OEqq>4#H#(#*Gb^^hlv>CrOTqB)!;ot@Dszbz7tyY+q7R0KS#mMrT4P6V7Yh=%GA zl#GamKmQE=#P(WCa$H6mvbUw9$m@lvpxv97lfri}cH%lf@_yzrIzqbZ6HVEub1?<_ zDsipl5G7{h0vMly&HK8rtUwZAaH8dSYoy)*CVX$xI8>l&r_ zVD&><`wFp9^p|3NW5{}(WKQj}RR@u+v zHwSuv7WKDfs@O9JW{s8fY{}zo0J(Zjs z?{n4TzV&dO%mKbIsNzE*&0(Sq$YaHD9Pkzi@x5@sfcm4G%~Ji0NBO2;XT+56I~NN5-|d`djc2Kmo5dp2F&MXB8b$~j8Vah7Sb)uL zfKl1LulRBpaHq@NEv1Vkh?~w3OtLHOqyyF8;td(dE{X52_KDifTCfpjZ)bVfK*!vD zNFr>uZ|bOyr)yIZIuo+Z`z`3h1qdtQ(s6Xe2%rlPGz&R^H#atcWvLD3glVjh4W79hlGYIC3= z!3U6;^4WluV?yC8@B4Rw*-Q!bcd|tagWu~G>B3ILe6vEyyd(y)vSjOqp}$V2vwNE- zf40+FKW^oWUE;1;Td#O?q^C7d;Roq4iWj;+^Bh2KdDs%Y%ymLxYGOW7?KX}klmx?b~-?G9b@geSTK zZj_oOZ~9N%L0|aqY5a@yQPaTk*F6W?dw{@h7Tp6f2=$=2Ns2arIsSZO@FTMOXA$Hk zgMHU!oJ{93%>oS4@DASQYk1%eotY1Oj7JaVgEW*dzvebhKYaS0srzNx9Ba|Tl1HnX z4;ct_!MHR$2;;h@l0lkI14C#t@VSJ)+7*c|Wm0zG%uCOAVyxoD>e#;``3zDmai49U zBfcpQy=%2Ie=cd)7Mc5#kb&q-%qLoRA>rt@6m9FFCDvLb|2MctL2?0E7R;pxq7!0G zf=&%Ubjsa4kfi&+gO?Y_^$tBAlKCRrdLbnCrXgVyX)9N9xu#)~bcBx5ni}JB?4=uC z88$79_R1)#D6Tg`#_pAxjr$u?!D0>2TMPt|#^g0p0h;Znr#if#clm9%N;pc%+EZJ> z4eyz|1(L&O%li=-dg>9HO%*~vH@akkiYOm^{3!2+pYW@1O1v?X#n()4%Nh1WKyAq@ z8EAvTC&!}UP%0U)-|LFa!TTJfBP@{Ds(e?Kf>JDw4<2#NN9E-b+-4)^U3{K~uY4l0 z$!0EH1l`a@v2?Pg%zwoLWF;8-8{QFm^B z)Sr;=$QsrNq#mz3v(aT2vQRsIQ1ZMn%HQ=#PtG%PudMU^BVB5BTYoe_GA1~tm{Xkxe80P+PQl7SD zFTSWYhuNffx%Oxe9j59TyIbbub>5Hf%zD=y%odgkt-d8pCgERE7#mXHG;sNl0NTTd zNM`APgaEF6ya@FKh3MjRPjN{@CvdlR+ok174s<)TEnoHYdBUfHIt=l~B9hhCYKCk`A42p%N_z{s1J@V;+uYpmpHA$x=0m%>MXlDBr}ZWpN7kcu3l+p>CC zbUYB5Xk}mguBB%C$&WFVnS9bAu4?4`O_cPZ&r4fr#Vy+{fh-A=&>}eyjvhICUwlTji@Iv!Ur{yC+W?^bF7@e7{%c_32RXl?X$?cDYp z8m{adI1-wr?Mj2c=1HE8M)vUBuNZEtuZX~0>CFuCBe8MsUTs^=SOBxB4hTrz@r?95 zpd|&$iU4~xxttEU=9rQ-Y*U9QgG2;ImGQdu#i-!@mdS8$K+-;li*SA+#qvf$VBkU| zL_fXjD}O9Ot{mH7J61->3FSv#6qO%%F$fA%VVr_mOQ{;1z{3Iax165%9dg!J1xrT2 zoJUu$gB;}a#z2&lz2YDpB<5ciasOjx7%gs#2aW17+%fcCSU-FDuFU$1=LxGN9$x-n z)YC^pPQz*Z(SFSk#eUhLHssI2xJfVr0g{nNkP>1>G{`~Jr(LmD^YX-4`;#T~EwV9u@^JSGXXJV~}P5e=9(jU=#XKRP*33+B_M z2bHxpkQW2{0B~a*ov4tMo4xj-xK%{)KgPZKt4_tGTpK2ug{Rft%19~0*C z4z0NT<7VL?5+Aqwcpgs!+1p+@7uO5S)vG%BJu?880jy~WEe>EvUC z<=C8q{MwDDAeuQu00*JZ|1$yULt{^l_E_gnre{8^kHjFI-V@n8h3e{!_!3%QQySUA zJRTD~T!TQO<%$u2RvzdnN*1$^0(8vv=zYI_+fgi!LvzgC?$22*GIvx-J$J8OwPumo zUo09TqO#cVC7CZH&Oskf+z!5nRc3+h|0L1m1;0l1Accg02@LVS1~TAGP$)TrUe9q{ zq_O5{oD*AIPKPhIbnk}eb@{wB$1#?^salD_6ZlFDv4kd4@jKOgH_u8xIPx(`pf#&M7BGsrwez^Og*+bh5}zY2nV>{o@QFIVvOw zpJEC+5EFxC>+TS|n`1yZ#Zxzw3`@6wctP&O5`OZpp`X;DXLX}@%-S7!<@ScMU*GeG z^Lv{lrS}Hbxla&k5c(?z=$3rbOf4$P{1bqoBJhxfm=X_Qf^)c@Q)OB`w$|lkF0Khx znlvG=UI@mUrggux7BJF4Noesj4L)4Zzolo{63Y=&M6BV~S{-C%H*HkvmoyoL9{Bzo zpsRuVafei}Oz;4T$7s+3^9y7;MTh*YibxB|rXuPE5@Tsmzen8t-uE08`m$v0ii**MH85ZrBSkVVcm=W9ZoVdGhg zxyWpPKj~t|CHT{*U}8oEE|m(K>HY+-7byc3AuPZ;d$0Tf+uB}GM_?TD*C69}x2QiSTbZIc zBLB4fCj3*nX4sy0+WcMoQ+r!PeMkEXM=xo)ubS??PvuJ}H3pUk75$Kqk`iD(`2|>c zAAmIzVVeetdi>dC_%At@)q6anzePDT|hpFSP*pspsDvcp#a=U_a5BWmn zd#(gXl$k_j7b=fY21m{z)Ym<(eeA3+T}$i)6a9s# zzUzndUZ;UjDcAi_Y&5^#_?UQx=XA-Xe&o~GQ=8HeoW1;O@;~=D2_7X-VWq__-jCv$ zvEvD`wjCfLb+A{iac+>{{-(YN4iym1QYo|moDg7khO=}^V?rR0{^EoVe#kwmp*iq} z!V8zj|Lc$Y8}9zA!7oO@L-e@+0t!)H4-_O^qk51ZRa~)9*xNtOhN$xI{cII`E(|4j z;Wer5NMDP^OE{2o9*P?v@y`7r5z`Y{vA6|csZV_CeVY2mvcDY$vnq}M6Jr1SOzF4q z&+LZv8bB&-E^8OZf17=T8<`ABX~0BhPM3eo8x)1ACSXL?{xZx@hCMq^Uq8b%usQ$J zu-U5IK^=b>h9qidTsw2Dnmcqlb?mqcH}L6#p0|*5nZ7mJl;@6m9F=1 zUPO)(!k^&N_5U_aTOG}NnFDIZe}9gD*+*99e>4DI1Jz(OzrZd)0G@gChO?daOKcey zX9P4ilni^M>h)ukb`)<-nXW6+d;RfjQC!V^N_K}*ny4$N(bXMcDPPrhh8qjpFPOt5 zL67J79#Al$1{fmjP^8<}dd)CpO&B*OIXZzVC>`V%XnE$J6}C^?uW31w7tdGgylH*f zzHU*#bE0eF6U^0)DQP{?mDs`#>8HM6`4GiM7^p)K7_N{>*7)IeK%L+%Fa?bWE8wTF zyX=Z}`WaR~H)>sI`Z;q%9r+%LmJ|I2ZMyttALX+TdZ|5C78^N{ce+0D;0C>sP3xm7 zMTwE(#v?C&kgB3OCEq$r2II{RgJ}T(zsv*dLV@H1fOWE@fGFHJkbb4DcD1H; zdEh`?Ks52z<~0BwxZ51;ij9U)_^SPR5kq;Fm^T_Xv=dR?XZbG-O=S)iqyHcN{`<+D0cKJ(zv z^=4omfRybt3ljiYo9;?O&)00|b8k8AdOcEi{^L|2x~m((SF1Wl`KCI9jVLS~Mc~Xx zpM6h7>&)cfUe+F8)?iI)yFhq!6O%;cCAxJ#?7oFb@s~i*SeST9ph%bDpfwZ@GOUun zR1Co4p6K|qX=2HRDHzb1hWe1|{CVK%sGqM;_*og<>k;)C{wM4((uyH;zgE+p2VMd3 zQJ-7HL{iLRg(jP=X|0=>(qTMNN=RBTJzLPNhKK3)$wyZEjNb7|`L=Ne`K|u*9pc-G z1NA9!$xEqqL6e%4;R#Q!M1|uS3Gf#X#3Fb)DYLy9SP(*=~?aB8a zg0~1*UA3xL3u!b2OdIX^r`rDGKZ)~S>>5!**Z6`IV|R#H zg`t6UJJkJY@B!}oPuf92{ezu6&mT#qb-%uPt$6!V04E1&w5In$olb)w_gQfBJy_5S zqvig|(gO4HgW%$ZLN5W_f9U27j~)fa3@$CzOurh>)3NXuGa}f0Q+mLDQj!f>`ft`oU@aCDSx6#ER%Ww~k2+I1La)IK&~tK>@sA`AN{Y2b0Z~ zMY|FwlPWU>NA3m3mMdSb>Z!Zf53IA!{rlTay3?e8uau{IR&`A)R7L(-u4U0rg$l2Z zbpiGD=WR{P&rGymCFrFI@xRqHL?RDEjsOL^5O~;dWkK_7zxj1ygS&oQRGjlnP*tZT zQ5Ru6B6IhTO+?%n>%DuDF0F-J7qKZ&e0yxCT2$kW&z?NH27{h|TGwEMwp$P+dl;1# zK%m14^MTp6?Cub&YX=WKg>YtDS-ixdNv-8`&UY^p&K|+UvwNRnJajznWR`y@AGNk^ zci$L;Vqbrjz-P8J>RsoKpZHfX=R$kioa1mT(B$O5gfz2E!gPXD!ScbP9{-pG>7#72 zE3x)PT2EiMHw!hR9D6aG;Kk2%H^~^0ysVH<(zcio-$=<4wln{;`s__ZVPcC~*yUK7 z;@C5mc-3fIxP8XQK?lF4LSHZJ*8~a-U2`DcmcOw;JmLw}TA2;sLVH~!j+#YBeBAP4 z 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 literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/nodes/CURRENT b/poa-network/multi-peer/node2/geth/nodes/CURRENT new file mode 100644 index 0000000..c7a124b --- /dev/null +++ b/poa-network/multi-peer/node2/geth/nodes/CURRENT @@ -0,0 +1 @@ +MANIFEST-000077 diff --git a/poa-network/multi-peer/node2/geth/nodes/LOCK b/poa-network/multi-peer/node2/geth/nodes/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/poa-network/multi-peer/node2/geth/nodes/LOG b/poa-network/multi-peer/node2/geth/nodes/LOG new file mode 100644 index 0000000..d21ed53 --- /dev/null +++ b/poa-network/multi-peer/node2/geth/nodes/LOG @@ -0,0 +1,299 @@ +=============== Jul 12, 2018 (BST) =============== +11:09:05.859266 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:09:05.881724 db@open opening +11:09:05.886827 version@stat F·[] S·0B[] Sc·[] +11:09:05.902200 db@janitor F·2 G·0 +11:09:05.902230 db@open done T·20.463441ms +=============== Jul 12, 2018 (BST) =============== +11:24:30.549578 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:24:30.549938 version@stat F·[] S·0B[] Sc·[] +11:24:30.549967 db@open opening +11:24:30.550069 journal@recovery F·1 +11:24:30.555568 journal@recovery recovering @1 +11:24:30.575186 memdb@flush created L0@2 N·1953 S·15KiB "n:\xbb..ver,v1870":"version,v1" +11:24:30.579660 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] +11:24:30.598959 db@janitor F·3 G·0 +11:24:30.599047 db@open done T·49.061622ms +=============== Jul 12, 2018 (BST) =============== +11:27:23.929314 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:27:23.929673 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] +11:27:23.929707 db@open opening +11:27:23.929818 journal@recovery F·1 +11:27:23.933816 journal@recovery recovering @3 +11:27:23.944145 memdb@flush created L0@5 N·155 S·1KiB "n:\xbb..ver,v2057":"n:\xdc..ong,v1961" +11:27:23.948584 version@stat F·[2] S·17KiB[17KiB] Sc·[0.50] +11:27:23.965318 db@janitor F·4 G·0 +11:27:23.965391 db@open done T·35.663326ms +11:27:23.969673 table@compaction L0·2 -> L1·0 S·17KiB Q·2110 +11:27:23.983676 table@build created L1@8 N·9 S·411B "n:\xbb..ver,v2057":"version,v1" +11:27:23.983838 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:27:24.000730 table@compaction committed F-1 S-16KiB Ke·0 D·2099 T·30.949886ms +11:27:24.000800 table@remove removed @5 +11:27:24.000839 table@remove removed @2 +=============== Jul 12, 2018 (BST) =============== +11:34:08.322462 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:34:08.322604 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:34:08.322614 db@open opening +11:34:08.322650 journal@recovery F·1 +11:34:08.324145 journal@recovery recovering @6 +11:34:08.351791 memdb@flush created L0@9 N·957 S·7KiB "n:\xbb..ver,v3049":"n:\xdc..ong,v2117" +11:34:08.356450 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] +11:34:08.382422 db@janitor F·4 G·0 +11:34:08.382467 db@open done T·59.843968ms +=============== Jul 12, 2018 (BST) =============== +11:53:49.053572 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:53:49.053723 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] +11:53:49.053735 db@open opening +11:53:49.053775 journal@recovery F·1 +11:53:49.055338 journal@recovery recovering @10 +11:53:49.069911 memdb@flush created L0@12 N·3140 S·24KiB "n:\xbb..ver,v6197":"n:\xdc..ong,v3076" +11:53:49.071823 version@stat F·[2 1] S·33KiB[32KiB 411B] Sc·[0.50 0.00] +11:53:49.087260 db@janitor F·5 G·0 +11:53:49.087302 db@open done T·33.558786ms +11:53:49.089173 table@compaction L0·2 -> L1·1 S·33KiB Q·6209 +11:53:49.100536 table@build created L1@15 N·9 S·412B "n:\xbb..ver,v6197":"version,v1" +11:53:49.100861 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] +11:53:49.115649 table@compaction committed F-2 S-32KiB Ke·0 D·4097 T·26.423679ms +11:53:49.115759 table@remove removed @12 +11:53:49.115813 table@remove removed @9 +11:53:49.115854 table@remove removed @8 +=============== Jul 12, 2018 (BST) =============== +14:17:44.682705 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:17:44.683753 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] +14:17:44.683816 db@open opening +14:17:44.683982 journal@recovery F·1 +14:17:44.689029 journal@recovery recovering @13 +14:17:44.749579 memdb@flush created L0@16 N·10616 S·83KiB "n:\xbb..ver,v16777":"n:\xdc..ong,v6212" +14:17:44.750996 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] +14:17:44.779208 db@janitor F·4 G·0 +14:17:44.779238 db@open done T·95.395734ms +=============== Jul 12, 2018 (BST) =============== +14:39:51.265662 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:39:51.265819 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] +14:39:51.265832 db@open opening +14:39:51.265875 journal@recovery F·1 +14:39:51.267251 journal@recovery recovering @17 +14:39:51.282847 memdb@flush created L0@19 N·3518 S·28KiB "n:\xbb..ver,v20335":"n:\xdc..ong,v16833" +14:39:51.284827 version@stat F·[2 1] S·112KiB[112KiB 412B] Sc·[0.50 0.00] +14:39:51.304139 db@janitor F·5 G·0 +14:39:51.304178 db@open done T·38.337769ms +14:39:51.306434 table@compaction L0·2 -> L1·1 S·112KiB Q·20345 +14:39:51.328923 table@build created L1@22 N·9 S·410B "n:\xbb..ver,v20335":"version,v1" +14:39:51.329000 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +14:39:51.352502 table@compaction committed F-2 S-112KiB Ke·0 D·14134 T·46.026738ms +14:39:51.352618 table@remove removed @19 +14:39:51.352681 table@remove removed @16 +14:39:51.352719 table@remove removed @15 +=============== Jul 12, 2018 (BST) =============== +15:37:20.124805 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:37:20.125293 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +15:37:20.125338 db@open opening +15:37:20.125492 journal@recovery F·1 +15:37:20.131018 journal@recovery recovering @20 +15:37:20.167319 memdb@flush created L0@23 N·9030 S·71KiB "n:\xbb..ver,v29311":"n:\xdc..ong,v20356" +15:37:20.170842 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] +15:37:20.187160 db@janitor F·4 G·0 +15:37:20.187230 db@open done T·61.857192ms +=============== Jul 12, 2018 (BST) =============== +15:48:32.297828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:48:32.297998 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] +15:48:32.298011 db@open opening +15:48:32.298064 journal@recovery F·1 +15:48:32.299666 journal@recovery recovering @24 +15:48:32.368672 memdb@flush created L0@26 N·1824 S·14KiB "n:\xbb..ver,v31169":"n:\xdc..ong,v29379" +15:48:32.370730 version@stat F·[2 1] S·86KiB[85KiB 410B] Sc·[0.50 0.00] +15:48:32.387501 db@janitor F·5 G·0 +15:48:32.387524 db@open done T·89.5036ms +15:48:32.391376 table@compaction L0·2 -> L1·1 S·86KiB Q·31201 +15:48:32.409611 table@build created L1@29 N·9 S·411B "n:\xbb..ver,v31169":"version,v1" +15:48:32.409682 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +15:48:32.424137 table@compaction committed F-2 S-85KiB Ke·0 D·10854 T·32.684737ms +15:48:32.424229 table@remove removed @26 +15:48:32.424293 table@remove removed @23 +15:48:32.424332 table@remove removed @22 +=============== Jul 12, 2018 (BST) =============== +16:05:29.052109 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:05:29.052302 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +16:05:29.052322 db@open opening +16:05:29.052385 journal@recovery F·1 +16:05:29.053889 journal@recovery recovering @27 +16:05:29.070585 memdb@flush created L0@30 N·2723 S·21KiB "n:\xbb..ver,v33872":"n:\xdc..ong,v31212" +16:05:29.072728 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] +16:05:29.088665 db@janitor F·4 G·0 +16:05:29.088693 db@open done T·36.35836ms +=============== Jul 12, 2018 (BST) =============== +16:23:49.639965 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:23:49.640119 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] +16:23:49.640132 db@open opening +16:23:49.640177 journal@recovery F·1 +16:23:49.641522 journal@recovery recovering @31 +16:23:49.702907 memdb@flush created L0@33 N·2951 S·23KiB "n:\xbb..ver,v36828":"n:\xdc..ong,v33936" +16:23:49.707537 version@stat F·[2 1] S·45KiB[45KiB 411B] Sc·[0.50 0.00] +16:23:49.726802 db@janitor F·5 G·0 +16:23:49.726888 db@open done T·86.744755ms +16:23:49.730542 table@compaction L0·2 -> L1·1 S·45KiB Q·36877 +16:23:49.755043 table@build created L1@36 N·9 S·404B "n:\xbb..ver,v36828":"version,v1" +16:23:49.755142 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] +16:23:49.769539 table@compaction committed F-2 S-45KiB Ke·0 D·5674 T·38.915634ms +16:23:49.769669 table@remove removed @33 +16:23:49.769735 table@remove removed @30 +16:23:49.769777 table@remove removed @29 +=============== Jul 12, 2018 (BST) =============== +16:40:12.633424 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:40:12.633675 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] +16:40:12.633694 db@open opening +16:40:12.633751 journal@recovery F·1 +16:40:12.635430 journal@recovery recovering @34 +16:40:12.653741 memdb@flush created L0@37 N·2658 S·21KiB "n:\xbb..ver,v39480":"n:\xdc..ong,v36880" +16:40:12.655362 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] +16:40:12.672204 db@janitor F·4 G·0 +16:40:12.672249 db@open done T·38.544509ms +=============== Jul 12, 2018 (BST) =============== +16:57:40.345817 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:57:40.345996 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] +16:57:40.346012 db@open opening +16:57:40.346070 journal@recovery F·1 +16:57:40.347980 journal@recovery recovering @38 +16:57:40.363783 memdb@flush created L0@40 N·2786 S·22KiB "n:\xbb..ver,v42253":"n:\xdc..ong,v39543" +16:57:40.365500 version@stat F·[2 1] S·44KiB[43KiB 404B] Sc·[0.50 0.00] +16:57:40.381342 db@janitor F·5 G·0 +16:57:40.381385 db@open done T·35.364738ms +16:57:40.383292 table@compaction L0·2 -> L1·1 S·44KiB Q·42323 +16:57:40.408961 table@build created L1@43 N·9 S·410B "n:\xbb..ver,v42253":"version,v1" +16:57:40.409041 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +16:57:40.423831 table@compaction committed F-2 S-43KiB Ke·0 D·5444 T·40.39884ms +16:57:40.423935 table@remove removed @40 +16:57:40.423986 table@remove removed @37 +16:57:40.424026 table@remove removed @36 +21:39:50.525477 memdb@flush N·43421 S·3MiB +21:39:50.610325 memdb@flush created L0@45 N·43421 S·341KiB "n:\xbb..ver,v85728":"n:\xdc..ong,v42330" +21:39:50.610621 version@stat F·[1 1] S·341KiB[341KiB 410B] Sc·[0.25 0.00] +21:39:50.619942 memdb@flush committed F·1 T·94.239078ms +21:39:50.627386 journal@remove removed @41 +=============== Jul 13, 2018 (BST) =============== +02:22:42.318770 memdb@flush N·43426 S·3MiB +02:22:42.349319 memdb@flush created L0@47 N·43426 S·341KiB "n:\xbb..ver,v129168":"n:\xdc..ong,v85750" +02:22:42.349367 version@stat F·[2 1] S·682KiB[682KiB 410B] Sc·[0.50 0.00] +02:22:42.356398 memdb@flush committed F·1 T·37.578228ms +02:22:42.357339 journal@remove removed @44 +07:04:10.330333 memdb@flush N·43422 S·3MiB +07:04:10.393823 memdb@flush created L0@49 N·43422 S·341KiB "n:\xbb..ver,v172517":"n:\xdc..ong,v129177" +07:04:10.393906 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] +07:04:10.401140 memdb@flush committed F·1 T·70.637042ms +07:04:10.404444 journal@remove removed @46 +=============== Jul 13, 2018 (BST) =============== +11:03:48.229037 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:03:48.229335 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] +11:03:48.229357 db@open opening +11:03:48.229460 journal@recovery F·1 +11:03:48.233070 journal@recovery recovering @48 +11:03:48.333384 memdb@flush created L0@50 N·35960 S·283KiB "n:\xbb..ver,v208539":"n:\xdc..ong,v172602" +11:03:48.335105 version@stat F·[4 1] S·1MiB[1MiB 410B] Sc·[1.00 0.00] +11:03:48.365177 db@janitor F·7 G·0 +11:03:48.365234 db@open done T·135.861856ms +11:03:48.365374 table@compaction L0·4 -> L1·1 S·1MiB Q·208553 +11:03:48.537826 table@build created L1@53 N·9 S·411B "n:\xbb..ver,v208539":"version,v1" +11:03:48.537925 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:03:48.552126 table@compaction committed F-4 S-1MiB Ke·0 D·166229 T·186.66634ms +11:03:48.552301 table@remove removed @50 +11:03:48.552405 table@remove removed @49 +11:03:48.552509 table@remove removed @47 +11:03:48.552616 table@remove removed @45 +11:03:48.552651 table@remove removed @43 +=============== Jul 13, 2018 (BST) =============== +11:20:12.182469 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:20:12.182651 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:20:12.182664 db@open opening +11:20:12.182717 journal@recovery F·1 +11:20:12.184513 journal@recovery recovering @51 +11:20:12.241385 memdb@flush created L0@54 N·2632 S·21KiB "n:\xbb..ver,v211126":"n:\xdc..ong,v208560" +11:20:12.243129 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] +11:20:12.267182 db@janitor F·4 G·0 +11:20:12.267224 db@open done T·84.550385ms +=============== Jul 13, 2018 (BST) =============== +11:22:05.344239 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:22:05.344426 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] +11:22:05.344439 db@open opening +11:22:05.344495 journal@recovery F·1 +11:22:05.346064 journal@recovery recovering @55 +11:22:05.396304 memdb@flush created L0@57 N·327 S·2KiB "n:\xbb..ver,v211460":"n:\xdc..ong,v211193" +11:22:05.398077 version@stat F·[2 1] S·24KiB[23KiB 411B] Sc·[0.50 0.00] +11:22:05.423465 db@janitor F·5 G·0 +11:22:05.423498 db@open done T·79.043478ms +11:22:05.431533 table@compaction L0·2 -> L1·1 S·24KiB Q·211514 +11:22:05.447314 table@build created L1@60 N·9 S·410B "n:\xbb..ver,v211460":"version,v1" +11:22:05.447458 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +11:22:05.465235 table@compaction committed F-2 S-23KiB Ke·0 D·2959 T·33.57446ms +11:22:05.465771 table@remove removed @57 +11:22:05.465835 table@remove removed @54 +11:22:05.465892 table@remove removed @53 +=============== Jul 13, 2018 (BST) =============== +11:28:36.605530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:28:36.605766 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +11:28:36.605790 db@open opening +11:28:36.605861 journal@recovery F·1 +11:28:36.605970 journal@recovery recovering @58 +11:28:36.669491 memdb@flush created L0@61 N·1083 S·8KiB "n:\xbb..ver,v212511":"n:\xdc..ong,v211525" +11:28:36.675160 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] +11:28:36.702895 db@janitor F·4 G·0 +11:28:36.702923 db@open done T·97.12478ms +=============== Jul 13, 2018 (BST) =============== +11:41:32.591748 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:32.592105 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] +11:41:32.592141 db@open opening +11:41:32.592263 journal@recovery F·1 +11:41:32.596765 journal@recovery recovering @62 +11:41:32.663254 memdb@flush created L0@64 N·2051 S·16KiB "n:\xbb..ver,v214616":"n:\xdc..ong,v212601" +11:41:32.667391 version@stat F·[2 1] S·25KiB[25KiB 410B] Sc·[0.50 0.00] +11:41:32.687539 db@janitor F·5 G·0 +11:41:32.687649 db@open done T·95.481415ms +11:41:32.693255 table@compaction L0·2 -> L1·1 S·25KiB Q·214650 +11:41:32.705795 table@build created L1@67 N·9 S·402B "n:\xbb..ver,v214616":"version,v1" +11:41:32.705947 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] +11:41:32.716509 table@compaction committed F-2 S-25KiB Ke·0 D·3134 T·23.166583ms +11:41:32.716920 table@remove removed @64 +11:41:32.717040 table@remove removed @61 +11:41:32.717124 table@remove removed @60 +=============== Jul 13, 2018 (BST) =============== +13:24:41.332660 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:24:41.333223 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] +13:24:41.333279 db@open opening +13:24:41.333442 journal@recovery F·1 +13:24:41.338137 journal@recovery recovering @65 +13:24:41.431439 memdb@flush created L0@68 N·16181 S·126KiB "n:\xbb..ver,v230767":"n:\xdc..ong,v214663" +13:24:41.436600 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] +13:24:41.455095 db@janitor F·4 G·0 +13:24:41.455178 db@open done T·121.864633ms +=============== Jul 13, 2018 (BST) =============== +13:52:04.996573 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:52:04.996949 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] +13:52:04.996993 db@open opening +13:52:04.997131 journal@recovery F·1 +13:52:05.001435 journal@recovery recovering @69 +13:52:05.038322 memdb@flush created L0@71 N·373 S·3KiB "n:\xbb..ver,v231162":"n:\xdc..ong,v230839" +13:52:05.042832 version@stat F·[2 1] S·129KiB[129KiB 402B] Sc·[0.50 0.00] +13:52:05.062434 db@janitor F·5 G·0 +13:52:05.062495 db@open done T·65.477336ms +13:52:05.066040 table@compaction L0·2 -> L1·1 S·129KiB Q·231206 +13:52:05.082072 table@build created L1@74 N·9 S·408B "n:\xbb..ver,v231162":"version,v1" +13:52:05.082302 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] +13:52:05.096557 table@compaction committed F-2 S-129KiB Ke·0 D·16554 T·30.442172ms +13:52:05.096669 table@remove removed @71 +13:52:05.096762 table@remove removed @68 +13:52:05.096809 table@remove removed @67 +=============== Jul 13, 2018 (BST) =============== +13:54:50.248625 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:54:50.249067 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] +13:54:50.249113 db@open opening +13:54:50.249268 journal@recovery F·1 +13:54:50.255685 journal@recovery recovering @72 +13:54:50.390496 memdb@flush created L0@75 N·6566 S·237KiB "n:\x00..ail,v235060":"n:\xff..ing,v235771" +13:54:50.392211 version@stat F·[1 1] S·237KiB[237KiB 408B] Sc·[0.25 0.00] +13:54:50.407405 db@janitor F·4 G·0 +13:54:50.407439 db@open done T·158.300632ms +13:55:22.967627 table@compaction L0·1 -> L1·1 S·237KiB Q·238097 +13:55:23.046954 table@build created L1@78 N·4978 S·219KiB "n:\x00..ail,v235060":"version,v1" +13:55:23.047304 version@stat F·[0 1] S·219KiB[0B 219KiB] Sc·[0.00 0.00] +13:55:23.055317 table@compaction committed F-1 S-17KiB Ke·0 D·1597 T·87.525732ms +13:55:23.056075 table@remove removed @75 +13:55:23.056416 table@remove removed @74 diff --git a/poa-network/multi-peer/node2/geth/nodes/MANIFEST-000077 b/poa-network/multi-peer/node2/geth/nodes/MANIFEST-000077 new file mode 100644 index 0000000000000000000000000000000000000000..ed5755705aacd31393887de7a3e8846dbf2f1213 GIT binary patch literal 852 zcmeA_$H1J!#KlUkOVlai$8R9TW*o>`pgoS$2eSd>_jU&Q3Y?8kEUARjA3OrF)9 zjkkYX7kFJO@ZiyHxm@FdBO5&4KdGr|J+jq&8+VLgv)-q8rcBWt%r7+#-n3`j5iBg{ zsFTcbUZ-H(Q>o2T|0&j{MM>6XUzY>7LH z%KNGdb~jgV?+8Lzk(Qa4l9rg6!)P)MYz5Hp|I;4M)?6=g{ApZ4YUdq~R+;bdI?B!| z{TqWsvh^ICKhNCP{jBPmY=(A$E!*AAf)i60a9lW0b!=1aT{*6_DG~n>hJ)Ro33UJO z8N)@)PU!yQ-V{Y#BN(gEt$a7dxZhm3zE2O;+e01OOahU@-sy literal 0 HcmV?d00001 diff --git a/poa-network/multi-peer/node2/geth/transactions.rlp b/poa-network/multi-peer/node2/geth/transactions.rlp new file mode 100755 index 0000000..e69de29 diff --git a/poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 b/poa-network/multi-peer/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 similarity index 100% rename from poa-network/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 rename to poa-network/multi-peer/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 diff --git a/poa-network/node2/password.txt b/poa-network/multi-peer/node2/password.txt similarity index 100% rename from poa-network/node2/password.txt rename to poa-network/multi-peer/node2/password.txt diff --git a/poa-network/single-peer/accounts.txt b/poa-network/single-peer/accounts.txt new file mode 100644 index 0000000..f349749 --- /dev/null +++ b/poa-network/single-peer/accounts.txt @@ -0,0 +1,2 @@ +2be5ab0e43b6dc2908d5321cf318f35b80d0c10d +8671e5e08d74f338ee1c462340842346d797afd3 diff --git a/poa-network/single-peer/genesis.json b/poa-network/single-peer/genesis.json new file mode 100644 index 0000000..5cba62b --- /dev/null +++ b/poa-network/single-peer/genesis.json @@ -0,0 +1,30 @@ +{ + "config": { + "chainId": 1515, + "homesteadBlock": 1, + "eip150Block": 2, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 3, + "eip158Block": 3, + "byzantiumBlock": 4, + "clique": { + "period": 1, + "epoch": 30000 + } + }, + "nonce": "0x0", + "timestamp": "0x5b165989", + "extraData": "0x00000000000000000000000000000000000000000000000000000000000000002be5ab0e43b6dc2908d5321cf318f35b80d0c10d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0xFFFFFF", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "2be5ab0e43b6dc2908d5321cf318f35b80d0c10d": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/poa-network/single-peer/node1/geth/LOCK b/poa-network/single-peer/node1/geth/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/poa-network/single-peer/node1/geth/chaindata/000002.ldb b/poa-network/single-peer/node1/geth/chaindata/000002.ldb new file mode 100644 index 0000000000000000000000000000000000000000..cb7629dadbb346002c1352d775009edf0e0fb3d5 GIT binary patch literal 794 zcmZqTS-_yl;qmwO)qhgKGv=!socMbFa^72w75h2Nuf2?)weaa5#*5)M8Ce+^81$GJ z3s%N#Sojn?QWH~Bix|1488YxN7&0euYB4Z0#WJukvT$le z96E4-!Qu{MYDq?FQEF+fZgPHJT4uU#-5j7iH>Z6{wNi3MVrHIaijtL~siCQkQbvAm zYHXHKrtPq)XV}yQv+TB1|vZM6_3Q?3?(Zig9?LRj0_A)yg>}6yh#kkKv@e( z0fnT>s>HmK%+g$5VHXn}rR1E)z>vqt!O2}G$;iX0@s_1d1?V<5P9L71Oj!#!xzZRJIu^*D@qKaccx=_`)~)H= z&RmhYEaWOZrK?2v!$POO4p%0-Phs$~W%%H{;B34Ls~T6P=?0IN!numFKj%d{N3MS0 zdwzOMF<;Dw>l_QhUdW3}p9x*|zuEQKqys*M4tiVMQ36d71{ zGI~`o{9}ZoZHx>ij1A5I|Nn1ji583O+)-Nhhrvht>1sabZFe*|t{TaFmiQdqaN!_t zoe4t|BSVt|6GMlfvxp`qV+kWOC!YW#gCS!PCwG??3j;f+7BEJPMT%3CON&x`mV$nLLI<37?n+?@itYy6{{`B|=DKRo~ng@Mn;Lzw{tXssy!pOww z!1JSPp+a2_gUF7wA1MtBcny;n8QQ)u%{h9>jj`>!vdyHr+D&(kGaq=$ur2shle%^F zuNy3}txF1k>4*UsZw!pz_U&KNbm)Ca{59j|v?W7h&LJKF9c=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsGqfv7>Ai1H+Dg zK5X-R*jO}z>sB+fFtYM)V+mYP_mF|1fsv76L0vFAqpC>*7=W?>Fisg5oxKCJ(%|NPo4l9NM0C-xfx7mS-9y}FeoyoW#*Km7U|`rmZj#TB&7arv71c>qzP=O@YRJI#6=i5neQYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=&~ggKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0QHestpET3 literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000008.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000008.ldb new file mode 100644 index 0000000000000000000000000000000000000000..d2b26a1513df62490165abb9178df47524827180 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(5igKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7araSq}muu(H6 uxR{8GFmN)bG5+Ud)L=LX5{1|jQh)Z?Q%3!nOkyA*{2=^yL$^w)`)vRx>RJN; literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000011.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000011.ldb new file mode 100644 index 0000000000000000000000000000000000000000..df591285ec4a5126c6edcfcaadbe0d6cdbf90ba3 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(2hgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(8jgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c40gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0Gb3^x&QzG literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000020.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000020.ldb new file mode 100644 index 0000000000000000000000000000000000000000..0f885d9e99a6ddfd068f3d58435204b29fb142a7 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cA2gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c71gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cD3gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qiLgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm8l$aRU zK%$&L%*|leYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qoNgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qlMgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmH7Hgo`4N=yuF zAW=>r=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r05HB;{Qv*} literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000038.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000038.ldb new file mode 100644 index 0000000000000000000000000000000000000000..a05ec3826f2c34a6199189d16cc0a8392e95cf55 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qrOgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*08mI;GXMYp literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000041.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000041.ldb new file mode 100644 index 0000000000000000000000000000000000000000..c8f05dd77cbe3eac74780b6ebaab315d0e462feb GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANm$gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm?x!EOeQgq5PlH;yP;d9)crO9n~Yko literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000044.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000044.ldb new file mode 100644 index 0000000000000000000000000000000000000000..627147b4d7b2f480a6a51150b612a39211a8ccf9 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANs&gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANp%gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANv(gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0AdtcNB{r; literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000053.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000053.ldb new file mode 100644 index 0000000000000000000000000000000000000000..32548614e07c2dcfdabd893cf97d080abd9721d4 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HL=gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0A*QPO8@`> literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000056.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000056.ldb new file mode 100644 index 0000000000000000000000000000000000000000..3c07eed7394d4b6511ac7fd9c724fdf5e2425875 GIT binary patch literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HR?gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm L1·0 S·2KiB Q·22 +=============== Jul 12, 2018 (BST) =============== +14:17:42.392536 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:17:42.395630 version@stat F·[4] S·2KiB[2KiB] Sc·[1.00] +14:17:42.395645 db@open opening +14:17:42.395694 journal@recovery F·1 +14:17:42.395969 journal@recovery recovering @12 +14:17:42.413553 memdb@flush created L0@14 N·1 S·356B "eth..\x0e/(,v22":"eth..\x0e/(,v22" +14:17:42.414591 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] +14:17:42.442813 db@janitor F·7 G·0 +14:17:42.442842 db@open done T·47.187651ms +14:17:42.442909 table@compaction L0·5 -> L1·0 S·2KiB Q·23 +=============== Jul 12, 2018 (BST) =============== +14:39:49.043706 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:39:49.043821 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] +14:39:49.043835 db@open opening +14:39:49.043899 journal@recovery F·1 +14:39:49.044289 journal@recovery recovering @15 +14:39:49.051780 memdb@flush created L0@17 N·1 S·356B "eth..\x0e/(,v24":"eth..\x0e/(,v24" +14:39:49.052391 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] +14:39:49.081746 db@janitor F·8 G·0 +14:39:49.081769 db@open done T·37.92478ms +=============== Jul 12, 2018 (BST) =============== +15:37:17.901222 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:37:17.901345 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] +15:37:17.901358 db@open opening +15:37:17.901421 journal@recovery F·1 +15:37:17.901850 journal@recovery recovering @18 +15:37:17.910929 memdb@flush created L0@20 N·1 S·356B "eth..\x0e/(,v26":"eth..\x0e/(,v26" +15:37:17.911100 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] +15:37:17.925999 db@janitor F·9 G·0 +15:37:17.926024 db@open done T·24.65714ms +15:37:17.927077 table@compaction L0·7 -> L1·0 S·3KiB Q·27 +=============== Jul 12, 2018 (BST) =============== +15:48:30.025065 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:48:30.025198 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] +15:48:30.025211 db@open opening +15:48:30.025278 journal@recovery F·1 +15:48:30.025786 journal@recovery recovering @21 +15:48:30.038226 memdb@flush created L0@23 N·1 S·356B "eth..\x0e/(,v28":"eth..\x0e/(,v28" +15:48:30.038417 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] +15:48:30.066147 db@janitor F·10 G·0 +15:48:30.066173 db@open done T·40.953875ms +15:48:30.066226 table@compaction L0·8 -> L1·0 S·3KiB Q·29 +=============== Jul 12, 2018 (BST) =============== +16:05:26.776151 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:05:26.776271 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] +16:05:26.776283 db@open opening +16:05:26.776346 journal@recovery F·1 +16:05:26.776757 journal@recovery recovering @24 +16:05:26.787652 memdb@flush created L0@26 N·1 S·356B "eth..\x0e/(,v30":"eth..\x0e/(,v30" +16:05:26.789490 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] +16:05:26.816798 db@janitor F·11 G·0 +16:05:26.816853 db@open done T·40.562165ms +16:05:26.817677 table@compaction L0·9 -> L1·0 S·3KiB Q·31 +=============== Jul 12, 2018 (BST) =============== +16:23:47.409548 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:23:47.409692 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] +16:23:47.409705 db@open opening +16:23:47.409772 journal@recovery F·1 +16:23:47.410167 journal@recovery recovering @27 +16:23:47.423566 memdb@flush created L0@29 N·1 S·356B "eth..\x0e/(,v32":"eth..\x0e/(,v32" +16:23:47.423748 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] +16:23:47.446201 db@janitor F·12 G·0 +16:23:47.446221 db@open done T·36.509905ms +16:23:47.446274 table@compaction L0·10 -> L1·0 S·4KiB Q·33 +=============== Jul 12, 2018 (BST) =============== +16:40:10.390435 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:40:10.390563 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] +16:40:10.390577 db@open opening +16:40:10.390649 journal@recovery F·1 +16:40:10.391101 journal@recovery recovering @30 +16:40:10.411407 memdb@flush created L0@32 N·1 S·356B "eth..\x0e/(,v34":"eth..\x0e/(,v34" +16:40:10.411625 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] +16:40:10.440987 db@janitor F·13 G·0 +16:40:10.441011 db@open done T·50.42733ms +16:40:10.441063 table@compaction L0·11 -> L1·0 S·4KiB Q·35 +=============== Jul 12, 2018 (BST) =============== +16:57:38.124701 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:57:38.124826 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] +16:57:38.124838 db@open opening +16:57:38.124894 journal@recovery F·1 +16:57:38.125141 journal@recovery recovering @33 +16:57:38.138032 memdb@flush created L0@35 N·1 S·356B "eth..\x0e/(,v36":"eth..\x0e/(,v36" +16:57:38.138332 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] +16:57:38.159988 db@janitor F·14 G·0 +16:57:38.160014 db@open done T·35.167225ms +16:57:38.160670 table@compaction L0·12 -> L1·0 S·4KiB Q·37 +=============== Jul 13, 2018 (BST) =============== +11:03:46.000460 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:03:46.000607 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] +11:03:46.000618 db@open opening +11:03:46.000698 journal@recovery F·1 +11:03:46.001141 journal@recovery recovering @36 +11:03:46.008992 memdb@flush created L0@38 N·1 S·356B "eth..\x0e/(,v38":"eth..\x0e/(,v38" +11:03:46.009163 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] +11:03:46.023882 db@janitor F·15 G·0 +11:03:46.023908 db@open done T·23.283363ms +11:03:46.023980 table@compaction L0·13 -> L1·0 S·5KiB Q·39 +=============== Jul 13, 2018 (BST) =============== +11:20:09.942969 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:20:09.943598 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] +11:20:09.943626 db@open opening +11:20:09.943722 journal@recovery F·1 +11:20:09.947317 journal@recovery recovering @39 +11:20:09.958460 memdb@flush created L0@41 N·1 S·356B "eth..\x0e/(,v40":"eth..\x0e/(,v40" +11:20:09.959885 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] +11:20:09.975584 db@janitor F·16 G·0 +11:20:09.975619 db@open done T·31.977474ms +11:20:09.976379 table@compaction L0·14 -> L1·0 S·5KiB Q·41 +=============== Jul 13, 2018 (BST) =============== +11:22:02.953772 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:22:02.954444 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] +11:22:02.954479 db@open opening +11:22:02.954598 journal@recovery F·1 +11:22:02.966261 journal@recovery recovering @42 +11:22:02.978212 memdb@flush created L0@44 N·1 S·356B "eth..\x0e/(,v42":"eth..\x0e/(,v42" +11:22:02.978765 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] +11:22:02.999921 db@janitor F·17 G·0 +11:22:02.999956 db@open done T·45.466851ms +11:22:03.000743 table@compaction L0·15 -> L1·0 S·5KiB Q·43 +=============== Jul 13, 2018 (BST) =============== +11:28:34.365499 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:28:34.365667 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] +11:28:34.365687 db@open opening +11:28:34.365776 journal@recovery F·1 +11:28:34.367127 journal@recovery recovering @45 +11:28:34.380594 memdb@flush created L0@47 N·1 S·356B "eth..\x0e/(,v44":"eth..\x0e/(,v44" +11:28:34.380999 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] +11:28:34.403500 db@janitor F·18 G·0 +11:28:34.403536 db@open done T·37.840488ms +11:28:34.403948 table@compaction L0·16 -> L1·0 S·6KiB Q·45 +=============== Jul 13, 2018 (BST) =============== +11:41:30.386027 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:30.386185 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] +11:41:30.386203 db@open opening +11:41:30.386272 journal@recovery F·1 +11:41:30.386659 journal@recovery recovering @48 +11:41:30.394072 memdb@flush created L0@50 N·1 S·356B "eth..\x0e/(,v46":"eth..\x0e/(,v46" +11:41:30.394334 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] +11:41:30.410389 db@janitor F·19 G·0 +11:41:30.410973 db@open done T·24.760035ms +11:41:30.411851 table@compaction L0·17 -> L1·0 S·6KiB Q·47 +=============== Jul 13, 2018 (BST) =============== +13:24:39.113379 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:24:39.113565 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] +13:24:39.113598 db@open opening +13:24:39.113722 journal@recovery F·1 +13:24:39.114072 journal@recovery recovering @51 +13:24:39.121664 memdb@flush created L0@53 N·1 S·356B "eth..\x0e/(,v48":"eth..\x0e/(,v48" +13:24:39.121894 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] +13:24:39.136887 db@janitor F·20 G·0 +13:24:39.136917 db@open done T·23.308508ms +13:24:39.137816 table@compaction L0·18 -> L1·0 S·6KiB Q·49 +=============== Jul 13, 2018 (BST) =============== +13:39:12.018429 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:39:12.019064 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] +13:39:12.019145 db@open opening +13:39:12.019839 journal@recovery F·1 +13:39:12.021641 journal@recovery recovering @54 +13:39:12.030692 memdb@flush created L0@56 N·1 S·356B "eth..\x0e/(,v50":"eth..\x0e/(,v50" +13:39:12.032915 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:39:12.052820 db@janitor F·21 G·0 +13:39:12.052920 db@open done T·33.639977ms +=============== Jul 13, 2018 (BST) =============== +13:41:58.941624 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:41:58.942136 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:41:58.942205 db@open opening +13:41:58.942530 journal@recovery F·1 +13:41:58.943580 journal@recovery recovering @57 +13:41:58.946268 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:41:58.963116 db@janitor F·21 G·0 +13:41:58.963242 db@open done T·21.000186ms +13:41:58.963542 table@compaction L0·19 -> L1·0 S·7KiB Q·51 +=============== Jul 13, 2018 (BST) =============== +13:50:49.450674 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:50:49.450804 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:50:49.450822 db@open opening +13:50:49.450889 journal@recovery F·1 +13:50:49.451330 journal@recovery recovering @59 +13:50:49.452188 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:50:49.467448 db@janitor F·21 G·0 +13:50:49.467489 db@open done T·16.657771ms +=============== Jul 13, 2018 (BST) =============== +13:54:34.930429 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:54:34.930546 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:54:34.930560 db@open opening +13:54:34.930626 journal@recovery F·1 +13:54:34.930819 journal@recovery recovering @61 +13:54:34.931374 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:54:34.947674 db@janitor F·21 G·0 +13:54:34.947767 db@open done T·17.191913ms +=============== Jul 13, 2018 (BST) =============== +13:57:08.944621 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:57:08.945178 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:57:08.945263 db@open opening +13:57:08.945603 journal@recovery F·1 +13:57:08.947077 journal@recovery recovering @63 +13:57:08.951043 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +13:57:08.971140 db@janitor F·21 G·0 +13:57:08.971265 db@open done T·25.961614ms +13:57:08.971547 table@compaction L0·19 -> L1·0 S·7KiB Q·51 +=============== Jul 13, 2018 (BST) =============== +14:14:56.449979 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:14:56.450651 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +14:14:56.450749 db@open opening +14:14:56.451334 journal@recovery F·1 +14:14:56.452603 journal@recovery recovering @65 +14:14:56.457641 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +14:14:56.475716 db@janitor F·21 G·0 +14:14:56.475804 db@open done T·24.938608ms +14:14:56.476030 table@compaction L0·19 -> L1·0 S·7KiB Q·51 +=============== Jul 13, 2018 (BST) =============== +14:34:07.781663 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:34:07.782320 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +14:34:07.782416 db@open opening +14:34:07.782844 journal@recovery F·1 +14:34:07.784127 journal@recovery recovering @67 +14:34:07.786947 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] +14:34:07.805547 db@janitor F·21 G·0 +14:34:07.805659 db@open done T·23.18933ms diff --git a/poa-network/single-peer/node1/geth/lightchaindata/MANIFEST-000070 b/poa-network/single-peer/node1/geth/lightchaindata/MANIFEST-000070 new file mode 100644 index 0000000000000000000000000000000000000000..e86e81de59824bd86660c0db774e409d7814455c GIT binary patch literal 2270 zcmbWw&ntrg9LMqRGt*beuO&a88OxZ*k7t-}Bo4MA!zDm5`|cVe3#qJ=znN)-=M_CD(iV?O9WhG=PL|7GNC1ff<*bh|`7 zrSJOQm;TkW^nzpZS+V{zTC&X_*sr*rS9cE|%R)ct+ZtDOX{y8C7g`(&2S1*a%>Uyr DLOxQ< literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/nodekey b/poa-network/single-peer/node1/geth/nodekey new file mode 100644 index 0000000..8a307c3 --- /dev/null +++ b/poa-network/single-peer/node1/geth/nodekey @@ -0,0 +1 @@ +7b40b607cd20a19d0464f74d9b90d668aaa67f2a61951301205c6a73f572e8e0 \ No newline at end of file diff --git a/poa-network/single-peer/node1/geth/nodes/000098.ldb b/poa-network/single-peer/node1/geth/nodes/000098.ldb new file mode 100644 index 0000000000000000000000000000000000000000..ecead2545dd3cee12daa10ea1221bff19fa8ee03 GIT binary patch literal 1327685 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

~_P6?SYn1K&B2G1fb@Ss9^ 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 ioa@Q zPdu>~?&A{&w^fcWteC^>I7qf@EMfv#g54p{_OrCh}>+L<%xK?NZ zvwood1G?P|G))%V4a~8O$P2M~FM2@F^vJ4wlIn9P{qR>5?_YB#o7hy*w z&`7l8kZ&e*t4J>A1SH|g{w#e#vH6sF;#vD3l^D-gKzhLmY*E0L1gk|yP4QJz&o`p< zID3tMEQWBNFTNXun~?N>RUwTt-I($yT~DPu+76Er<0xpn~;JgAjo8 z-=}B*A)Hoz2<4p+;Qxti;4S*a>R^Vuv1e(}SKIat>nj~QQ80@Z*D`+N^bTf{bcbF} z(7|gHu8_1LX)4f|=?UgrgY9sEPJ%~sFn1eZHnv*?3L(d<)i+{SkmwTwotdZ8@A zDk2>ozUh0u&B8YkmLXd`pTgU&H`l+8d^z2KCJy&zcszM&mW`SJWt)7i6T%M$TKL-BW`uBFzRa{AI?DYblglbK->Tb?Ygtx zpUV3kG3XE0e{acM!A_JjKhzo~&Tq+YU)Di!rXW65DURXq{$w`gqxHN(y@6)vAQtDD zSVlnRq{%(FN0~mQV0%IQ6QvT!AM~^W5p>B}D7A}*Apcty%xo4eOCxJ6JZiy!Ih7wj z-4~)+|D4rPYvBd8qI}a@NWvih4RKZav;jUPCwpqu^Ts!_&fAxI7^n`5#nJN%&czx1agk?AOh+Db*x4lg~^`=xH7*%w@r}z26G3nbl7+< z6OXAmqrM-M8pL&*9rkU6)O)jbdpQ|sQVo^T?Lp3KO6RPz#<)_%@ z{vlGCc&oxKFFkGz=%w)C0_G4vWPR@!&59*?h(Nux^mX3zyYYHAUWUYKn9!=^xApI5 zYoc8G;<5;ny*S_xyqc-2>cbK0dIsH5^*b;RFE7eQ(A zjun;5VtJ05TxrkIp`#snF`-5Ad+eVHv~_;C$nULi#LeMJHDd4aNA>tTiY`fq4W?0i z0t!cm)L^`>@(|oW6wo0Ddh;342{PeDD$fadaCcftilTYD8Kb|~;F#xP=!E5|g#1)L zc{wq9=|5k8pqo2N;1#H~#hpXSI(S2s(tH%rb2N33=kc!oQ&gHHlifEy5Q>%OM1d=s zLbQRoFcdy6I)2Q{2mh*tdGEqEM2pa;uO-4^k%tc>h%P9(*DaK4Xps0jZ6!NU-ZnEa z&f->?kZF`T0q{6$U~__ zBqTy8sJ{c19^Fu$XCO`+9%DubjzGCeLnJKgajnLW$~Dme;aOIRFwLk7MY>b`<7C={ zR}E%Qj5`->m+hIRTa#Wa!ikvK8Bq-!a=oM_75(t0zJwRRa|Yb>(vNQu2PlqTR z(Cqd^DLe|fT%p1B_*F^CGWQS>GmI*cKxo+S3ELs5!)$<)AZ=s3CzG~c;^}eYr983kF)t^0(+_X(KxQ4YgF$LQ z_!+ga4xPYLMEvDkIqMm=5V~Sq8;cj`X2+KbNeC6@x5Gtz2fFC^+)NQXSO#zD$&j_K zI)crYyH+@lyj&M07o!cr<0rxtB(>^>3scnJZFnlIq~(*dSiDNQp8Cgm-bXIHGJH^IF}=h+ zXjZiJy{nIn&tt{D`H-CuoTZu&JZre!!&Mcno{ zjWB_(ZZP6Ye&90N2du{8pT-|ySn%U1;--CY06^F<-~JZ>{6B+mg*f=1=Re^J&w8<# zAOD0ac!Q2H97(a`kmStdqXyq@_z;C%;Y3_QbX6KrzMfVNvfr>S$i)f%W-AJ|e13|a z(P3El-RLA+K*XDVMmLNd7_$GE8~=tYMu=}={%P1P%ts7qO!-k0$-8ofq`AgApxlgZ z5kBel@+!Tha+V;e{aMe3xC%)vGD6eLZ&ys`NSf~tk(UN0r06TU>>a7ZI>>H+09F%V zsdYPSbQ;Y2FB}@mm0mLs@4@WQw)=)_Tjapnvt>XxU^wCDRd#Limsu|5k<+~qT(itsd zcmedgc9oxW#JwTOo;n$w zPVB?9Wc6P$+c^|kO&qmrg{vThSCjg;nUXKUlS0pZh~|gKy$izH{0*FsAfDQ_D9!cBir-&GgNrj zO4@Nm$`OqGBD36=GtFvVs7}7=4Wq>$crVf|LW!Z|ldZA=7O1BM4v}1lTR=`g1|1=< zL@l%{PNEj*lRA0q@e1i{49iL$*A4CVWE5A=ewNY%z4M?+{}OEP8vStt!#9uKHEgAS zB|&=B{48u!rw>a4*(#)b;j(nqfLBrn9!i;my7o^!Kt3RSHUz0m+K(U<0EKMd<>xdV zoN=4hzMe08Z}nU9*tPW4)4k$md>bKRntB%VCW}_Iz;>4gxJJQ}bFX;0UElT7x3#mf z@;^31f<9*c!GYDhZ~!y&2J|J*38drL6>MAC>**U}>up&)R?))QZ`YPjQ(9QM@O%iZ zSZ<~mP=ccvA5Og1#h1$%#^!xRetP(rnXFF&AKj0kQ=YpQU*-`!v;}ktWqkzrb-*4c z9}}%Xn(rj8qc`Cfvv`|@f`M}Q3$#g0rG?UGuexNa9~jGTjIyVEz{U@$>PdE^Xeqz^ zO2tJ9!J|+XI}G8UD=~FuRQ~`&)NATF(5qz_WIq9eXZUF6KrZhF@7u8a@KulXxk!M|jO6RI|*5N0=!4 zf8p2@Wr-YCP?`k{0_gQ;U}}=wiN|=mVq3w-B(d3tFNx2VNWI9-w2l$EP%94Jz^hC~ zPsGe-qMiTlcMw!*rFI;#^e98J@=7OZS-|GHc0IFKiH8ZZx*ZhlJ}?FXP2nz4}ghPQQzzL!O+jd00fo38x(JMuN2x5+Y38EuU-O^cHx(Pt zsa|p>2`2D;Cm7D_!~`IY<0-WRBskp><{yKbYwt2$?XcHI-IO$!#5Ai%l&Hqw97)Dy zEF2C$)gK+W#x(!tTg-ZL0@l| zrB;Ea^B;B_i5io~u$@L+yNy;YF9Fr@!%G5|f4fnM^GU_Xkzf`*=PPUc5CC=t zw0@HUb6!0Hg6(-X=WSEl>c>u9_~JF&*6(d0H*=}0_j;xf_2W|>u$BcBT&9Pw9vJCD z_ne;QF|6V`WMyI7`$v0xJwZDVuo9Yp{8b)_re+wRoyje|>2Brz)rAvfWD9O=Dhrvq z@2@iJ;dv6keT?Xv|&$6tEW zcYUCovv0xY*8jkVuo|8cFmB@aJ?oOrHRPo7kJ20Ud4sRtn{n;-8hY#y&q!u}4Y3M; zDict+c7VJsIJ;b$;z@LP1Bo3T+QZM}l{AJxyw-jLhlcTO?mkpva9?>UcJ0r~vfAZR zNn6Chsr=yQZVyXaJS?nSxmej&Eb5kUS&N|O+9ZE)M?C$FK8x*6^U);=NL(VaDfFX2 zWs(1;$%%pO?D>>X4UxIK%2;Mz$-T#hVw&Y`9m^<=RnHMSa1QSeU&*)Qm_JS%Q5MQ3 z|K1C^RL3`w(^C70RXA$POE=7(RYJc(GglVEaXN4H zyQdkb->y6_m8wboJvN@?Z40rt!v(Cp2M}ee9SJH{Ak4;KCCPp~Mi9$8!FY5rt7RLq zll zB$j3@`_J8e`JY4OUl~urZT5R&dZWH!4^T#M3^367asws|(4SHr5REh}L_nSj!YKy7 zat|hWIXE~|@?L2)GChhczW2NAKHlV*4C3d6nv5~7sR8eT-@`jRXRYv6wFsZEyu`(E z$PzK%I+c}362ppW#_|XuyXo||Ui!y!1+9vWRrRfdU${;O&oTyeEfeY7F_qoYFWO1^ z)P5;+{RoZ`Hc)v!9q$oEkh(9A_~Xoz%-w$RBGkVQc>zrDCqP^kprpI;97hF4@5;cx zbksOVnD)ylUzI;L*xK8s!LdfF(&#H)_M5z@4qXg-t1d4KAGzl$>-r0VZMj8`RyOR` zlbbSg6XR5M4|yef5ulfV&k&LVs}*3v%cN8}ba%4s2rE*hStvL^kY#x)mOyopPHTO% zX2fl2sD2P}!Z&^M$=!eFx>WzWP4-ITAjR{WKS&q|)Xg%FL9|ntdKsfJp|zaCdsk3s z!dpHtJ9i=TKJPV4{R-x&;M-KP`5r3`Ln7Li9HRF_1hb^O8jK0z?~LDG`U=GAklYNn znuGtDPh0vMu52X;_|L;%zZzG{8 z<~AmA_+N#iZGS)AQ3?qZK9Hu}5UKY?{Z>ZxFpe~}BV}gSMYOW?o=FZBoR5XLU@Ll< zAoDaWk~orRuV8_~Y1xOj@!BS@A2mv~EYpB1_Ft4j0iFLsXV6^YBg~zB1;e!d;659G zn{ufX)xmm$;8o42RC$wo|7gf50MjD`m6OuxYM&;HX4ymxvTyJ@DJFd|tq4&~FzFt* z#|e_0QnXS0VO0Sr{{CM!5GvQLu@V64q5&O?pwMHiIhh^5D4XF*3PgslP z9F0`GJR8cleJ>*6M9uWtjT{*0jo&16L>#LWZ=fh4pI4$x$Gj}=zpXM7lLP;%G?*OL-s+d!Y$;4^rcjD4(bI3O??5l z6_?Bq?o^<&PdJvKRS zS$9;QJ8VV7X`mNz<8IlVm>6eWLoSot{cKI;P{Mz0!ac#hWkLGFLT!)I7SjsGlZJaP zlB_S_`|}1)rYl*`9JeG zyB%4*%D#=~?PUJv_y7%(W&@}K1#IVhAPF1TJ)qh#`@em#8h1WeIlCEZ+fuhl&`j;lZPu`I<1kv+^ei4ItwPR_;`do ztC}30_V!GrFRJ_PL8`U8IK02dr^Ot&x069OJV_k95Gt!4R$e#=B{;&%OKqQjs0|R6 zwO9+EWgC1-F{(3s zP;lATK9{k`#=TXUpu3Nyck_y(@U7}9E_NCz+twySO`q0jAJH0hftNaz5FNA-O9=)6 zH8Di3g4Mw1R^opQ8Tj%>6U_IeQRp`ZDt4U%cOJF9rEWL0Cgx;hw=UTI;yH6sz(APA zZ|$WkGWrf}GG_rt?R*<{fYLqyHIFnRHbJ&U>~Hn0c3`5SZ1)1GVAbfW-8sh#Qkqhd z&+`QPCN+$*f6PUf%$&ZNi@G9loPJ*ztZ&eG2aWzf={~_{(qoJVnUgXD%LXrkgBq-o zJ_T0TW;FCW=H=(-dde57TRp7k@2p*s%k#IH7EChVGBe1K>f~**rX?SkJs6|a4G48UsdI%e5o59PqXSzM*Q8q2>{p9ZT;aFG(sc zVt78o4Gy&HOmOwbe&oTCCIlmVs=+Bs3g1@r{Df?!-L7? z?2Samvot7E$fXSd-(V8C>(dwuYi5CNj~pC^&#%9^2}Yl`HQkT$kz&S>pQnUFKtNiB z@uUc2A#OsBtysa^8afYQqpj-R5O+Hcw@6E3+q(3aS+gCgU5?z7t+=rXKg&dt>p}?J zEjKo_ysxSI>be=8KMzizc=4(W9?cD#R}u{OG7_--gU;(V;6ipBC%l8${#`pNmenMT;_4xQF-_Sa4G>W@KBR@p^g@qxMM0Y|o z17H3Y^f4iCa7o3ez3pmXPB$>NVi9a?Nig;VD1=wI8#?PsXaf=Fy-{p%DFj`HVQl5?v`<{F*)<{JI{yr_kCj@so~qca5r2~ zbvTNzHGep?>6DWu(5}n}7=`W!jG93YLP2CX&4}z)KeRtg?xOjcYrVdCOr%4k@{8d^ zJvoirzA_0yOxFXSad$d3YWg|l$OgRo`mAB~Jt(~RKE3qsotzTT-<}P!k$~v}g8*{^ zXq@A%fL+1P_ccP8F>usgg7#7i>#5&KgXY%Ote?%;JkW7Z5SLh?70fmaJ0(WVLPj)82?%jOB_02=4a0;4h>>U2vv-fVQa6E>t z*!fmLXL4X+>VBw5?-!Oj*S<0Ybqfu|OYHCXA|?C8$H^W}`AG3OeG+<8DmnT?WHY{> zne&l0lqSA>4(Ex^@joRGQ5^R90n=Wxy+Hdn{nh?(6C5veRY^+HE-0DIkj1~hHJnOY zheo6|_CL&EyI{(Z&1e-}5nd9oRMO|^hj2hf1B4W!Vzp_L(O+#I>uM2$JLVG;4vhgU z?5u={kWe5}86F@0<%ga{8!qHjm-c8S@Pw!O?ow?^i#`UI;7HS}2p{Rws5sim&c4CY z*;b%RQ^;2XXHWA!_vLHuSY$?DQ=jksUZCO=#E@m69$0{e{InAeZ0B47b|=JO{M(tO zJO5FxPVUQB)oDEaR%900HByh_Mgf-|--~D52b%~l22i{`-l8DSKf*S@sP@?QS|G~N zy5f~AfP?y10po9k_$>(OE(&Agj2UCmv^PD98s?E`uU|1;`<{DsoIR)DU^(FK_bJ}<*&$!pq^&^O5@8T0u@GGMfIPVg4^#YuzFHW%qPg7MB>CJo;; zM};&#U@VwoC>kMKnE0L9l~zqv&6+fA5Y9qAEXDFs9Z@CBtg*Jdqa;|dan6T3lV&Cg z7M7sL1)>ugx)2}*jEigl{Xe4o?InF{Y|OGnN~Dq>?!(;%z4`X4_^_UMVN(QgI~+7A zc3@HM=zO^GeBU{UAUnn?;6KBQMeO>r?vr+YO~o6&>emgbD^9dCLqSB851%$wZL9wW z&;1*cNEN+><35SNT@I2q_>rF}dK~0EANCGtS*yuYBl)>apc*3@*{`EH=3wtDbS8w? zRbrFY$N9!p3iX`t{`~NyoVL=>DMdRH{)igo!~f$Kw2yD?nMMEGpa&eP7g>ZizJ5%C z%IgX|`(M}a*Au-Q`6w>^LVb3fxE-Mj1R7;O5=9jC%UDDrXJd>L49iOTU+2fP5qix} z!2=clk45pX_kZW&_6Pn)64%1tZ|naR1=#+tPXJ_~FEmKkqB;+JCf41jQ%z2#2(6ka zV8jY~>?_}UIFIcjw}4LkZuBYgz1~4-DWif~cU@fWy2SJQGU+inUdzBy@y|T|-AZ=4 z+pX+_^`-{CNj$Yr_L2J6Os`O7r$KGsmubc#{)do%>2K zf-$S$V;&^jOavO)b{US3j?XI+}U~4%FRdc9M3->T8j=g6@Kcj$Hk_~45zLarnKd?fs2pA zb>@8S#;Ta`JJ^W&zgL903gtUT^oQ02&<%nt4iigWE=;la*~N2BjHzCE)Arri20!b# zLb=^=DdVumHdD`56@no7o~FbL|RLu^YeBsf)w(ky^mVkPk8+L zNcP8AJUh0YD@dn#&6#}|UnyJ$(-yUdgZd`G-ZwY!_+*{%*h73CJ}~>TE5=Vbfb209 zBMk~$3+fuX7T2ErbQX1RfrGXMy9Fyq*V5rMab^!iz<>Y#LVi)JJHFH~m2GCV-jJ|L zHm(I%-Waweyb=gd{X-C^&-JHs1f+98q9$EiRx2zlNw`)mi+dCsO9S6}vvppQHLU4wyae6S@GonpM zE!YVdCln1z#8>;a+$e41BoCFXrg2hvkJnCOofYE2R@epM*gSC7kHy0UM9c3zE9V0Z zBN);2)G=5ff+N2d=_IRsb8ZjNH=N@VdbtSOjZ-jwi5Jf$phh~MMZr0Nb z$1(Uodss6Gqy-xWTMZcPUoa$R+lj$t9^=oCGOFF+aU1Q8vf;T%M7FB$4 zZ6M&)1jSzhZ$}vgCk!gU@mILHY;8Gp%Kw>l_{i7(Lr-yx?cw6D&|h}hFcAkAr#lV$UK*cuNS@G47ppe)Lx0+;YH$o5Mv0Vl==4~YYh-L*a&Bv9TvyNpL@b>5qV>c?Z)Z&+6I zP@YR0y+^O_Jw;W8(Nn>SY`s9mKE^(%HG{bTBt&Qe53(ImF`O&wRP%A35G*eR8Ia&S zcQd>HNEQqGA@Q8FT{YT4^7t>orj+jL-Q5lXVX5w7Iv(WrK?lPsuoO!4QLvvS*D&nx zJi*IQQla6IK6x+080fs)qN95tzvG?aZa@Z?GeS73QPp`*a+3bBr;r*RSs_!+{O8CU zXnu#zL2de$Sf*XS5e=Sp>mO~iCc zH%$Dc!bfBS+jiQZ^mok3gFNlAO2SC%8A8p4?NX!4Z5%xrGNuq{@fhex)PdQ$D=6oP z6NksCc)a%BmNjZ}4&Oew$+U5^wc%UX({=2pY;hw<*<{pxEZwrK?v1^t6$UzZuPU51 zGRQVtHs47E(Zc2?*#QFHlDn6;JX~;}4{Ic3-}QOO4ki`Z^83A-Cfyim>#A?h$TB0m zdJ891u&>5`)Z-#nzRmeN!TwK=olEM96yc(|)3utY7)P!ir`U)Ph1MW`v zWkLqz@b0MPG3z)4lAQIjj;0wx7YY!#mQ5LV`=a^AvvFR3jwb86|B605vQs0DLDf-i z??OZCOIk6zZaJcA&UUcMw7L$^Qef1gP8U#39dt{DsgBFH^Inz4R4VPK8cM_UyNbr& zB4S8*8rluI*=MAi7stc&^pR45g| znpF|3TTrae`U*ox@{nVp4)>UV?2D7WUC>7Gd^q3ZTy2-qO}&c3q1wPThoJE2@Lmzj z7Mr5Rn<0(GRV4Joxx@gl^InXo%Q%xJJESH0I&+XQ9rwR? zPU~R1NG%OlTKMe!%#@Wzq1pVZIFVcGCTh5U{7r1zek*a4;=cLQ?osqWn_Jv9N$NWT z%aVol82{?EOPq%S8UMSVaE7h}L1;K31$df!sOq83wOdKkXwM!L6qPgU7s!*Fd#zU% z!as)AF@x5x*PqMC=+M8>zq{Aha9LQnOReOu2CmMUIvbR(k6H$nt_EYp@4C`v`zIR? z(MaO`N${MXO)W|f;KmkwFXrSLU;Mmk=0!OR=Jub>!Y_u|tr$HvO`*Re2F(K(W;*F9 zt!lSDf#+p8J;?nn|4Y8Bf1_C4Gz)Xu1Yv_(#0v?A@kICnh zUy}x_pTk&mgnwVwS^TQ*4<<6@kcVzW0fQPc2i8Ax%p(sP>ijJncnMD-i|kn8npYp* zfkM6%qA}{g#L`S0Y20W(2KQ${hqkdYsm}GFPq|2HU?Xzcugo3SScu!-G&_HqY|IA) zlth7p;knDy`e`U%wWpdDP}Offf`#pH;Y*bDtqkgG?tv-!6-@+? z97TozNy4v3VU2@_M1ke!dp%i3`8PSt@z}NN8~ymj;-Ej%=nIQ+mH3?>Zw~ME|6#kg zi{6u`9GW`Gb+SJ+*R1!p^tCz83`)V3eco$U&TRXs6tz)wFk9f+Q-+t|gvJL+#DVF$ z#K6U-N8c2EQ`can|5e)jwhjY}sX;j_oFuWdLqREA{LF`l$y}eoT$YqcOVTCLRep|J zwfDrwhaOzC091u6{)0C0>zTU9jG(*-Ls$pv_c{m}Y zQzI>#c1)=?BAT*#dsq;1)(0T^hUnRKS;K2g-g3|AJ)#M1@@81;+jGVLN7`G(Mg6@| zqcbpccSr~b2ndoY-7O`dfI*71fJjJpcb7xuPP;4B#DIGK4{0Q$!aj!rNLE}yc0ZVwi3yFcFQ=+9ZcxwZ13W^;6+OSEa{%vxRMchc*3 z+_{|>XD??zpRsMb-qm>)tvucTSOwJo0q76UyMoc&0REzIxU*dy8joVaS^T@&3oXY( zD(7k1eHKlR;$=;;7(G?nTEEgl0*xWGwGf9znV3)b9WA%d#z+kOwfVd{t=ujzXLFdw(LA1;%i4MH4I+|R32@CmTC?^r2QyQ%Cl z>r=bXt0UBnGD;p@Ji@_Wpf~2Xb;CS|y$+aT8Ww|UwxW%ya_LAFB))(3eBl4`-GG+A zjEW6JKYUw|2vM6Z;0+-DNi!zVO+NOVI3;GvW*l)ozDGCjlR~bCN^sy_yO!|ie9uUJ zqjltgz(58b-^!!7KQ>K<+7uLahDhRf&IoZf`+TE;K`i%+52{+<)x$J{T+V%iI2Q6BLbxkwvn>k|pgM2*B?VIl z0{I8uLF*U^Lzh*KUCnIwxL~}GC>o=Pv*$+r}JTaJjX;ju-OBo z6#j6^908jVR;s73n+> zgJmq&W}PX{t5Y9x2Pi&Qr-A|88(bdl-6kA7P}7)OaOJlM~=xo+WU_ zO1$91H8kOs&{p_ZHhe6V=2ulncy}zm+f2QR!>@Pz(ZLq?IcDm+kLxfAQo=L}JLyN! ziie($^{=l?Cm0+|-retvfkP`MkT!<9;s#dFUt~w9aV|hppDykmalScQ80pjsqnAYz zQ?2uiWxS8spIKU>ljl>zWY@ELuY-y-JLO*U*05eiGSlE85dIEMd=gIr2YxeGNCvP} ze>8yne(j?tzF^j@vsT)0XmNU}X}BH9PtW=+np!)ZP_b#+|J@HJeWklTqP0#!%Tb9P z)7<7*#TK7l7P<7YNYR}w!Kdf)1Jp@?D3mvtTqpnB?}XB|uii0(3%-;sN^hQ0ud11b zU(;sepa)gZmq+%$;y!ghbYH~WH9f9>8A-ggSV^9V-Pq~Qw7xU_giP0#0|re22%iHH zcAg9>rALk(I6#M{f8DAE1~V+Tshjcqu%#}%b~17=7XP$7NFX(PS;_WBKHtU}nYX&L z0iVX;2fgPt4xt5%Vb7i5L?~+R?Ne*g*G7OgiGhLn3?$#fHqznc!b8~sN>s#ls%vVo zXZ0IcldiR2c)Eps&L%{dkXhY->T{7x?8$w7V)1Y-B&7;tDXTYy?pO4?E^5)exZ$Xv zV^D+#-R;=P| zn=;R2|MVF=ng<9;_%J*z=?V=LbB+z9{;~3*wI-U)T3(y!;Yv;#qiGJj+wnN9wWy`; zN%}Ifj8*y>t#SQ`SJ~ucvqPBHZX|9^RXi+>-;Z@?j2`D|kf*!CZq*K~B>C z-?>7kPO|nl=ueR!pIHo#po&2BjqF%U=&FkKGG*;WkD0Rhg)CnAr~42VlO^|5_8ACA zkQLxJCG4$n_Xk+Tjk7!yL}r#Qo2?FSqMVX)vrj>7q5*K58{9C< z>5S~CcFo#EtdoMO*dM_~M3km7<9yY_#gfjX6c7H0Y(XI`6K}i(6?LSL+SVRk(_ab| zVaI4?GcF$&u=^*1l>uoqFGJxOVeqcy8Al+AM(g&U>}?O1pPU&lRKZsDf}I8KpL@fe zxbk&8>p@r%%C7LaggQjnd1w5H9hFlqrAN+fo3oVnF%RTEBWe6V=&cFQt^zLqwP?5# zpbB7(0}xGExgGkb1ja^xWUDc@*nU1+#dDCwQaAc(BazFumRaj85KnqC%8fC5A;%2k z`5UGufuAzMNZ#eBIbq~al+~~n2}S)KIv@=`v=GME1bhG<(eIJA)qiPd!*9#ITi-2X zjm&xY+e88plagR=(T`Jabl}0br(pxfg_h{aXc)6ajaA5qO&g@jk_hhgIy(2E<#xOn8cY4^w+~nN{$F{KWjq zNn3#66l?S~u@avBLge$rPWO4nu2#8t>JOP}ehM+=c3kdbd_4Gum^Z0-uODPq!-}Ga zS3tpW(4ZgE$$|~(tCvlP)D?<8Cn&HrA-f~6_g`n-=UJpV{8?jW0tC&cJ^%MK)g<;-2@Z6Kvpc6H~JkEjS z^oU=J9YDADXx=@r8EEJlvKYlf-xA|*HP+@MB;z_3i=F$}Me9EP6-z70DsogtNwG04 za2jf@ks#N05c0<1>lE?euG^bEY@nvzC;~7JDUYfFej4inApx+9dn;vr+5$V7o0$X@n@a_%XgK;G_WHi)OX-AtE|JIxkZ$~S@4(LCc`AV(vI7)07!P0L>lM4(-1Y!k` zR^hz^gF+aru^@2AFFar_tbtBGY+Kg8Z8vV?|FB6wiIE_Hp?n)-fSJ!M^%II!7`gh8 z*sJz{g^&0TQLr3Q92`m1CeWz7mIBYM!lXetT z1=G2!PRVwPafnOP>yWUbyA>$G=K};3?;z+gZ)$lplBXc2t*WQSULYI z#duAhff4YJ5(vsNu9rQC@oj9NDSBesU>GfbeHiLN>fFcKm+q8RFXb=u7*Q}2HMd@b zMTed&IJ^;o>u@GqNY42CmBty?(cu3e?tjjDzRMek3tZ7RltAsP&)oWwN9LMga2Vr- zrTw!%sCyDH$!{#?zXpC1_Uv97o^;&dJ#H)2>99RWA;R-&;I{f*@iX$WCmXNX`|ZsK z043Pbh1K7Tn*dLc0k&!iZ@2Lh>iyn$hB}2_=lHGV8R{m;RQBWcrTf0#rt;zmYZ&$>eeL_C#%x5_a zOIXWeKjrSHjg_Z}`<#5Al*~_DE+d{zYb0x6Y&dp(d%ZFAU4dAX7zzG0yV=*_H>c!&B4>7G$f)of0_^)-Sw1gLx#gW}iPce6)gA`|qb+iJ3({Bz^u>&L}kh;V@cTIwR7d zABRHG^F+GW6b@uS-J;nB{VNCpTO9&iq64?V8ys}wgIg>E8eQuEEYoz`bj7#42Fv$s zwK2~Bj3STF-PkJk9^Kob4?0~zZ-47%NQTnVeMXIDBIt`+m$__YA@+8h4@5S*A9$~j z%r7bGtO|S(=p~WD`@7Ay>=a0K<;C$KN&1e($}%9$hK@KmrPZ*`yq zQrBb^_g?&UBgb5{(QrsO1a01F<@^=;f*P~202&(P-nF(4c~SVGTU798fkr!N>pSjB zbYzm}0Y%vYKSW>3nIXa?O#tVr$b{>zL4#+5K0WpJNuw*Z`|30z8OZWcy1r+ZOgWA) z>TR`Pp6}M7GS-Ifer01?M`pccLJ)yQ+!}tuffxs7?W_WjsUd3QIfwD}BQNw1gH}Vr5I^ir3qYVjEJNjkdf?@`?;K)9u`K*lK~H=Xb0X zy8m?OetT0@l&X%oQd-eNs$S!kjUsZL=L59j5G37#NXt)O zAovYD#&zIMEFJRZ-w0O0h4WMA=^tiTS`DdKeNr#bFDh9ms7kce#WwfzYW_%X!&jG~ zkdM!m`W7E;qf~je7W!(JV_?Z`;JW)^NvsZQu^?Pi0cRDCT2aAMKSA@OdliBW3Kd0n zgtAat&9ztP-+pS9$*SmL9B-1pCZ+mi7%7rBaruV9{u8tcQy}`!+OxrKZvPP_JbJ_| z=(P|6-*K>oZhTa53p}EixQP@9Spb8HKyxpiP1x3JlGmK7;60HVPVM!BkTw z10k8WR;Ll(20#+h{0kzqiryFM>V%Ux|veWzJS3liRL2Dlq z%MKp#T-UVypHcn7ZW{@Gl;A`GpQ$U_Dr61|P_fF1u|DMN%Cq9>DXEspD1N0Na-jk_ zYZZ5fpGn&kIRYWOxGB5zkaU^-)WS8z7!&#_$H%mLkIIQMYRtUF@Ob4wrd3rCyayr( zWJ3JhCs~L8lar|C7dKS(e!`OWc?2U8vrzkdNk`?b$xrEUkIgGFLtIYCw{Ke zzKg)h~p*$~D0&TqzVqsCxF;5FE3 z1zv-Zi)QTa0F@&(&I~S6#&w}lK#le>qNLgRees(Q3>l@Zy=z?OU!fC4B)WBFZEJ`J zDkbXkirpjP%*c}1bVhr|`Hqpw2VW74_vp1ZD#!}-2ctD>jl0Ha?MkFDDjVhKqKIa9 z{C-Wl_A|aQz*MSqv$8iXI}dXpL#l(!k%^D-^N*$HcUxb#wVW|-P79rvMRUO~Q}rH5 zu#G~16;g1!@g3<~-NkOcmh0p4OC?tb!*VBB7|83{9Adj8s`pDA1B z6Yiguv=d#&Qhk1L)2_=y9p=WF9PFeO7*aF;>fdy~k-L`DC* zBgT5de8`+Ys3<&Z_sdeYg34?P9TjQGGMj6v!t2uj$wm_uxAy@eyvPdL#JT-o)L!(~RLwDEHIb7+_ z;{Ec$KW2c!=4~W#Fe`wj4mNy-j(2p1Q(MTDpGW`san=@tYp>Pw$eD@ZM@i4!PQn3V zBSanzVbqTm#`)QNbaCaCiz^-Sznk~Xy@sJ1Od+CtQfV-l3&!*TPtKlR%vOY1X3}vgCoyPm|CCSA@c^~8W0kl`dug!!`Z{TW? z@w#UPd4K!jB{B2TF-~tVnQkQ_3@Pw$cRL_m54pMoob>jeANiC}f$klP@RW zb|va2^Bofu;ziZeIXdLoGwkFtIUHv`bZes&Mqy@V>(10|iRda)ZF?tknp$hV|4r`)Vv&4pU;`U(8d`*cq&h= zfvzU%&iFNywQkjEO-!}m;Y4R7pA;7YjEdrKq=gt6 zqF4h$^ucAuk-0}ZGD&REitE_bFAz2Q=fVGvW*Cp((1G^rzmbQN+(3Pj`;F4|Uz?Ye z{9B_SI(bg=1}pa)@Q>?-S)U$Nt@UYtav19!;2SAOAS+>~H{IdYOCpqwar8ANIq$yt z0GwtRAFAAh9&%Fty0;fIvbrogS9tF=jVwOt{NOQNnkl+Y;Z}0lAi*IE8(NANyNt)y z4PR~-5i6-3a~^Q~ql#U3H~i_O)WyIzng7eYH~!L?qI0-JtKmI}Nvj04G>G5U}c^{R!^#0{meS(92 zl2r- zdK$Vnd5~f3GK_vDHWz68M!gGp<~)MQN#pTnt9?JhsiiHyOurfC?|%5dWe3!rKkF|U zxDQV3)(Id3|0LkBl*#vpNlB&0@b)kjx2ectvsHuf16tm+=%7MkFPk^lzvGCAb-w>_ zZMX8Gs?*0)^%wK6`=RjkU+|Rr%1cI}&Lp+K_4IHC@Ct<!t-(hXXXNu7%N)5jJ$w<_{jdiSZ*_C?b;qJGkV?i|1+_;_XuxUUEd&v|aT};} zLW+RfAc%4Z(g>Ue@CJJD%pT%UN)Pl6hnnnK;WxpeR=NSHzD*1>(e&)WFMYE|W#l)L z!pU~>xO)BwV%H7R_Lx3OAc(O{B73iyA%f&X?F80k2m<55r2ob#i2!dbfLamMV#@}h zzx^ka2BQx-U)K71N96a}e8>E=$e`5Q^Pyoub>MpsCPO@wNd(O>`b;+T?L*oD&(U>x z3t0tc^@ZX?p*j*R{8M%?JaEB&nWpap6s!sn@(FC~ksAndh1?!TDlDE&4>ZQX`^;vm zDq3qLw(7BK_h!ni-=I)huY8#2yk8){O^lWyB@p2)HPACTj&v!PiTfGz-q1jb;awjp z_;CbXCZg_x1cl~E+3p>odvE)6$Qs^`a#sAXASsHVCF#xIXMfy*6|qdSwalKrNvK+8 zDmS)hrtL&_zkn;pD*j>7_!h%Mm(J?;O>W{`xo!lQ!nY%%Ok;qV=0NpHH< zVH=IQ|68`Xe+DtABW`R}PTMy&t*88kwfWRLI=g0&(kuP~j0kLs4(KigX_5un14zm_ zgSeX9I2xqQL?f+P!HT4Z=s!xSA-O+AyQ8TewlT83{{1j|@)%Fn%eE|fMRR6tWshab z=EyX-jZ#Q829K{20?3E_7GN_c-c0#BLNDr`g%v^Zn?2I&jN0ud{ZI1^x*F*5MqpB0 zgo{Ob^+g+x?(ulb_e1EnLy?=FY_VMUIA|fxGa@Td?VMDk!{HoWFp{qM&cB{1DBuVO zG}3m*Kybk!4*GkDk+f4h)Deo%rk-g{_LtMXtdttJ6d0KGaJ*_s(!-aD;BoPoSzCoD zk~}nN7%K{2lIPH|K{P8G;$I^yzmxe9o~984g|ST`4MA3P)ovE{d| z--VsQ1*xcI!Spd;WlcZKwPYre=5)UpRnF(>SK08Ld5*@%v2|UOi|+h|R}NR_;YlNo zgte#HJh@e1n>Is<-GZ!HlPZ>Y@GeQFG@sNl6!sYrENpwg4NbJiq3-I;cmGtaG+n~5 z*M5=7r;8(&;kR}*+f0X(>Y7IG_Lg-W-}k;9FAZ38e?|LRn(qMB znaX7t{yw0IX^61PJz#;(eBwdj!GGbpPtTkdwt3K~Jdn}GWXwmcl^DYnAgx}GFFe>3 zoek-YDRNbKNgT|tBJ!xUUC~7|r~|Bi8%a36L{xWd_0?VlD*(W6&7r&O`7@d$jqgg{ zvuaS`6>LYsF~e7nLg$%!^@G9AO5Z}ejdaGRZlKr4V0HKdHc!^Cm$6-?z)m%RJS}Co zh8u`4g4!0`8x1#NPSo4tLF^WEh|+ECpoay=3(EV{CK%L0Pk3DJOE!F7#4NVZWJ25L z%SZ@Y5UJKq56!po$M-{GtPwG>h^Mb-gNy|{!X+9u`7|Yd3O)w>P`GeE)EVb{On@b= z-5%U~l{`_~dgs}EayY$T#R56q*xA%4i59&$?~BE?G~$2~Dg;6bXR4~s_pjCNJ4_0e zXzFRf27GDMY!SeCIy}6vygDgf=#2%BIX}gQ8lfbQIr@JEKY?26Rv~g~XF>ycC7nomMfAq%Zye{tiOJB+NnTB^n!iiAUZ8qI zOiPK7pm!b+g=u+Our9r-VOjnl$1@+Iy$8?6}NDi`*L{qZa-^N^j$dW5RoX3=L|0jO~mSCCL2J&9+ ztEoKQ(yw1A>g{fxo@3Ynx%Vg7MX2{Dz@)>rBREPI?r38q;EpGmu}Jm0_|_(c<{vXh zIk?5ea=GMZP3cBDd8DM zkBW&^>uzKiZyMX zTHSr;QQRZfB}~+=GHT9g7ozB?fyjObE#{k%pO?T;v71?IY$& zqf2(VsO8-U&#cN1TL#vyID?Udmbx`)CHSY(;I3v%C&ve`#l=_`7D zs2J*mE$c+jsww7d3l;MzEfHoWzqRVj(vwA8;v5!ybYHdO<^xE&?Ei%UYL?*g=9o`$ zk<9RH;hjF%%e=ssZZU7v-<^ggDmlmODZe#X-lhGW%#UI{(u&t%0_{M&>m48*i=UEJ zcZTj*L|Vh$*TPKa6%uF4ADn}G;czAX;Miz1(BrUiJQSfumK4@Pe)TMIkpw zc_rfLTPVz#UUfH2^B~UN+5GlLdP?v#*PUT!KVK!Nl$LZu^=`~S!~Czz8x;hhd=P@o zJEf-urm94thv|E@1(Us2-SCpcT7vHoXW<9`vpa8V8Zk5HilUb?>2RkJ*v8j$9k&`2 zs?iNh{w%SoJ&x?A^yI)FX%8Ww ztvUz^!6@^haz98If8Vs(H}_nehNh>4AtO3U|A;g;ODNQzSBf=Kp1l}pMQ2I zQR!VT6_?Hx$0kX}@&Jhi3dUJNvP@JtCGf`GL|@lB!45(E1^>c)Q^*96dn&l(<$EEs_8QX{y?%pA{*2~A(*=&>QY>bq417Soxy%di~|1UP@Y6Q_vT=&z0Hnp z1&5&Nt2d?>-e1c0>54sb3=cv2!0x*K?A}0PJuL9~A!?jD)FWQMp8hMG$F8^1bHhe1 zBwc`=`o=zVxV@BO^@4c`MbG^04l!OL>Crt3t$mM*z20{PG8$*U^rePYZ2}80cG@_T z(to^JoZCFj?c8fb&?*?=gCMPYPUVittio;*%Sk|?0oQCif<4>^ zewt|nxEccN!sn|sgzeVuw|kdiPJCzRUcPV>-I0B^^F{T!bq*%YjIoBOSbX=(TCdV?05VDqxrs>pp>Z+5NeuA! z+j)oz(ef?Ro8x)rJVm6hdAHTTQ#HxZ`>ZSO>nbdBhjwGb?W*r-qysK`gvL<(i(<_@ zd-e$skpSIRivioq!vgV$k&)K5&CQDmD~$GFPK~~fdVwl)TSSyo3;L<0!@_lHV+|(T z=nK*Ns$9l+M;Jd0+5M_RcexM^T^Z5n1Xd8`FcDzA4WRa8%YE(U&W|mH**||~^3v-b z)>X~Y!-pn6w0MXkHdMSu*us3DwkO8L&RxhwNkptOrp4h9LYuYM9*+-xeq5HUZ&F_C zNDarq5Mz(aXJ5wbCyydN%V_w8jB^subo#wA$r-Ekxe&Xkq8qT2 z9vf8Zz$U(s^E8a@#LFnxpb-Z$pMI#&{ST7-aG6osKYR`Uy2J^c=|E6HM`$23+Vm7O zgr0-I+${l}@XOXr`LC|~puWlVZ@cQF`JvpdnV3jTddv=>nA|Eg!zPc;{v0ECI9DKIh9zfuxNZD6EVVa^W!m= zSZ_wey~xyW`>3llbz3u}8v&9ziQ0l*D2geCsz6!F{?jcKmU0Uh>VB$?r| z9U~9C&3ReVmHp0Y5y?ls!LyejN~=OZmP-i#BM6iT6Osio|LL0h;pII0^yrNp)$yPo zspc-TheZFD1LEGWXZ4>clBVJ+|IQ`>zQUs{uKep-2FD63#kiHj@mWo0QXYC3F(y4d zq+}Mv+dw)L*C+?>3DPUa<9USRZ@DIWZ$<*qTv+=X5Q?^sdR{*rD0J#t$2YOn~0wPvhg(vXaI|>}C^{ z+$(w@&<3dpw%SM`8kRERuCfJE;HbIDo3ED_I)mT86c1^X%5~C(jwKzGV5he z;~x(!&b~|G$L6r!)XAEf-pIn+EK)?FH zkLK=TeCk-hpqnq!%fiX2I5?ge%;#8;r?>MZkBPEe(2d^uw8!j#yxq~bI%my&=&p0s1zO4PtzN z>!FnRFiELueX-$WIV9Bwgf&`O#_#2?sC|@X97MI!8dyIFA<~3APZ$0wNmp1Y!s$zH zrc&0WPT1+>!c)G99uH5NfOrxA!hoQ%Envf<9@D>uWyI3MmEmc_E$HRz(_=(utzV9P zIhjtMOS0UtVtl;Ww|8u*f6%~yX2III>&j&k{^Q#44@O0IC4t*Hy;?baC;A87=0|)) zwmd%|`@}0)ASdZJHUS3qFPsOhfG(8(qYKw{cu#}>(FNiAq~Xq^(J}=Vdz7wI6$dm5 z63Dinzdvoz@N-2=i&1>myyNf$@2BCAT*rkXkH&(-wrRJpQ+@Dqk@cM>t}Ds^!PNig zLJQFiT__5P3$di}{XtoCO_F@Z#I0R%uC3Ci!&KpG127Si8IV{X@XRad)tx zO%T-UyYNnPpymOLDD>EGXuMpYIr6T%i2k8%S*y&T-@vY!|8TI24~jq<6$>p2tAMzG zk)?CYou?BvsdQFDkz{vq3?3vux?m!}3WNhH(`Fq4tkjsBw|ep)#oEQ3RCxMj4j<>tAJ9I`Fg~ zoB?O=LvWMe$qQ0@O9W2+7IB&9A3vyGkdv!+i2I;|<|~3l)?bC2E~r{vlh!}#Wef{p5KRAm^_$${)!(YwZ)Lkr6)_)G zNh4l@ZN-Jc82aHKAcJGZOJ3X?H~3$15MiY*mV@8gb+M-_DZ)X89bRQ$I&opOlMhgE z%_OaOdA2JaHei{pWZ2I$CaCJq+bUSrk|S^I@pe_OZi=+~$AjU4I7o9XTpXkk3?Fn( z7Whve6-oJx*fKjMlHo7b*Jh=Z_;dC2c$v{A4KnyDAm5Z!X2|pPyPpci77Rvr25O)z z-j2WL>^~|H)p1A`NLtFr0O1iJG8zl>E(A8F3kdd$AU!L7TVqxyL@2mNx;zAvDtJOI zI<2V$@t$S3h;#pG~AOvd>?r@)vr52o0pz6g^BPBqTOnZz^rJvZEEObk)o2cPIkF=R#4(z;=O4dEY9N6ttVpB?aP6R#UoYj6Ed^ z>b;^{+X+WRl)DD*{&$HyPQ(60C7$ZN#p~xi`1pAa@%@u9O07cnIPpgfL9H@(R&(}C zgxIg-NReRX2jGh5`GTAy5hKH;T0fEudxul;$~Z1&G~UI5DiPg-y&cWaxt~iW`RhD$ZwAq7&}lsVscI=ZR;9D| z1%KK`z`i6fhxHw>#uQSxjU}-)5tl2u&XthCwAw`|wKXg$!G+ zVM{y_gABs2(!OvPF)g;qV^n=cDKNa7KfRp7^LabARszfYuE@<1#e{vpJ52Uy=S|4>h84AWH}|bib7{jPa|E zE)#s1Vmf|xXepe*_?Gzd{m*E8cbE|FcpE6tWvF}>`lG!fn?v~Gd8oAK=n=Q|$?|K@ zEc)<0Hb2w>q%Np6k(z&n_a`m;QX?zCh>l z&We$re4iQwD7pCDwUx!O*>#z(P~&&5tT|vF>(dw17>+Qu?!LxU&;XoljjB zrhw*61s8&q2dlFe$lG*-9^tUOyC?lFCrZz^y6DaXsBPr#6kbryv-EOaZ;V+NbTx4C z86Fj2u1us`YT$=d9-(9INC{CtH#zV#-ZXM`>gUx#TDhsCkWZu6fwYtV!T^bSZPKJ4 zzbr|(@xMXOdzzrRBeqggY0Y(tJSV#Trk+n*y&7}tMLh1Lr<%v7ZtKi*L$2BpuGEK# zm7df%rBCm|!G^>TXatu5I(zA&gTko-C|-NgHwj)@w+4nUo(iGtkUNRbro@8_Y+1gG z1@*nyn0G=K7MD-PH?N&_dz&24W=?sYzioD3__}^pnvYf+l}85F8VFK?WT23*;QxCZ zIfVaL#h6olq~RsZi0x5XQb#pB(JLO3&37a-YC!x+*_e!}<1$pjv14nb$z)FvFYj5h zQ*aM6_Ag(NKN`EA+jQmBtHJX2@yNo?@aX$seZi|wc7$?y1w%`w5&egT`F>u~mVWOK zczrjiEv*-Z)M5Dl!> za1fV^r8(%TkkI}d{Mnq4QSGBHde<*YNtbk~Ag*n#)<;Q}NXsm(xU~8>f9OUq;CdVQ zu0ZnJ8~ye?{0| z*k9>fyIORH9OZyj!~bA^D)P;+C4n~$A%HWu@eARH#hO@>u#zg7k~u2d!2+^xO z+MPJ;x%H7y%4I30YZ>a=Cj@c#OEniv&O|AL0+w5J)TLO#+QDJ};w;dKg{8W~6Ng*x zAIOd?jJKpj=-U3${zNrAUf`CVpw}qTD--R5#q_?jf?R%8dl{+I6MHU4;WUqG$D-kr z)R?Bs!>40e4Jz=9cohvYF%OQK0qht0MRmYLQ2U(QiRSZ99p~+#ox3C@>3v4`=Zecs6Aq zSlrE0&xDVb1n>oH133NwCFwCRcYHm#F6g0)!N)(1Gi2F@0N zLYjdGE{@7Srj`5E^_PFkQ@WLY7dUmRLvKhr^8VkR|3^tKHxX&P{!$VZE!gBHpd@SX z{_9G$UhrUvb|>r40kU4@-XZ)Iykzh+^G!a%i#*)tX<7vNc%qe}j@ejVN7g#E0lLVpbQ2mN9j4 zpjwcZhb+^m;dlj>exVJ-&dUuseoY z+&}zOYSs>jXiBOLv$8s0GR5L8Zc6m_>AelpQ@IFA2&lGYk;9CMZ0z%^%$cGt_=whcyB?6PB=&2l3@IVzy!P7vdAi} zZyb*tACP{+8gg=jcZ6UkC2kDw-C6`c@dd8FER?o!d6hYRik6yHG1lIpB}tPeB~*y6 zmoeCI9v!a0yr>f^EaSwQSeo+M*?0 z2gBhssXSPC2gd8TdwtKHTvWy>BeB`PoKPj{iwnsq{3^d|C*3c5DE3rf%U>K;0euUs z0tBCF36R3m8=vD;N5sM9gdbjpl+#KI6QOyWqv%lh>{o6nX3o)>bZ%@`F6pWT22nxN z4M$@vWX84-pF;!ev4x1$)${^$GC7buOIHd6(ESQGcZ4vkJXXJOeL#vsX)D}`HrlOt ziYJO5Jv~(OVH(-;PUV+(E#&&ylW{Ew@3T9@&_vmO8$Crf$Gmz#BqrFB;Klo7m@!+!C4 z)8}05j#%@^$(&wmY57k_pQ#7c+(MnukhKtFC!~gZhPqwrwb&nsFyNzo2Ho#=q-ue@ z6}%p9`#zDt)-aoWZUBcHXlC;~PWnUXqb+KkBpVD{bT_LNIl2ejs#as!oJB4;+3CB)~ zuPBUStkEmC)@%6;!bOQjVLw9PCEC^CN+yA_f#6?|Z?^`T$lO{ix+GJr|E~4BNeT|R z{ko9n%rdXVzQ%4`Z+9SBzHwhh=whA}E;0(i&Uk_{9rN+Ev&M^I$Mvd&$;FEF8w(0~ zOB{*DsSAboQGg_1XQP2M4a3{<$q*41GsqCiUgYk~ER9L_&AUULmqeGHd^7KDZ!V>^ z%B`F8q0Tv~lV&JzlYLcotk;lMYqD^qFjV5QM_*z3JN{25D|i;jH#9=}Rfr04Eb6}w z@K8Ea0gmkX$Cz0KQEK+qfdL|e-)API)Xq2OJ zU79TK%hsqyN3GvQ2X}i@%F&0paQxMi0>PxgiF7$d)5SKsNpC`uleR`GX#LQPMkG^< z_~GQt;PUbs9jZ-RuCmP|`P4It#W`p#$fxPCPC~1#H}aeBBs;C43XUC4ZgQDkbjLuQ z7CzuLD@ev2iE6>_2eq?6*h%C$UZl!`!{lolhOxT|Ew-6<>lb3VEq7N>Fsnq)ZH^#u zg-T)cB}3bq0U2)bw%(>t)3+at46R@F6s1}`^<;@Tn=7GvN4?!r(PLip%}ABV@uy!EOtBzfyksDT^H?89B+OyC@+= zqHBReF(&8tF?hbCRxKa$$#u2<8QR0MUZa_Y&v_axbwz?*ZA9e2+**B{{emp^87_PIT0W+AlmZ|c9R|k&rfzt4=K%GnvsOz z5BhQ@d*8WkMhotLf`rSuV;>dzt1zQ)Dqu|>hhbQrjzkS12li817tiw&jGA|*%?1OL5cvv z4x;)wP`>Co@6d>bEZ8KVS5(BTu#iYdRTohITPPAJuhiDmW~-&7=b#-Mi2Q-%GmHp$mzDw zs@^RCNzwR&M*9#-tqAq`gor203a4lGj(K#_)T|PDB#YlXBe~H3>_fQYFc}#F3EsN^{LoV$gth7yOWy2$180M_ z!t9;VW#S*@ShQ&frXO<_PXvC|KP2|jj&1DvSWEx9aPNcB$+5~=)AaL(;6dD_XY8l_ zNr8x!zXwogcpnfTw4iWc@QWa}l}k_EBBL_s4H(XoEtC*GNn!2S8v@D=i9z@QGSp< zf+8aI_z%s-`gzg=cMdvA9(_T=H6Z*caSuT84kBPia8V>pS-G62Wv`~I!=LQ#8HyY- zXv$j~KbHL|&MBSG^m#lmt}y)`P9f>y7h?3(e4Kz3(G4#1AEdIA)uEd9I6VUSAT4My zEDMr?pk4>{zx1eunBTm78x9|g`F^8j&Fj#$T{F%G&*pXi5Phu!$7-V2=~vzBgKQOb zcs*aaW!Ww_=0n>h8a*;X-5i`W8X8ZmQ(r`bmzM|hV4#H$+6+o?!o?q{4Llg7}1;!9~}f@NSw8zs=!gFsF}x;}WRW8724>PiZr! z1e>sEJ2E|jo@VgGJT!Ivpcdxsy)dFFdTB^@S^j?VSfbDCg*mU3b||#I6`YKxK>~1D zge$h8*ZQM-#iiXLi(sxVHm@O4B`$ebM=R_8YPXeeR0$`8H@o_FT|R!iqJ?^p>0GwW z00GB}Fh*IvyAKl0061ZQ0<=6TH18+OjB64Fk_uKd#ZN#5l6x}&a9Dw2T2ET1&v9aH zSBtC|77AbTJ9{$RAy2;)TWxw|y?`=Jv<<$Hv`^x zPCN=Uv~7-8RYN<9D-31!>yCIxDr<9aId|+R)JM}{sL);h^6_Ry-t^?zlvS~g>`T(7 z*91!CKN`^s_(Tz&d5kfXy$|fcvI}DmxVSdbAvN)6qq0T)r2{*!AvU}AF0|1#K8cxj zCf=|mkVib+?NM%(no@3MrSd)(^Q_N~i&2WetK+pd`ZB9W_6*(H4*?3r5$8E3V!Wnc zyvLye!w`p?@m};mUmE?McjR<^r57@(NuwI%KWwqS7GzNTX4=Mf+DIbDCF&J+vX72v z8`|g1WbG=NT-~z9Vdu5H6(sA?pJ0MPK?D^U76?~}Kxij|+=m1#U13H%shtWX>r^*Q z`{gsYE9N`giTo8JtApq5R4NQ? znn0i{P4r5T@5WTufyu3E>^#iHRL;W>jBn;dmP0SPbCZmesE^^ zVZ<#(@-j>buNAAW`~j1r7CYsg)e7gnXSl#3IN95$K;WHmMO}pWu+jc(B{xve(~R^} z=%4I5RWxmVc{k<%&{XwNF#3<&D|!|uL&qRzM#a$s$2x~Tq0F8|Pw}2~PhxDMguODY z0Nx@rq!br=GCJ^Kqv1;;zZGW8riVy?&zg%K2K54fH;~bAM7z|15Ps4A3cd9R9DiHM z+Uf{ZgzGm#523IMBuaU?K;mq@7M1j_VS*yP*3Le3wc&&Q!{Do>dWb`Q&(^yy)r^$w zS8Gb`J3OLF&z)7R7Qdm=as)MjHws6B?swCNLjtXYz{QN~_^G0j?oT9E;tsa}1~%CO zRV03?PoZb%#pfD#2Zu<0Ch^g7wl1SBi{g?Eo~oU?m`zV!(>1aK6es2;O+CSCY}X{H z3ZlPxg~DTSQxW8;_PS<~zJ7q;`L4`?FOFh7M)t}4sqNw^nW`A3R~qUuz2f{d-`q8|K7asz3KMS^4#`8u>6~EDr{XC=&c! zI`pVcus07(0bmkENYXc#r zf_mW->m=D;xrH@@CtfAOgj97>q1vtP1oB*52K>SPX(OtuoEh5f15X{~BI)O{V`0N% z?oxBNw6GD*#N{Udn2jLX1LZIn6^=i)4SLML!UT7?3H}R8K!F{jAk0q$hqsPd@(!ETH#(8!oOrB{njq0_B2N3-pl%DrJX(#_M zdw1tstWNOBFdj*YD*o{IE9LU%u$sZ*YQM{9C6Jx@ANO8m;D6nFxxderFaCA!l?PCe z7~q4~k3gJ8yYy;ur0|rwFxfO&BzwvDbns~xnXQNUp+&?wvz`O@-Oksv!`aUrSXRBZ zXr{`!qa~db9V>~+hWiXyxvhba*#C^T&0R+H5@f5*-Jp%C*GnsRc zT*tT`SrtY`NMLiJPR!I#=rY`e$AruP*{d>5ai&3jIRd5T+n=v`)aq#k2iPv=SHa}r zAI^&N`af@hKo<{UgYN=;JOVq1MqdJawgQapXV#f(cCi0oE|y=_uUZdLBkXYBDmvQ9 zq+H$F1e8+4E+$Ua!+LK?AH%!YRX>)prRmbScxbG<%Crty_jCV!Hvo#cV+Z7$=5so! zf&3AS1CuN9h%8wlY%0g4vZ(_H7io0PUBp zrp|pLwnO8AQ<|?(*XI$}x!%G@;I!LMMtH@7GLIju8YhXA$K+!x+X%YNFI;5q(^zCR zPun!dx42&k2I8YklSvfuZ`D$pJP&1A`?f^0j<*nQ)(Nd#PDvCf1UPy~4?Qg;7&K)O zhY4}3=8ay#X$|Z2J}p7iB^&MwUPR?%qu=KGRqMde%m%wseE)g)7lU;oS5us{J}14F zTZGF7*|F#c95pJkZ-TO*u$iY1eD?WtMDAEP3f=G`mc7@K)4Ziht@0H>2gozPCb|?{Sk^J zgPB3)u^!ueLW1~cC3S(d^E8AtSpxsFiOmSq=9#>xBN4NJHYq8Wg{S(ezfi_nCNY0z z_mjM2{20GuMjTm%CHsgO#V++Ry^F^?;@V(u1*!vKgtggkz}oS-LN1Wxe|`(zB+fst zHsD-Ip=?)0i6U7sP}CLYCY_OoX@w+jrjB*=(RCkxTlKdXYmGS0E4|6r%_8MKd_!s~ z3^Z{FYnGt71vCX@*x=$S{Hs~dM)d{jU@R9?-VIJsJ*I)J>FsYcO-*_BaC5BW%hPZ@ zW8c$v=52aC5In(iXr>fYrJ{fB&tyC2?uuZpTcJRQMCfVnj3QW6koTaMnR;jb)|+>d z>?Og)omWqE=ez2-oBO!##5C=4{al2#>s#DO!{rSo#pm{*UB~NtmO6FO%Ty=w7;Oqu zUSPvtk;Dure1>U2HOfG8Z4Qb+EuaChfS5VRjdmK6-m9(GVJ3ol15bs%^0fqiOQ1G> zu+dGN>hSifT~JHe3ks8>XVh_-?O_E?UoBVavIL|u`0lHkQ^oU-Pv}5D0rzMNQFiM< z6vhzTyAtZQusKM`&84cpzkmPuL-}O{y!Tb3E*nKtOzF(m_;sz2uGQ~^+_`$A6$5zj z;uwN+EBdcgOO`)rd9y@6-*w@>{Ui5bwCrny^X2*lYV&~J1$r5+@Chzz6rc8rFS%{2 zD+p=4h7@YiSFnf5@RkMUiIx?Bttsz;t!34RX-@AU*mz#dgR(<9&8yUvi7^MC`>@S! z5vU>H2)^ttGO%QU*Znu_KaOGJ?5=naCDT;wex0}~vc_+7PWnS=#mU=eC;A9&Z}{S^ zFWrQH^X!rP!#G0ef=^CSyyvvkOYhd&zVloQ2Zt4b8>NZ5>Drg|&6XXQGw&jdmoBrh z`gK>R2w&hZR(JP!OVGsz<1LIkaZJf}t@EcXr?x_ZEnVp0vp=Y#(3XmHS=3wPc>zY? zPy_8ZAUNoV?iLa_dWAbO{tJW&=WNKv;!;=;txu`gOS_T_`y(Llse zfjzprlRZPhX@GqhU4*>g(nu$J+w4~-GVDh72ZTgFN36Y(+rTCRb~M%Mx9t^klB)N3pSCDiPQAyT zsq>yTS;I4oAiLW~YZQ5GpZ3@IdH{Oho$K~Z694EKECOD}>K~8r|ERJ?MBgWJBI9#< zaZvh%h{Ho$=0KwuwLTTEZc#-!H2tIRc$?^KUXAe6nm8UoL9QiKrhH?YYWt^Tg%ZK2 z>-GNNhk%$tOc44gyA2w|AG`%Z^7Z4*ri-UP)m9H?S$=Z0@G-!5j(Ii>b%@RFY~5}) zIl^Hjk8!JY#7O|BZt(5i;w6>O^8G8ecS73~S-zO1Kukj)kUp+?dRC90vqL|mSh2%J zlg3AA3(OoyNEvR=SCcrB%)8;o$ck7CdYmW8kns#sRT~s>`^`9OXqSrwrXF_93!#n+ zezy=R62}zc-aD^RWJiJW5rRFJ_5o-C0#`SMt!4O68O;Du*>a%d^S6ExscDR9XY~g6 zT@Bv&*`=|BW18naQSjY9%xySMm)GD?Hn&{vmv-wL(ZPS>6)8<7S1W zv6Mcl@woMP$T~Bkp$fVxe$MDBOOfN=YN2b=e48YPFZDGLmVP$mYd^>KOQ`4zVZ=1p zqFFI`P?Wf#9Oo`oT<@^T?C!7D&!p-aeR>mA;CDUU!^m{*}AG+g@m z>Q@rtz|zc>&$tRftbsJHm?Pu6t^0e&jGx zv$sDo<|(ccOe^f7(e>`BNy2LYxeLe>&n&79Fk*10rA!avQs5thQNmz4p z5luU~$H$XdS8qu;vd8TvT3Fv?)(OE3A(_B(%!``{ zA^7t9W&5AwxSCrBj3uovXk8!a=stQc?Eno9%oBEHB{7D2%+t3)H++o4Km-b_2)g@e zQ}Cq9`c$yOF|Kgq5>7+E##(%P)R9!r)TH*;>*nbQ{MJuIP6--Wt{%GMrcxtalpG6l zG^jL+E}g#+7gvhR^Lx*y1T;M5+I_addkKR{=HAO41zhkri?(f>lg_O~0tRc(i zO2O}NgKHbE#?DgF?$Cz~(kbhIUH=gk>l-hl)8AB1Q5yifexTV~gD| zU#9=b%b|PiSa`#_@s^=Y6-O4~8*ehS2QeLvpZ9;iG)-6S;7=vb4)onxuS@Kl}hTpBpz@UA8)KZ9Gzk}v1yxk|g`!s8fjTnB%} z08jKZ?RK)VX;+q0C}}C%%6^sgGbmhn@f-*2CcQh1q|^45dzge zEQ`aJ$n3NKwAPmRfBdC?z1RO#7=BhajAdmYIP;M znH8(ww&1JD&o z7YG_@Jb+4JC4n*qV)+M9Iz+gm<9VFT&7YCdHz(|!;*AR}UY21RJ#>m(! zj4swGFFtn&-Ak0bBS{{YFkILJ6T7eISgLa&XbLu4UQaSUE}v&y;`MGFJcyh2y>B8s zgV>%%2-3ynF~YkYe%x)xrLX?gOqll5@gEV1?>J)#PiHrx?#3qMYk7Ia-d}E*zjtJO z6g^aF!ln{cVaD4^y<|U6cMju;YOUo#SQ}yj*1A3-tc@s}9#wEL*;qM#lyGtVm|25% z;zM|;ZOeqeD)fOkQg(Y@;NaVdYZ$K#dX4mL?~N?eOp71<8JX+GgfKjrC4@EMdSET$ z3}J1Y<_~*3kLZ$0VuXJRaaN2$a?#PVKk4>zpUuh+qP1;IDj>y@3%abgLpzciW0b2< zt9NvWyd#V^F4g>v+T{_}GG&0Z{e)|J$?Sq)AYId8gZEMWy%%?X$?n*k&e+_aaKrLt zSxJj@m{1CM>x+`o&k?Y^EqF(Vp<(DF3NvZUPDAH=A)hK!Q1bqtP%p9&g?i-%%k>@l zq7XKYR&vsz@f{Lzb8s#SdQRr+YP~)sp!R%`kET+b<4`9$#vlAr*e#%P>On$ylFQ+2 z>&G;cpOn%}D46wuDkL#c3mRc{79iJmja)iO9FgkoUD%0pEnSVLD--2Y@_4Apx{0b(x`CRk|C+eA{r=;_ zl`mHCBB~IQPV<6dPl}|Wu`L^KJ#W%{Jp%;iSP@$Of&L*v-=hd*?~)Ed5~U1iYlg$c zPZK+(X(#8cFu#r9EWYnlxaYmT`lc*UrrD$60PQPZFfwV(SI}^Dx*bzWuEDn=b}Rq# zsDBsByfZ8K6V8uU;PpXvlrjhw0#|?|Ds&)uCkdGljdM`}?c&$8zMb9^HCV+deK7q% z(^5{H>D}RG0#zMW>Tz|(=sg{LthYu>-Z60LgCCIj70@92RqRR#BGm?xcNMnus?hH_ z%&H*WKSZQ*)uB+J`0nz!sN7id^>h&=waT1FXL^*+CD76*vW%v0>m{-a6Y;E9_*C9s?F6GxNK<;dP?Sa* z{P;dNxclO_vv2RRM-OJVcM}uE@6z_kmtxh2n-z3eSUOZ^Z^8<#VS>Gelzk@O>}%*L zIKU)at1#4|0dXd9{U?EtWi_PJl?qY=_80=z7SuCch+DJn^#>dxCJKHRyp zcdYhHKwlpcdx1iM`g}Rv$BV(3{R6BXPW}(1lZ;F^a_&071<0bAOovLtJZjpp;mEyX zhZiKB8oE%M8W3sfB181R1PqFdf|l2}A;UN10m^oo^K`XY)?ah#xD(F&Obxt4r zkPWrBMuN?5XIQ`4d&p0Pe5ykwXW3o-@nJ_ppdv@1fb789lGbN=BzS7B()pTunzo^* zD=sbA5+EDzpaqHt(P=Ud!H`*;D4G0*Pg*vwIOSH%D49&{{pQ?%f0drhIXo@xFBhde;QWxd1EBn#Oy8MJQxPs@ZMJCtHVRt$64iWJ%=I5yQ zXFo&D(EIQGC^8Qo8Enwj<{g4!qr=u98@_4RiE&oIH_SpGTUa+|q2AqOnGw-2Bn%y- zO>1=TTwy`+eLyuZT=T@%IN6BPIhwb6R(eDszk|20^4s|>>(yV8C145w694lzVDT{D z4eVXEhF0cnHIKbb%r-w8$p@W;8IUn;2i*iN5xD=KccwLa>j8SEsv<+|gn1XFycTO> z9_C&$cBtI1XA}ZHl1T{iDuC>l(Ka~I7vD1%z(oaU-GT(f1bReJ(=eh2v)?v}rMi*5 zO0tM<5{8z(ddk}8THa47H&%@z?V02I^mcN003Z6i4bvzh&B(?%2#{ep69LTb9Gm_e!6Si# zUAGhJVe?PZQY2ByYJ=NYt{2|HpOBK09~sxQ5x&3AGl#==N<|eSptLpOU_zhebAA#G z;ji-0_R=^~#(lBPc(q+>YCD>S2|)LV0N-{|*7$F``CwlVp4r^o&SDntoHxzx*AgDdb+*pV;jkI2$)CeGvqQY}AeR~-r^R0te zk^t=!F;6Y>t55fwx_*s86@IYg5toJs%aS0yLJ~q(R78f-vdID&J{&L=gVBKANAvHQ zfuvkpKjWBtkJ9k>F9sAb!#gVnjtBA&`5Ak{*k>#T>*Y?un>kT?&?E5758@0@E|S|-VCIdsXw0eN#g_0)h0_I^`>^~t&v18{MvYI#w#$F# z8`cCuR_O0W5Rf#qnpo*v?;ZMeV;#t!n|M{@mEzg9EX6VAZWWYRg~ZG1A9`H{0B zEHsG#(smR6q400G)r(hfVm!2H`CeRhcvm6P!3;Q4+WWRQ**CNt z+v#V#N9$N0%jYsswf3F8t=}heCSHJ1^*tpYS)z@jmh3*ZpYLjao7+`W-q~iO#%p}iDU24Vpm#%H+8#cZs#T`Ip+?I8$o(f$Gu^!K^u<#<(YuOf9M|4wq% zt-vJDCz>(p%5FodjxAx`P7@F-!~Cul-xSV$4(XtybGk4U)_*(p=4AYqjs@+B4$HIU zMZ_x6uQo)xv-&nu)QY=#(`bY!xggIe`3vvQJeE1yaZ^w9ZYl|50$ zZm$dZaBDakXBRJIlH&3gK283Clryf(ZQ_KvK-SQ?qctaYv>`|L0;?(jCg=aJRRA4h9^ z=t%d8U&^Z{z;bHYmR1+wmBeA(m$mrbJSjse z&CCg5dTPEx(u}tM?Tz|}vI0LtYG&D&Me*eZUfe_4F;leVrbV|SZoRo54!>H+!Laxh zr6DK_%)LTjPY#VKul@dy+J&!`b`43^^zw|LlsMe@JU>vyMO<=^9zS|TW;oSBt{)&8 z#TiTG(=ktRhu~ba$1LR;H92XFszMcy$vuEAcEp63N6tcHQo#oQhyr;BF5?R7a|E2q z3=$3QgsOi?s5BF`C8t3blP`kBlqIj+k3!TcEp(>&&afWZiS^-l@B4jo31s4TjjC(L z9!Rn<#OoK2B4?v&a`3Y=nP8_tTw|_WP`w^-g+*K_IKV~I0w`J(%S?Oj)dJn|3sX&b zhP57#LR6Coci&-k+lj})dGDzFy|L-_eOx4eSR`$7|6%(=RS-WYy8Oz>Sr3lbmRCB6 zes^gIYneEfkYdmo{Z&(5Q3bc}gOi8eep`hWUj_=)CCUynjplcoxy*%?;A!plnG>@v z8y_Nzm%HmlK9OrYm~M$@Lu{nY51_D|)=F>#nVUP7ga?!~%BvfcjVyg3(lT#2*Ldg$ByY@hpkb5l+8+^wEBihz7kzXQ+?KK|ET zK=Lp2)eBojG(Ye@K|f%7lq+FZ=j|x`Jgj>B;*&7R``A_vIP7<;r&Y6an;IW$bc5#IE<@NUtlI+Mr4|9ex8JF1Ku!e=cij*Odn^P2H+6OEy zOmNEMDA<6|4|<#eOG5j3)bYpuhTx3A88^M`{t=u)uQ*L5QnvK$Ty@ET!;qdR-N}W} zx^-!2_v(?4jeXGVI~xX9%EU4@wH>u`o|YQ86OL7bYo8>mv;W@LHqtU&|0=Ql1{q)@ zw626s!coYx8&|387l}lyLh*Y>^@13c24@=q9Y5FG#Bsh-cDLY|dTkRtn4Z5;;uhFh zS)^w#it_^B-$tUClG6U{LGig=iRKdQu~8tO9nnfJANdGD`P-meQ<{60Cdc&kv(>1Q zr;(e|KBH>g*p(1(|J@!lB)l;a6&Gr~KqYcJ_b(;vX1XzAg)fgVLgNRjkvprjb9ft} zuZF>#HzEOGG$1+S)S-nv0$0FoNZ{X(0%^z&O-*%n(r`O)Su~fj-PKD*I{O%j!!DGv zJ}W7B3-DMLv8wl0;^1ynxWtmn&5?@kuF0u+i|MCk@5v9~2uBGN@@7VWBLf)%Kaqsw z3iu7vH|sij*(f?{FVMg}?eq2lrX`u}7qxvcs*VuNw;FaBl)6`)7{}pVAyFl-gGp7i zCw_5muw)shC1h4%%QJ{pF{1sQ^?S_-~PCKUq{qYJGQpqfB!|lzLkP@jU|{ z?+{z2AF{J<4}z@u`Mi;6ZsPePdpb#mZ>n#f1@GSoJ*$8H)^( z{mM9T4-;!dEjBnBQufCqpW;ioWnsIZtSA&3GlP)d2>=_s@5i1A!l$ctY^)?5gs~@G2whpWL6+HA-OwNHHO-C~ED<|0rk20uMjPYd!byK9o zQZc;W^w9PL0WAG0=$=xt9t#G#$0WPwfn%`uVTeV>49(Qd;AH{F_~y9_`SKtEzs zo^m|V`jVqcdZZ_g^p0_OxItj~f=|la^VTZz24oBx55Xz95zu`bF8T*+?zi?)lk-FT;3K2#I!z@L#rC!Bh%k){4Aj8Dhm->k441V57F8wJb15a!Dc2y=MOWC%1{qc`cBK1Ald`xDFXc)1kG8{e^CKgqFElm`AeyzM<=4 zRl;hv?XZKCRh%Y9*i3lSjsuM*q*{>IiFX8AYADkTZODLafZGjy%DTDOmrzF~u>4LY zB&{BTn)xMwOe<-ou(qI%27+dH&?H%`XZTD-{$Ub3tRey?ULvnOrTzAsWpGM8%LoFo z0pTJF$ABEzQo%*Bt-6jvPzMQ~|0Xkk$dbd=mXT;Uv-O;4(uY$nQT38VegaN)EOFG< z(L+&p^jmJ_er8+hnmHcb|aN=VRONPz0Cgalav%k&|53K_C`^J(GoGxR0M zo6lXvH@nFkRhvDEKdHhwa;ZtoTNt%@`KD1o^rY%%R0@AG*%KMRo?BTpUVdIE94>Z{ z)QlcOcQ0^c@_=`r5<+}iUx9I-I1uqo{>@=L&x4Cg;g3_ZCOWS2^Wt7{pc|glPo6qf~W|5SKc((?)@@c#O^WVT-iMc@t@HVKz{RI(nkLYKsKwc z1CXk}d<-Na#m&SA39syz88VC3c*Z+?N-LGSK7}>-QRJEomp#&ckQLXfOIE+#c_R8f z>9$vBAr@iD!I&Qf%J5OilRoKdm-@dIW(|OJ)V~U|B0ynw8o}YaVJYk1EEci-nOHJ~Ll4?h{?DQd8)HEFLZzRF0wk8zlT^$^?&L0ce4No%Fyf zAvt5EYCOElVH+#pK(!S_NoF1uhiZS`m1#BZe+B8z4KnTEPxJMJg&inW`jSKq=4;2; z7Dh(zq8dF7DMPL%F(zC?b0UON+jBV}LDUcd*@sSE2Z-k1iGh(Tj5!Q;^~GoBr7J&D zKS}AS7DjK49TgH^-XtB%5{P{)5s4JOa<3Jq^)6ETj|GUW97&f^2ox2?G0*&kATJ0$ z9C&|1Z^Z+_h6HN8Yk!im7?v5hE_-z9B>y>Vkcr=t42n*^njB*#Z}Gj(*@GX&%kD15 zripmGPv%>lf-NTXsG~5K*TW;EPl#+7rvM@FT6A^cMjNCL%y#IBzz}5qW+_?hERMbf zisf?o@RcSv8o&L_bh!V*cCza5L3}`5aE&}IE-QpFWtBT z?LxGvlJ5S!(lD`@9j!91aSk9fI|u!8pk<)~jsIy7A-wcBz5_kL;I-4$h1EsrFWJ3U zRPZqkbzdiz=NGHrP?%0XLq@#)=^iD_-eQ&3Tbv$EZy~>WF~G^yN+Fr70)7Ml9hk~x z^^ky$J^c7Lc=viFi3})%g zW*QGGVidDel~tgp+M(I4tL)n{IwW8D+*6SdS0~UUrYi&~)jaCK>-72#%8#fvhyLgh zLRTC11+%3`2M$?WFS*Y&h{P3x(uiNBVTsUN9CQ_i$q(`y%M!Y`Y$5+4sqH(iHl;Jz&R7I3kFELe2pS@>}*W+0>{F3&fNBYM> z@99RM1=M}Tca74Fn|rs=`r*ll7<#>$tEg^G`HRt_hadFaz-+8Rpm%n_jkNVXhzKsK zGKBNvN*-GqZT&uahPx(SemBW!&g`pS!qy&webON$&1)*;Cet#&7WS(nSA8fbF%#WB|xxH%_)bnFuBzUj1^e_`4|?6 zl>?gAP!GYSO7uyi#oc~cV|FYsLXXKR2+EzlqspGx-*FE7Zp2wR*NXaK-8^#bq3HpG7;Ti-2^1pZ`2&AV~Hbf1iobcUc z@>`oB_DC-lx_HD9%Z9vgO@xZs>L3b2`w0#3E(S- zwYA1WUEAmd(frRlTH}FDjnZbutOvhMEQt%BDDnC0n?EB;dq?Ykp3UK#;;~_8YT7bazZYQ z@}}cbU#RYzp>ak({`ElpRbyNz`S$Z6?rbeRFoht9CusyF*|M{1NnMjLhdebuVYGD( z9yU^&(u_5BCBrEFNIib(PS&${=hPoN-@_QxtB-bTCP>dRPZy91QTpT*J*bY5iqArJM(e$-jMm2GsWt%KB@#a=d zk>6%^XW7f#00zMVB~*iBy$OL;MRH54GaB8iO4%kA65>WJeZySW+V(xe#Z-G0E*!z8 z+m!ftLZGF>@I9C5T(?ix!fz`ApIy6jp26p@KG4v9uNRaB5c6;N&mSPFuWjI)?F);C zL%!Y|>ArB;mAv)WtJFGnrEeAY*;LN@kv!j-Vw?@CnAzd-@pzba?R3#wh136nKTpvX z-jHIWQ=Zq$dXkdc_FgH12yr{}4nrL}{#G8%!1R_FzX*!B&gMSH@{NGlgHKBq1fg&9 zLLID)e=Le!G>|1)&+AgSttcPvum)$GdCd0G$;N$3Ul}hZB36)#N^N;lxs$89^1YjS zUp&i~2Hn2$F>tNHxBPGd6UttOAlu`DA38SnRVf5oRexbD{yB=$F(qFK>f+a!e4ks& zboLO>0NNpCuunk1&v69&BIx-ckTp99&>n_h{s;D$bdJ~T-ecHgf z988j>+Yt-DJrr-T?P!Ya{BbnDWbTb@8;CJ+{@PgAu8aTdbnf;J%IO2*zveHe0qk)Y z8L|)dP0JMnsF_{d%y+KIBWL2#KZ{%i`}zF%q8dfA zmC!B(hx7xnOnP1G!tiqpte0I@rX(3x0JnA>fi^49pFo3?*74z@c@LLQytGa=VumTR zpG@0E6z{iI9^vcVi~Ag*pd)^|pWIkEAvfp!60P32p&seEiUK7`B1Fa~I-`kRwb|~G zq8chxRSqPOvl2Tg`GAUWK3Z0cC=Lt9hgMYkuYrq!OUQKiIzz(nFo!Wx^rg6%$64E) z_wG!cVB(#z-28_YL3=D!0;#{B*qw0EqNr4X+{V$T-SBzT z-P0#SMLb$kXmMX>B^9X?)jvAa8n*fYhl42oD*+F_!~UQWO6zB_&vL_A&Gy_JdTd>`9K3afEtc2N_*8`n2rh z778SW-z2W&ejwAmj2iyqsl+#EVkJf8k%>_CMri zuu;HIL;erzz~k?;QACsL8^=8W0!6SNt{;I9_lxjr-LmQ(7K?WmrI*Lp1p58YFHE&s zy6Md-cmsF5is5AAQ?=5zfp(i>t1-0Zo;gcnBhk<)=p-V|3Bl954a9X{?9lh z|2|v&FOs#~e?0;PhW1EvbQ6VKa_cfOJAocpb6VK8;qsP|KC4Ua z%FY;?b)O?{e{*EHrfUoUSx89RUky*#l5DiVhB-M|ll6cYk+VS`VfBmKWfetuM`m(U zasqfCE#?FK@7@#tGHA|L>*JgAf=YyJhaJVgQ_0I-^ghKdm`vbSK(G~TA%M;Z7hUmV z&9+FANMe^06FHG3vdR1t|9&S2ugeVGov8-)7Qh89WPSUI_L)I1xN8O>7pkXAmb^(bE~2S?6$ zpP$IcubbmCv=SiZCY=*EafN!iQ4Hf(IeU!d3t7SX*iqtkPf#?O#;HP0LfL0dPLZ73}z$h42X6j zNYV&AQ!>HmDXoK8Sui7kTSP&FtXitnH%^z=sS`-{ESKg_aFF$%zWJOo3y017hcQg) z5DA*x^V!;zSe+;iO!;A`c#MSAfeZz?3-$^a81x;qoZ!xwZqO3tHYD$+U~;9^;n&uZ z-nm1e2zjtg7kKK@buYH92jeoESy%W4mXrSe1OcJJ&du2Ovm}0A4|ub!)uCX!`q8P{X z@j4T-z3|Ar^v-xi9>g-o<{w#b$e;N4EileAfpHz++*E~eLiiV%^fMTRn7H=Y4nHR4Ew z(t8~CEUcf09{j=Za&z^ezOU6dwF%7aN=dE z{7WkNX7ZpDsq~cOc`8>MTKg~E%iH};zjK|n@4g@3%Zx)ia*n~2zqLv*XYdOHw^+ad zpoLaqVQUbdbx^EAx;x4hq?~l4P@01D|j3u|eU4&q5 zkdck|k?&|DEHq`^NF2W)g&PfulKe<@i=uw>cUU_v)XYTh@jEsWe zkf>ucQpFcX@JVCj=h4ASKiuF6P15VYR%8;k1vy^2=E=ioA(Pm}i5-dkOksw!7&8p& zNMWm)omW_4;YpVQR4Zw?_p2?cbfZG4#^{`7UP|^mt_qa+`vtHss|qwpMSKJAuL6Km z{!c+L3Qqy}U~we6XYOkBS~-bZj{0*=XbT)7?>^K<{4l3Iy~9oV9T!Twop7$-yUo)a z`O@92Pw@gnfW4#nl3Z4IL|=ZC^vedKgMA4!WeViAfrwu$_!82t;%`BcZ@vU(8Tdi( z_?4^!(=B65ja;m^dmm=zBaR$NX-j`+GdNsT9{Yds9|FK5!pEDdAEH!?Q&BHM;Y&3v zHa|N~9Z&yy444R<(W(#d7(`(lF?*;%LGqu{xx(v`d;^m1ztm~N#Hz7u*GTyNGC_?c z-UknJWbE}ShIG@q_XtB~HKDli#XVB`_A7nEKlQ4XQ0OXX3xHJxdh!}C!bM|oMVY&6=cx6w;TlQhHPef{1emsJZv7kk~7%pQBGJ5@9 z4||082Y{jR7C<@HV4!daKpqGgjpS!O9ub1Un7MbgR`cD}vp-|p|AAEMU_c2AzIWd& zn+Z#0db+tkJIvtqvqz$zQRLCIMp&m0JbC!<;aRvMHn@B#y z{buiT6(i@GGx6_ktqptsZb3ag*0DrZ$$$N{j(oQPw-Hb94gGWwj|w45wk?BY&ZOpESWz z0dKr2iy7}mY?gNr;)iYonQat;R06SC19WBJ1wax&h#&z%1n++;2CO)hxat2?45WqP z?FNYxEVGXLz0lB@-*B~BobvTfq37gFh6>k# zca9&P!8Tqddc>jUX)q=oj#_U?KbSdXHq7Dc_?Gi2)C3Qf(0u&^fX+kr?!&d&1fb>$ z_zrU76!;vwq?K`QEv3l5BKKTRRxz43T1z(va-gQ3OqQRh+%-vp_6q`nn2~?oZ(DK3 zGDz3-sExmynAIz{j11-uxL?Sd2nY84HQhm;9lpnZ9`NjWKY!(j=5CF2&46@|WVs!W zNt1leWj_TE**iXG=_8kqX4+JDtRqtlle?yn16w|`dYKY?6g#lI~pPM|>* z^n4si|3z4dyE#tup4M{&?VW~9RlB}oJ|*r)mBlMibhlE`#p=kBo41Rl?)7T)P9QV9 z+v0FanC`3m@&LQ&7CMuh(p7wQ?kxnb1fVqfSpl=4BN`DdnRcivlx6bBPAC?bJ5AhW z6tAJ%*Li!w%_n)0B1VWl}QyC!ULkRN$S z+zkcDq#zP;-+96N!(-_YoOU;#ol~N27CbIJDh~NUSt>5_p#rxazobjW=Qfk%_pKK$ z6bk-7(!MgP3Z`rO00*TT6jZvqB_stTq@_bZQcAi6B&55$ySt>jOHfLbkS^)=n}go> z^L*=l|GjIu7OwMS&YV4a_UyR!wVeaBTs9<4NZ@D`%kQ(UzH!;CmXvN3aql-N;#1*J zA%QxNg6CxP#;6`VCoa@n4+c9PNLOLvpuG9cbuz0bE_!{RVK;VklD@h?5|Jvv(yG{0@K?(1XsLY5agN z{*|m-;)(cL;s!*!Jci}j@)IEN%CabnRL-+{fnUn(hHGBDbl#_JBUfI@HlFt z^c1{udm~dEH5Q2v*1rNd#KA$|uOUuBt9)Stf8pFYpSJ|nFtYdO7<vxsbH#12Lc z$_$OydJZp2d1ZaoIaQ^EvtWE)!I3mY$+W1}uA1VtY9nNG&pcvf>?fZD7aY{S4k*G8 zc!)JHt-T@^mIDyGzuWy_gwZwT;CilbId1E5R+$gean3<(<-T0Gq zd|Z<%`OpV5V8PQ{BU7NUVP3D`d9SSL?BC3HXAFnVij};ZBx78$$Sn6}*gl9oe?A{F z`Y!k-lIdG(1>tDU#LERo_N09aJ1c$u!FolZJC~{mHYKxFgyarcHOW_58OJ>Ab+Y{Y zEMB!@scVcr-t$r+pd#^sMQSjw9LAb6WB=KK_h@scRM@WL0b~7b?ZF#95|!{N~Uy zFnw8zxxe_Ss|$ga#HI$#sKhZ5X5VmHAZsG#uhtYst{iOJJWQ`MyNZEFr3bQ8rDX6 z__vKxS#RLvpEgP{&?by^*YI&G4#CfDWP#FIA(pXUB0zcxc#t3^7(7Upm;a>H5sMu6 zhh87i>^}&x?&>C+o~njFeK?6~_=M>IS~!dQ}=%rOH?u^WLx`nP+oSk2Ft<~Hr+kJvF_4<-=Q3dr~zNch2uUm&Yj z$(`|Gu4|?H`EP2WWp8y?vdOth(t@p$1(lq)LEK-k%aRLKHjFW8v=}4X0y^fyp}up} z-c*Xe5rzHL7Z$LkK}`Yq2;5-s_Yh3jhFpsDFi8XG_FXa_uHL#b|2i*&6LYRb~WYWkq;{uc!HROFC2ji1>IGon>=Go>=4y)mK+;m8^9>%dvtMu;Bj$ z4w`}>F$o7rg2jtL)FnueNP489615r zrpE*M{RA%4KaLJO8Z=W6y!)eB`W>)7*mkVR=#I<4SV|W|MMuOnLafrCui2-5_8H&a ze-Wqp?ED?oc)26-6l zaF4b23B?iWJCH#AVbhjCK@12M8h1er4>%G2>h4m#>fYMJbrw1VOU0BYI&fX?Ap-LE zyf!GS@ukmCEd$V0h8{TcQ+^!v#aR$H-6auy{@tmS92=CyiuCei!$9C54H8#$Ss-YJ zE@XnM(M=zO1UUk^rQW}}rJq8&kX?`4o|O5dhi}+RA8&dq^QR0l3tRgdNSt_3S`L*k ze3GlSeXTM1B%acTQ$V^7k7FJ~&=yT^mgU0I1E#-Vqz(UXM0>0}Sl%9E1pV18h!zTv z!5qbZsFYHEbBgx;Q%n%ssTlR+|0UlE4Qp10t|Nr$tZC3wh5?}GpXDR$_b+bedHI83gd zi`IeQToy)*kf9smLhijp|L0k8zf49SldF(v7z+)E4m}E|e;Z=ee&#`pI*J|aAXN*; zBMr`$027uL0fk7UpitPnHT=Jq=TOtdz{SQ8^|ZURJjzuTUox(^!l^pn*UT+mwt1=% zio*CM#So61W{AkTi}Rf&LST@rz*nA2MEUZx(2z|7pg#$KrRf?P*GT1ipmh%O>p{lz zTK0?1b7XI<&yUV@ubzBsdc~~hbdZ#XTX(j7HoK>>JJl}TL;Pk-YysV@G)-f}H8NC* zfD-AX6-(_ISJ2-7A~%#D2xJrN=Wx(_KR|`ygBRfj1o`g`I2Y{r_+4?GKImpL$5xrc zr%2U`F2k23pz-?RO3EL5gi3G;U*0^4!_76Yu8@tJMDSI*MPhA~`1R7p(Ch_B8)0vN z8z9^IhcN{tj*vR9x&iR%C0HL!j6<~I6T2oYL(zu}N~2y~vNU<`3i?5lgpQY(AV$`@zu}RgkkY-(L-H)()RG>5E3$eJxcEJd9mL* zh2I|KZnx42AixFv^6Tg0vIqU0Rczpmlz@HsO+r+K1z0UY0OPglb2$=#C%*;}sO-(fIObG@BGA z*nRsBJ_>(DR&pux`6f_nd^Av?$62z)H^nI00_>+5*e|}nK@_;T zo;WCR$VY;+|I3o%8-t(pkNYDI+#eWA3h#5s7vwkWk?_!ZdPFB^NQ?_1r1`Jb6FU(- z=OeRgnKUMT`D*wF*G3sN+DKK1;}~XhNY@}T=1GUb@v>dVL0Z3zEtP;#;wVOr@~MR! z5;Sx%tkW7cI1;dY(&tkRK`zPaVNMSm*;~3c_9?n!az?!)Ba{2wvR2%WvUzLw+!LBK zOrkK>k=1#I3*8oT&NOPA&iP#zLh%%WF^$n&d+p669b+Sy9YRuSEomP5N7Wx#x_G@*@J-Vd)M5`DS% zEB8}?Kv5u7U&TD-UNn!|P@o zalRAqN$?^4@sd$E~H&4^QLT<8yVO1nwxjxR3HB4vZS z*Qb9x+b1H>itxZlvvPVBJ=0}s8^|&KzCEhnTJ*e@R~iJ*uctxVNDUyhhLx3)zG5al zVxV|tQ1H0DLg3vkXxzDQE(8231t_n2Z-DFGloH<6m3%VVUdp= zeNk6$ULuwRj4z%I{FVGJP=^&vx~|87^iL+yk5AAyK>Nu^V{211h63Tw z>90fp7qCwMJ`O+Xfw1^%NKu>#cB|=Azg)~Sv`$8KQ^6*2cC~IdKyoq#cP^7knMOBP zXZi3zKh3yWbTYQy;>@umhpwjg*V-GmrJXzEJ_n0<92gY{Ap%>z{6-I92X58%U$@F+ z8&5C6M^0upY|Xp7P|mY9KYTKXdN3(_b$vaUb%|S35*N=p73uvvKHFefq)~Syxoz!o zb>fpZLxJ9HWj0{Tpf!N-K2X@sU^C(aK~qd_HTMk&=P|Fo29YS#A0Op~2RRM^OF(Gj$k$QqLC7o_lT5YagnJNjGnQ)1C3s{ZG!u)d5BE$DHIF0_qy1~wMc zsF3|?tBnO!$FUl&B9+tclaqrtHGC(86{akMX0qxjCvZ!^(Vzg6QAxYSF~K}F=usDd z5anGr(*H|sW-*K-lZ~uY9m*R2a6SJS%MR{k?~-x9x2pdmO6eIrfpL+B@PrneWK7C4 zszl=!M`lvyDYH)xzs~NWarE){19<`q$yoiz3wQz!EXSP$!T|IOHt*ICyS@IVO-0kg zk_>KVKD6OYz0=GzUuL0(WB<6LxB0ex{XiepT9sGA{&M5}I6)TCD>6D-#|2g~2}NAD zj#MNrEU4i%%mGse3m>FL{M*725ZD%cShbfTjH%$E6VP=Su!uDg^0sDKMiztNSzGw~ zspgyZdqE?fwD|NosJuE1vrYJKP^oR3g51kBupi_DsbHySLU~Q7F3?5+dAKErH$qm_ zldB4rj^oafQz7p+9#>D~W*L365>7_SiY`sg$CJ2F%EMQQA$x~%0v9z*e$lepotUP_ zyVLtCENp1TR6_@U2hv9;%We+`o3a8a5U{_iCBlqsa!Gx?r>=u8mgmviHCz|fx6+0A zBktkvY}i;^Irn?Z8>Nn+iwkMo3`ul!o%cC%IZ^Bt0;bo=#_{S$BJRUlvw+UVajahST4tK98%ytM0z2p6nm0l*?^u?@@}))1NqR zvVg&xJj36$yVzn6M#&1kp!1;FeeYgMe{)IKn2)zlKLs7NsRRGm_ZGHwRtU ztc5%D%>X<4VR@KU%O(tkasWl{ga-8hq^#gjG5_UP;Rzaeg}myV%+6MoW`~pWk(3~H zA*EB@@9UX4&A+H{vZ@jsUng+WzY;9=f71AnFUX-WK%P=wLOBX%VAQRFx%vPad_mb_ zm}rHzKVRGN93fit5!8ogU@ST@dg1CNewUOVhEonZ;{=gV!n_?t30weSpfHYG-Sa|c z&qkh;4Wxv`r%A8=BhG(A#;sOBg#;U+yGHjEGD`Lo)YZk&Ae+F1j{_49OT&zD`+4JH z__^0lC~2Yw9Nl=Cu2vimaU2tDljupjmT*^&m8LBCxN~M)%;1ErZWt-$8{A2c_+qHK z{|CHEDQJlRM<^Zxwa`~YgEUeVLvJtXib488INqGBzE+^$uYljO`7}b=5F~7V6`eyDGqJ z&m*UD+JX*J`c4%)YvpPMX@`gl4+SYn1&K@pf5`5!0>+JWds`&(ONERk{j--L?`B2l z-17;R*34qe(0c*C02Gxk=zye`@5)UJv*b$`f$*aGA_Ki}Q!8sDytv+s-`|b4EiGqP zZ0z0?41&U9>Y7uw+;)^fFI#oVy z%97uXs$)gUkTqhz;BHwqUv;aVIAQ&9@e4arT6j^euOhK<2T9VO0wFKqjn4+22SGZE zt@O;7MVJ;~ex>q-e6jp>Ah=xn1HQmfqR?f~cY}lM-ODM2!yn((GR{fyXyvk|H>&g; zhU*_Ds0TF*es-&%{WYm}Ue;T~Bfs57EmehML6wN-bvoQH2Qe;69}L)P-M3)1j6iWI;P4%4Ifs*y{Alhm_I~|{RPLxa zqnhiLVGTAq51tO9*bCv}^c0n6`G@)i5qVlJgi;4wwEyCBK#f&_ zD)Lcnu&Y2JqTn4G7HNej2C6{B{iok=c&f1i<#pHC$Glqv`qfg_7}ri z?E1=iEU0O=fC|Ck7&?Or3(3o1eRKfWBmwtQH$qo1U-q&a@4F7c$AeLGazP71=eL40 z$`f_>_7e8RiUZQ~a*}mS%Y&`O$|1*gqlx|Bv*%wnM)Fe1?to2pL7@2=R3*^nb1C!# zL4@pL@7}pXrLg<&_!Hvd>Es72*u3z=UQiK;K?`E+Jka5%cM-Ea(x~l}@B&yX)z#|B z-A9jOF$Ck?MS^ebq|xD_ouK{(UA==nLJce-w_jx1;4#T)d!BGr7e>x7MRjZPnk%&G zb7M_L*&#WlIF8R6lHYvX80R_{CFc;{M0`6^p_=4*Nv>oDJMwQ3DoV(Ltkr?w{mVKL z>0peH`na9o<{Dv7ZIRpZ@2mPqqQn#0nn9nS<2uv4?yN3GlxD0nB4Cgjg2*VkwF1=U$&cIu#?_Fcrv(PXh03-sZU_ypKzU)ufaW4GN2mwUee8)WFsrN#8N5nZ`JgK{u~} zH8PdC;*DB{|L-H8bY<~bO#d7N!v@nlem)f&(CzEi3nppoKwu#$WE9TXQWN6(chC41 z@j1j>2y)C9U;Po&D!tIJIdJEg_^DT?du3~JPUM82CGz!%w=oTxu0R+m6p;FFAI1K7 z78l9$51j9(eJ z0s}YZt=RLnU5a}WFAxtKQL{X3n6|_#A(+9oZQn6!+j@DY9W+V+?A?>hM4G6+!IV>>^0Y83lsS6ZU;9)K^h)!SO_uSilCI(oZ=J9 zN}@9^uEWS}E{h6qIm#kl)`k1XR!qJ8`Vpi1^$g=vvV_O2ZOa#W1dHYQRD>GoHje12 zg~WC-btT_bDG-F0M!}x0E8}xuS8H_+xA%kgU2CvlBu+wHmYCsp%ZI9OU-6T%5`N$? z$eCiJlts3gn&HLdI)he~04BHg3%audK`NHzwEoZ}%#PuKA=eeA%r)hg@T_jhnN#H1 zl2m$Jo5OK}?<&~B+Dd<=P^6F0r|>gn;p!bV7+^bm`lIrW$-;p z9EylW`=2}Wa)Asb3c1l9bU4y%??6x}WPbyjLih0Oq9G9H-MrB!V=Wvhbg$QqP1*&? zH_yA4!twkDK8C$y8P+xYJUEP&_9<6^omrvGyKI9#_ySvjw3p<`8V4O`caxrdVjCx zhWHt$KK%}>oqF3NHo_>DDH07f{z)E6z-p%;dB|t1s0c090X(!F2ms#fgfv*tGwt!u z*dsV`A3dihMhwCsI)Wx;H@{zh=dg&tDxcf`?h@4fd#rp#r2(0V4V~p8(356+=IzTw z_R3Gy9!h!d_k#@&4UBz3OE)6WK#gSaSp|3yqCjB8v7bOaMEjq5NK8fzV);L0PZIy< zulpadf>82Z%u)jzP4_oGk^S@0U*gyoo8Ke8{Whd*xlkNV^Yt+tfADtK|LW;g$nmoT zfmW|AlV=QxLl4*uMiO291&vPNL}ajS+|T>YSs>p`z6Aja78r5t{Tvu^?3X`7;)JD- zA5@&1uQb0yus_pKGAs7&c$lcjkI1*0)LT8B_g-wIPT}#B3;vSho)ZNYtv5weCplGY zR~OkC>2&)kJK11KfPAWCgAvDqoHux91!dM;MJhhUo2wPl!&}B7qhEQewFp#g+o}R+ z&n#o@I#RU*E_=g~y1Wt-!gB*#ksSS%!IyK~CHG?R-YJb|!5%PQTkss7|A`@#>h8OK zePkH6(U|_|KCrwX{A~H-E8`i3iB-&b8jep9KZGAvwlD9@y;5ZF|B+b zq>bQyB}#zW|3}RK#t?hU|A9UgLnoK1o+4Fv^#BI=-M<%Bt;iBs3TuOMZV$3tG`mG6 z0WswT<9n*w=M)%n_gRz+s}Cip>b_ZW%zn71c^)D7VYsNSFEeVHBV+RiEw&Dj32^s0 zabXaOP#AhdLyT-;t$p)Ys^I+@hFqDsO*3@^4Hc=W%PiUJy?Iqe_&LvwOfqwe*EV!? zzT*z^!jpQpU91nL(;IBB4HY8qKu@s|h|^$(3`n&}f_JzA&~j};V*c(|Q+&Lg? z=(f_V^h=zNLSZ^ama%uJ5pjQJI}RqfIDOya;L_ORPh-8QRt9sU;`8T4WO0cLNwT=K z)OnzV9i&;o7`08PUl?q=mY#z@-~1dx&Y18=t^L3$3DtLY$&`{BBd2}+s7#2)g!X~O zGefrXy*Y87g{S>S%g*wAX-?x}M}opm@k=y8u$Gp&VOUZSOlE^N-++YqET}gh9|$^V ztS{!aJquSJ(BTXD$|c$CQ_9-*zHHvJlYmUm=C$_Qx>hC(HjxBq)k()}tborgrLq}^ z$_m+Z_vYtRO$NeX6)7l#J$QNB3y^mJDCc8@E%gJZ!6x{o9eeknpQ_kKFBfL*%(w}L zH&E$Y&+S4IFvQnW>KGQA3S#-~wFeBD52_d5$#hTte(xexL#WR+4XvyJWF8P+u+geZ zK;ohGSE51nx9Z+@PFAyfb%BCz`-{ECY$rIrg z_Z(fm%~i1xyE5cZGv50d@vE7X0@ZVc>4W8!2IsFcBNt~uHUA}C{=7PvNIMf@BCP~F z1#}~ukPfg@@S-DD@Gv_bTncoLid*Z+bT@`Cg)EpYGcO3RhT}&t(-^SRgq_DH^$J(19#YXag(Hvt)?n*izcDB`sh{!X|}Ne`=IgSm#O zG_`3X!Y!iE*L4*FjL#!SW+@>H`f6DhKXSx;Qx;>pV6t zkC{v^!X{JAVYNz9Fy|0Dai6%=d-=@t4mWteoZD9a>t z-^wjcHIga3W@CMH+Flmj#irjYc5v1n8cNIj#ayDkTPRM|GZXQ(%!Aq8_6ibp0Coek zlU4n&F|DaUlE>G)MUV=RJUIQE|1HvR@?kLYKPKLXFT-B;8(>1XPJCdtn(1F=A~y4e zMe*G(=5U{GXls#n^t~2aD810g0RqeAX<)+k$Wz^4P2k+4;h{ZXh7Cx5-Ni2;LxQDh zTw}m_zZCD~tA4mA(0&_QV!zjbIf?(am?4F3#6rwg(44a7*!kPDu0b|^qSfq>(Ab=j zitBWlUVRY1fC2+58Spa7$ch6+Ko_B;pQ@w6q7^>!!VE1$toQ9_c8!P+l=e)f=9t3a zDO8AAy7pha%6j13KO7wn)p(JHv%+x+2#CG=Dv_=Ac~}~ZHC*KblNcA`kwH&l6`wGK znx6jUW^cIlCNJkFj+6(bBMan{M?5w^Uzu@XJvlMt?qZBDu7tMQ#&cn38Xj{#T&eRp zUdS7etNZ>HW~*I(3Hl^es8vv(CU#u$~bp9VAsV zcEKpxN12;kDHQGtq-(o9v%NrSs&rGBTMFaIThfKCMh+%6K++2Lf$j`;HK_EKe9et% z#UyxBVCD4o$4#E~d$={BlomJ9~;&lYH=9?HkZc0w6BsgOCI*> z`3E@?)@*CAzw;dKOwp?KGGa1lo5Q)B6h_Fz24^b;4}HS~ke6R#=s>P)tnld2T8B#> z&E$xLiYS2*VQN0>h+u*2IQE8{$~H9gT`WdqPIYKq8+mMG|L%HbK9&Txg4$fPWy1pMTIHm-yk9hohSeGyi~f ztTM5Q`HZdH+{lK@NG3V5cQ7Oc=G_Wr`F`wawH`d z7@Xo^C0hL${599Hb2@MAj2nlf@q|pwG#nS-mR&7kaSu5uP{8}vfU}1oageAc*|Fdt zX@CF%aASj}y+1wbACK=Er{@21j{g2E91FOu@Y(Dp^MXqxaUBwHT(SbY-WtOZ<(;W< zOyzGJG8iE~?{eG1w3NYa-q~KBWq*51h>FB4*mL520lo`xj^4iyYf*;`SSl#Y|=H9q&kJ&~5-uSm%n zSBnor%D(=76dSc^ZjBpuQv2egcGfBb)S2N;8xya!*K%B*6xn5EGdg?c&z8?&(wqp; zmnGsd(54H56p#)#rk4WJ-n+QH^L4fwAf5@nB94w_o$6d$kQv+8`fW0jYg=}m$X5O!zASc;dlHriE=y5x`;Jx&KsG&=Lg4Z`AD{N?@XNQ=^!x4T(Gd5H>vnBiQLX^+E8?{Ei}&MEVLv1 z!fZzX9DXc3v~&zP0L?$rZbaW?}Rt)ntqc5+*twqyGM!>zB&qw5Ucf z1{#J-mDUB`ftGI;xRW5sF%(nX5+kuO-qGkQ)n1V%)!J!=>Pj1Um`w0t5e4tcwy5xd z{w*~M+RhFtH*Yw$C7+oy4$>73t0nu-k`hkFw9;NpYNA0!LL8M4eUCcMvkOTq&tZuqDPa?huF@HklY^84 zW|*JT3N>N^{WxD@dPG34DB`a9Mz_!X;UQ0gE(b<&wd;;@@p%XQFS`aDM;!6|vE--M z0eDY+f~&uETX%7Pwfv^+ucv6q?tPWHdf%+FPC5!6noa~j;-}%r9S4GJ+Eu|sN#rR_ z$}aG183p4xC@;Mgy+xVA?FFKY;he8BPNL$lr`!YK)gMnK6-*q)+x@(vPm^5dEh(W; z;oE~*kiIZ>Ck^P*^LXf8{o&JKg&uLocJCyqYbfzN(T6r`Q0o#c2C! z%oe|XZ)e|!+z)D^E5t*|4O(ou!%ET`zeObYB*@{Qqo#mk);AaSii92ra?QM}^P#hn zzc{0tfL_JJeGBfI*8IW3{E+P#N{#2V^C>>x#!yDLrY@#Sv^zn<>iH)bh~lI5Wi|() z_af=yfMXU?ZYBo3PNAbd5Cru6KlyUr(?+h?^OQ6n*(e(iq7<0KjQHbxk(l%_px#Fh zP(EVAWUS&6dcQcYKo#K-l0_8C5M9*osDGOh4g0YZV^q{1=kEfH-e3)J!}Avt2P>!( zY_uO|C>FLOePhm9LbnWqB+1nuB^Ka;|6rK$g!@_4}FLo?2!l%58%YFUAsg=JpbBX z{-iDa8$Z@o=U*ExG5MqxZLyPUsdT%Z;SrGR%dX$f(amDl6Y;;K#9BVv+xRmkm>^yI z4hLTh2=lFy>&KD;#Rd=kGrm8NEFQ4>aC{>?g#YjAqPWud&#(eiwh2@@DFZw{7ipQ> zuh!%CZ}MSvInKWN%_<^BL(p=uM|)Ydg?u1;e}&uHM=r;BB!Cmq z1lA6@;>Cgt{JoN5gJ7l-+cAc5S55IGUPReVn02>Di1d-&>@!XhjMLtV{F|*rl~Uy< z3BACHI;4}{s0fa;(^hQf?01h@ZCGGfzF1)>V>(Etubp*wd%6P+U;fe_6DCU+lIkLKo>#eMV}t zA3YAG>27VISYt;Q>wZ=c!@3C?F6t-It-+*Y$V=BSFT#2k^dI`KwWFwENaP*-VCYqa z1VEAR0HFY~HT!?@Bd?On7YKg{LJn6HW({MX@1$hc4Yce$nABDYB9^!zGo8=lHC`tj zHDt3=tY02FMaCjvXlr|N)k>!)x_N^D=mufO8D0m=DO-U3_X3wN41|0Af5JUDRokk= zqtud{o#FYm*eJBMYjWYI3l2I*N^8m|$BI6)vM7u}L_^x5`ypR$+w4wnmbq|q83YEQ z6D6sgUg+t6mT!@j0A1eTJRxyj$V|!q!Wp$bY=v7SKSU@tC5@UAuYKr$u&^$iz4*MMzx!?jQM&g1iEkgT&Y~TtrB*iD!$OwO)4zto^P%o zIM3IdOHI_}HvzlPFlHGgP~7FPF`L$0^3-4Yku7?@_aa}!(oqqWFE@IYl4wOuoBwW0 zJ$GZL!b_K2@pyW>$$LgzS zSOV}La#`>!92d9NHJlpEYBP|d?Y$i2)ak#FRBR{PG_jmgx$TA?p_q;LCa~d9u(x3xw{!Kdpa@SWXr*{6CC6@9&AaMI;%59{hTOUK*1k6KoY}7*JtKO<^O;A-XWTUi@h~|}U{|l{F-b+)E}KHF zpUfJKPvegSjG|u3b;y&Sjye)d9gS8&POz#z;R0Cg%WoJ`#C?aZ!jd=MXv(@R9W7*_ z-PgmzSuT!9$wP-qargVw3nJ#sdV+f&;3J(@(&`w)Iaj$wF%>H|kBm7Ce0`?Kp2=?Vou+_{zfmlDPBlzxJ2*Tf{)=}N!UK@y9j;=Jg(C*B} z-fD)3yF){>b-P_OcP$Q8Fdr{6lXPn6`6DJ87K}R`J^JM1Y$=iXw7Ug>e-(>rL!hgG z?*&F;{tev5Zn!UC;Ka&b^BR1i^v##xxt8|#7Y`i|dOV0!^h$fv_num+TGjZmDiY)F zh!tF)Wm+U-i@h0|Q?c$nZ7H}eoh?|uMz4ka@F8^nD>5 zxvf;k0f-PtK%pQcDpT?9_lIi4pPGEtv2p))d{51Yr+Vape%+Ex*>)O5I6TJ(ODZW7 zKh4q;w3=vaOZA$7VqFKRi~Bl8U$R0ODmaQYguwnf0VR)7Fs%Fspv2JIli4p2S!7)3 zhf^tz1Howdcs5i?ZRW?mCD@@7xZ%R7X!-N`d_V9MY&!Dvv+@I-iU2r0Ps;U?N z51{Ksv?7J3mw*0S&I&(zpT!Pru3_i2VB*S>Ib;>5wIAk&8XelN`+GVJ#z)y?U7K{D z9$6$P%&5Ai^F$%@k1`DZFHX1+GVE*qf95I9Kc5}Ig7Lov6G3Dc^OV-zM<5oMd28^A zT&P~|Ey=;Xb*4%MVmOcH+`_=pmG`U-`B5kLa4azDWqIauO&^RicT;hWbo--l(OhW< z&si%}&i?pcwy}DG0H+7)pGY&{KX^!U{yq5q|0-EVS=UZG4g!I09~B%ubFcUDv)gZ2 zE0$!9uWu6M6`d{lO$Y^a7;#C8u)d$3u_#;~2q9@udJxd38-3iK`fUa(eV9lf8biK< zrs*JFp)CStAXs57$I2;`#)`M-t8HT3t9=?X)ytqS+v3Q&=oefeltqEwJ-u3STu&{! z2P^lMnqG&!Go%sv1pgymfDG^ACt~EMKW22P8*v&5urR<%G=m;{gmZd`YBLs#M%JAx zVGd$JKU%fO8FY$=kz;O0FConOekWw42Dfv$9~I-PaS(d85jY?ULas@Eon-Tdu*<7H z0(|xEn{G0Ic|n|%WfexSA~aCGFM>ppgk`X_H{N^^TrswF@J|5@0@}kOmbwQeH+6Aj=mVPMsG`cNRLe)*pc1uz^RA z$QYxJ!+%D97(b$!yfyfxfYoT;ze-BBlH>zCCymk)E!U%i;-z4ILKICoosW~S-JumD zc0ltkVEv&Zzo&0SRA@KN?WQq@dP$xsk00KD1E~!gn^-`$Q9NC6yuxi8xhWz!_%=yp ziqCk!o4>RFZj-M&nT)`eC-@Fe;T#Rj-qal+=d;7tNbv4ZnfUQ0?zyq@o%?gYB(Ifrh1_;KFyE07g@Gqs0-`JrJhVmkiC3lV z0+yO$nj(i?+-Y$e{-GbAd;ez279izbj8Z0O?%~8u^U8U-J5z>HH8bz+F7-uiD5H-- z2ZIvsVwBHNb{q+A#2#^l2h?SiW8chrJ6wW)4Z@(}jRq^r#^OTf)j(DDCj@lYAzmPT z2<*ZC2|4@gG%wp1PcyqO?WA_ir!n#g;M#ij`f98lUrq`pFXePR%kF#swBAh+Q>?!v zy2;flPN=ly6XRkkS3WJmlVWF!B0fX(Wx@bx!tEara4fLwDZq`3`@8z;4o6F6TDeRX z%P3r#8jFJeV9bH$jAD#1`9fp@&TNKCm@Y z7p3;cg}d5?d58izaHePKOiGt|2G}p1Zr*KKRY&WMQreIdfs#6sMy$ zyC?mm4D%Qbtf&uMa`SLlDToP3B1gXlIOILikhg!gyi;hCZ8%E&l2lo+r2Mkf-uQHB zRR>=zSjjrH*nzLqO1^GjfsU1O39;puDl_Qkz#GtZXk+~L{guL#MM(%~dH{v#u~%t#`vpfOtG3(Y&Gtw)+4ncMD7Q|uqrDWiqnDrSpGv(8QbD!pI*3}i z?>Jc{?UC=_N}{fK-`+xs`_SbzpFaK~Q7KzX?E0)-F5(d$ zYTPQPqhbCB^fE*$VA;z66%6C128;@Z4xC)UlBF#79h4o0;r@MJ;`RHjBez)N=0-*L zrLo!@k61%$ZB&0$QzZQyJnTph2pDbgOB`;_$*+A}H!UUGUB-^!DVl~UM2Z~yC-Orq?fr@qYTbA= z)aEnPIDQLZe~d&s)j9Wz$DWCYq%XLJ7XZ0Gz5!HZ4$%Oq>UZ~&HxM)0tFx^2R+ZWk zpHyU7d83~>&*{AGNfS@EyRA|`QG2^xe`xCcg(%IY%)A+K?PGeSkPFn~+H{(%_n?V` za@Y_?H6a6ynFlT!VB`-3LKp^P)@2}(e{~m|rpE8Sha3G0%dGwUv*|#eNxsKF?Zo8^ z+Xr;biUPv_NQihd7<6F_ zyKab&pPiPyS88}S?3+hPf&DNH1*LwMM@-v*M1UYH@W)N?VG;n&+00*b!5AhLj)ZB zQscPvBjMFx!mSaB11%(CJ_MCY?p`lf_8_D|J7zy*vWpr7N7Yyd7Z2c~aRkC#G&W#s z4o+-NA(DTZy(sQV2<)JQ0PAd^>%;tfg`W5tk&Mer+83FAe|N&(E0=$y)G5#Iw5RsT zC>5e|pJl9mt%deYaC=k?ZV<88R9+qb^TTf`az=7i2#^B0Yjz5FNB}Y(Gx!trSHkqh zbkn{Wl~vCXq&HGi?%5xxmv1MW7ual1`uju>{JFAoMnZl_~)rFu| z_cFKCmPL-dP8hQn35R!7FjJbjZX`;Ca$Aoy-E--FjuZ)=p>!u4M0da#mZD?_8x6hp zZ~dKx4vis+!+$34JiS?-nsToHBMy=I+g3({sF}<~6H zL%J*dKQ1&rKVZztsi3^BnoI$crhu=4YYB9}Ebp%N&NWNPkk?ci611scXgYZVVSsLe@t!`C@CYi%X6+w@r@rOnS;P%HdL5DV} zeAvz50j>%UYX{cjje(B&Oc;3fKLAbDmw#djTarA%e<`XY|F2*CF9PVU&|z(50ynsM z2ei7|0Jv`aEzfLoMJOu*|?03W32E-v3ork@#~V;l#4; zkrJ>4a3s>*H;6PR36pzXZa$dcjDeVT^}zjVZ%XGA%HBtD6^3N@QJhvG`gl4Q?ziGh zWfY|A8ukIB-+vA9$BT*5 zzrUf|;CtXHyv6}5j`P%xv;4gP{S2KI|$JOk8K?QU%mUc`AWLER`bdrlDf7l z>E4Hsj$+hz$z7->0zVUIH=>^o=Qg^bY5k}~VIq2I_tgF)lY)#4SC=Y%#M7t0zb<<9 zi@gCaEo`L4axKV%c3uKb@dH7nkww|;!=PPnnl-AMOPo#VOmU^tS3%inU711Xl1W0> zcD)L0OKpXU8Ae2kI0b`*jGys{UyiRrOPp>VbMV4qUo=H9`&9!Tf&zqmoeJPLs6foX zQX?v(2Ag%EHHQV;kiNiPp*GDO!V)%rD!-HV6K_Q84Ik&1X3ozop5~tBHIZv^MmF?{ zED9XSXHgpKv2=Zrl7gZLWRuYLPQ*>DAi$4@YL<5(Xpq@K@`j7ZLmabHjqK$$jHCW!}I5(l$49u?`0uYmh4I6Yx z0C5NUB|(ZCP;QAlBnU*1O>oB{FL&N?yxlw#y?z6qPCq|cSCaT~wqYN=7WabL$&!HP z#cb2-he&eynrdm=nu&}f=Oh$E;III520A8qw84<<8w}9l7ZA!T3%LaXfN`>0sD8R+ zRJfp-7aPmlq*1Vn)a-~JNl4F-<~gXYdDM7RB{kVvn`{m3gmMbxbB%1EdY1q;)*SHv zNPEkmD!=c2_#8NtbW2KicL<_LgCL4@hk(+cAkrxyAq~>q3P?yuHwaRKfOMyHKl=ds z`Tpm5`I})z=e)RM-+QlhT`R7|Y_~1$@XH$!v&P7;?Cd#O^eme9r=L=)sYCu0Bw<`O zCe{SDjTex^9#`_m3<2*bby=!AFbox|rfi(-zNV4F+6eRI?VvEbXs{f>YdrX|C zyZl|y>u&9~n1Ca=D${2reC@ZwLqW@H!p$TAH<}M&rMWanrASkRI%!zD+#Dir?gxqO zmHvJjeIPs|GIi7nN>aT=PEy0GJ*AS+Q6@*Z;qnPEl z#RH%V2^bEg_X7SDG4|F>p%otV5Tv7-Q zC;8~QqK}B=yR1>mjnR4t3{wyG-#`8JpA`c-x-SAiSM?eM78?xoRJ^GhG1nk}Meg2F z^|ZG*RG&1!N_m%_pbaczhImq_ERkBUot5!=W(a7kb9mHnHK|$i`W(1Lxc1C&#}n9$K=- zBK@m}D4+hqcRcPaU8nAQ#tKc)2g|DH7_ZL_)!b=RL&0kFyR*VV4QdWltj@38XEvjC zl3Ko1JLEJ?3g-jhxl{%=E%NNd&0Mz5i!p5vfdqa z5|=@~wPkcLoLOIUl3@T$DHM(>quBikOG4T9KU+7vbE@H8DL=;w_d%fUrh5YJgqndl zANOqCFa9?gBi0A{?vHG`PF|Fn9Hvp-8Yc>|?j4DmO63mgoKUjcx;aQ~6?2|bh;wl- zs{ApYwR53UqZbBoccEEKlq*oi!;i1pSD2=dX*TRrEd2PU&7R?G=d};fBo8ey^AK?h4B_xZgRTy?R$k1odM~lN`g5=E z%?Nfro-+wY#c=RO1pRyC;0U9f zDY~0=nDfMW%tHomrO@`$?YeY}0K?Dlx<26Gb0&e!oi>cTdi}v~*`H|w99hNI4+o;l z#}{&0aqi)zCe%z*B_F8{Msz;tTrcKcR4q|E_+-J|N9a>_#BBTAA^cG=F3GoPcZqA8 z+notkbi(ku&;DoeTE&yGDtTv>3f9*-#o=+j>L~kn-l~x+KBP!jM%X<(C3_VA@Zy#Q zo3i*w&OD*g7lB`Dpe%r;oWi|MM0(1FE3dSmNhVySR2wlPmw^Tr&D!m#-1i8>9O|Z zd%wsO1DmnYXGnih9+KKn7E_xai3# z+H>0Z?~90+3vW&0j0766WijvhDRbi8{?D`g>ne!2?$r2yCQ^i5|5o)s4ISZ$R}JS^ zKLPx>txoz9si0S>)_Z&1m*ROJi{-Shl zN&V`yF=s|eFDx$%i$6JA|BOkEm6gJO1T-eXYX^x z?6+(CmGDOl?BhBS6c7S6w)J_mc>&#P1|D3C8{TRWZBer=KHzqAnlKnPO!h=Yqehw^ zrIT#wI7cQZeW%OkQ{4Jp&0h0ZOwTNhuxIrO?o;6n1se=(PSBEa@6k<#^+Cv$7XBtC zfQr0`kR|ZI>t39g%aHY(r^Oy1Uo3u9EhBNtjN*1$#Z>c|NfPE|@+|ER0ggV&pPzT9 z@SN81nqPjCw(lL2FdJSn&AJ~TD0PZD6G5nr1ezS-qx5PU=xt$}r&*?8dGRALUPv_E z(`1P#*A5yee1}Hf*~X?IHt!3ez}>VVGsu6j(Xb$(Ww*Ey*Zcu3{V@q2LGW6nK3myf zaJ9eq>{Xdx-{LhJ0b@u}%Y9qpGjAT2z_!e0&lu+NwNbky_3maBHA=n$xrRE9p^V!h z;+I^;T#x7$!kx75Cq7F&lSzwTK9invD7av~HM8rpAh3o@egem6CPHrq>x-583XlfL z>yqTpnpg?d5-N{uRDWcMAT+rqefOr+IzIIF{XryBJdww72Loz%oaibsYF)8D*~aCK zhW2}x5IuI-EujMx`Kj^1c7e1k>e)q0+6IWqRrl!yP^GTlnvM+G$*wLTvOIr1z3QbJ znX+0i`D5$>;ZDNBxlTc{!P~dlD43jnMU`%vE_`?VtCN=a*i|;=i;-dG=|~2UuIT&Q z5^~hb5@$5hY1)Wk`IpYUG5Oy*{xBs-_w@C|bL!V8^YXrE-9u8K__D5spb)}?x2;%_ zBh7R1fhN?)AYst?IS_|xfj~aV9Y8wnA6&rzI(u&F)Z$=?*IHlAW$$JlOj?`t4@o?_ zr8u&yVmSY8^}aF}{)gBy{_pCOqrLkaC|-2Dc3mZ7rc%iv=P{2!O8$XA6ozh3?+=^E zq4x(Ln_l>{<)UKdqY94r9W5a@f@5NOmd;Sy+juQc-kzg~kPcWIRR7i&^TXE7RKx6**zxf&M)Z}0so=1Uh8 zP>(~hhvC5cmGYa%)`>n3vb#;(FLu#LOmx8a(ir}H|*ixrhECq*yDa} z`U>DZ85b@h41nb{NrUEI5I05*JZn)q02b{UUockZueCn=qFWxv+d?e3pUin7j1Q6Y zsq;BZP~&nIklF8zJ7|$vdN5?YN-T%rDk+2VxbL)l75TkobiV_)g_olK#`FW7&f&qztjLr&ykgtQXK8%<-n?>5qmJ z@y9{eL>xZx^I)G6)QZbpWfPFbu)zOSZu$|F?aZ+govIl=qw^X6u}|DYCD3RWHab6b z271AGS9t${A=>vtJGt5$xSnD{1vQ?M;EqYBq`Gt z@;c5HE^>^=7EB{V6H3T6tQa(N@|0$-V6}k@b?X2Q+7JqH1SWUSEei7XX4^e>U6)LX z`sm*@9njYCnxgjhr=rpy`i0$80TWg3OU`Ua$H%k+Ygm+dvS(xWzaum`4#@Du{b60; zQ}ALGZ5x5ZT6#OIhiEViJ}G(B4>7Ia|KNja9k3mErk(QNp-{WWqadJ{G)2AQOEBe! zCzgFdDeEU`?|%A50J&NOU$!@LOe&hH!W> zly38Gt7d!W+TC2-M06jF#|c*V7x9Ui3J0%I}Rq z;BUq={V4wsM_p%SS+fABxflc89EfjT8+bZBZsHAoes}0I|Fjk=BG(H&% z8k)CanE6OQU(HW=8QCx!xEfIK2k&ZNV9k+5>V?>?+&<9ObN7_^VZa@wWSg>&UhgAB z*92`qj}1ZA%RViBOAn$DZNb6CE3NrCmu zXzJdPN9z6N=i#6{K^herBXHd|KENY-_ix*{+>Pd>%O@DO9g;B;^sXi#2Jm?pp??z% zE{ks|qyBbO$o-$63{Hl zh4Tvj2f_760sOb#not=C2&+_*GFrm zMdTJ^)$LRy?%RD7^l0mP9KlK9QqtG(AGNv}5!$#d{Sh9c1~Fe-t)%Hckr%CPTMl9YyiQyQXsm!ZULSv`$x9+ z>n9(#fJFS?;PM-X^*5w*etQ?00pn4sqCIk3PX{|?1uaJPjGIcULenHt0y*eDRZ}d{ z8ox$a+plWEcZqfb4IFR z^7!2S7Vopg=5%f8#SE{tXmrmV;)UDvuB8pf>1~sG;(VQ=2xFzX1N=ODLEQ}nz#f7l zLITDy!77fJe{73;(_o9S`qQ9^+K&0h9U3n2#p*+&?`FOhyGRRV`L6NX71C&b5D*gd zMZiLVTfM?<>f5xx-VjH)1BdN%cB^2x1o&R#ztA7-;#623vU_7*{S&5#Jp#QG?}Vk3 ztq28k=CV~s`ka5%Ue7pEef&PEdnG8r;J&NV*R$8^7Egy@<_5|-!OmFcS`UyH&t9Pb z4PCgWbh47t+Lmj{20QMmBwWt_WW#c3VDGJ%1DVpVoiAS~w^OV=r(=aarasXB%sq0* zWtjT*NKa;x%_?s8&9Od4u&A5aWIyJhgeQh0TmCJ1phvg)0p6EA4IEp~0Z3`w;BV-= zFwOZpDqJZ#^&k6Q{h4R>Bkv6Le+A~=40gx#6-m3w_?+m z#_?j(XXO!WDu$}S_gYu0hu~S{z=iZMfv<@&tRcUt9K;1{0tZpWoMv0!@OK1@m4pr< ziqTGn&pT=czRakFd^cekGpW#?pEYAUjB0HSSetU~tzg}IWLJ}_Y;@`+s>X#)(I$@# zg~?A!V?!a-;Nhn{U3$S_Uwkky_zFfr!`Z+4-)m8Qbc^DR#Y!7ap)e2ArABJqn1;(C z>d_yyvwPhb!OW{~MdVM1J{7+~60j5}uylD_^(OE^%2}`z5m<0=ecu>3DTI6div!_U zh|kSoi6Rn+sZUWA!D>8x5xx6)v846lqOzhCF(|?gX|Xox;<=}-!^vC@Lq4rSb9|m1jFQ`xEexAAbi!WbhzkI{(^}X)SYHPI6yAQ@Ya+PY;TkUm+FD$pJH{b^a zNJpgrq6zyMYl_}@u`QlJXY=C@Lqcf5j69wOGNsRX60$^$Sjf8}9j*i=PWw47%FUAp zw(cmIYgy3oIyzUaU+S;RL2vO$K=9igeEYwQK0BPa^a@|Mq8$$9U% zZb`Ol7zau|DBSgSnEMGy@(na_D0k@>dT5yilW4;{!%g?8Qz0ACPWn@hr^>b{YGI~w z{OLbi3c{f!tDw5k+piTACrcn@vv_5Dz6j11yA-aG!S$^=j|GqJEUc8Gr z3xoqZrbv4Y*CF$>Hs$4e-=ibt@l+~8l*(})*vhM`M0)TcIL~JRa0gl>>6h~$^d0KS z!SFpYG!t%9b~heS@oypgUKWnEeiu$~KiumbN?6D-#QsMS;W(uy zkA@w*Z}|5GxLWGFtF(O8X93J?^+wx?YLqu*!M0d z*&4}F$&1~i>X)jtL@J8TX$+Io0l#83{i!(6Lgz)t_f@*YcGDiy;B+dm@HTmqzBx5N z>8Gbp{v(G2(Z7331(asn0wY`>eI0_yze0GPkh+_lRmWH%%7cI3udV8o@eMN-nnT=^ zk4dwyrPqH%niLEr$`Fj62VfXykLF@p&b1Lzr<@w4s@Esgo_w?!w~Ox)h3_miUfBH; zfY!ePtOveVy{@z&(utv|#n6+CU1Qp~!(Km2HL5D3gF{qHVn}gd-)QT(Ap;Uzxm&|B#pIj&d)wi zPI-Jh%|kX=tk6n8T~KQ2>)XEtW+wYZ$h9{OZG*ZslO}+dlLHGJAmn!+_n;4N#|&-J)*MbNzm+)gzNKkGh*OS%z}-u!PB)^&a4xBHXTd^=lx}F9 zmjgN5+1F$FJ((|2!jYKyuPUE&DOJ@mtE)s81m+(otpkNT0oG@EUswm?2VMf0O{7=S zSQj5^L*()Mx>a|ddM07ke5-keEnd)Yt!RjvGv-V=NbXp=t6z2fvdPld!deoq&Pb0UXY7Y& z41wQ_TaxPEy!%+(1y?_s+!Cadn*E|5bLWjHeTYuht7p`&mOn~b52=_Tsd1ZHt|$bn zLB-R<=Fvo?vk+j!3xI5ae}7+7pyPw96ga%f?7PUxC05pN`7Hm=lE8h7b`GBJh=lEu z94TKm_l(6Da0+LrCv*57zQW(b9u@bs|6=nBX=$w=`+{Aeli$r244>p4P?LhyR{;(E zUUiD0)aL$3H#mD_uW@6Bl&>rLJ}H1$(@`-y(!7njh) zbkYlnp}H53?MlMkdE9-&;wl~3UEioPym~{#o69}w}ep*FDK*qZ==dG;%LnZ*9ojfHLF9)N5>CJZ#uNUF{UxpAf$|y|O_v2hKK3S#IbI!?t(-(2ty0P9E8i!?gB`DaU(~|{5Lyrj4^8!l#i2GN!L~>;N2dsNSfXdS~vc?4|9e6wk zXa)uTYd4(juJii}?I--!6W4`-Q9ElEQI>(fOKo}UTx)Roj#|eH9!`9^I^vwYfQsYb zNoO-FW&E|n`3f?6$pp8384wi!$k!2;F^Uw3u?h5ap)1=G%WrqH7ril`ESH{?HMrDb zmL7<_ywgw5v4U%+(a8RyGV+Q1!unzu0LrzxjLzRy{sh#FuEBzMb;X46@ za)TAHE0CcZGr0nrq!-4gX&+wXxbIueD)WrXSkkS9w0iAr7R2Tgf$2R* zT>{PDO(90v*?#W(^=XE(FMZMGTLeccc|74W* z7cCCG5<6X522V*eYW!K_WXxUjS-()57u{WNpm3x9J+qxW(OxI^%h zXC7q|)o$*-lGq>@b2U>1xf6JzlQZCn(OJgYdU0`ie%bxa1jn$(N@#>R-bv51KEkcgc3L;f-?X~)&pCq ze*hPE!p5U}m*ibnV@uKipeN-`0^slz-D^2b4sR?z)9cUvr^+k zU~HOz0xA7%>BA{Iw3pTPLhcIBO|btsjgJh3^Hki*_2^`M%~&g{$xGM-l(}TCh-Xvc zUm75fO5E0f5tjF7#~|MF+`K9kAKmp5JtCKG279|J*C#a2yNE$x7XyH}cz8W1%Z^2W=Ri<9PFvJsAz?SR47;}9IfCwKOk)cD z&ezB6$q<)MY^1hYoBV3eQ_fLTt+xD?T(Giw$ll;V4|;zFp;r1kpFD(q^!>5_NHQMs z>uL+H!w%YjF&k$G1FdoLHhQ?b>E5oSQ6=}*6Ni`MB)t#%aYQ}vU6f_&MVwSDW)=65 zorrhX8u|QTTFxPcwF}0;ql$#j^vAepwL4&c0pjKjs1}eD8osiPcY0^?ObQXQ4odeBSiVypowL;WUbMmYP6sVKUj1Kk(SQm+qFFcu%D~g;`HU^H3u{5w36@orSEA zCyDtyMGQP9`36fW7IqY3p$VGqABUmWa!?M%-;M3Hw%+{RI*mNSh^vq93B|U$2<|6l zRC`(XUa~Uij~GvNO8|zC4dY4Kmf9&B)9xd^jx2O|q=@JesR@>O4Rl2xZ)I8`4Uzx8 zE55Dux@^u?wIP(qF#MiH7w%!=nDAq^K;gEYN206u;#vzG*18dgc)bL=akH`n81nU= zCRm6#eFeRrSntT-O7*L!NKTMdFU}$uN@L==&hUivhM>U;Uihikjxks{PByd0@ByyK&T~LCG4Y>`wyh4 z_B7j^`H9Tkdn+4fQ}ApF226ArApH(szX#irVCIdyQs<}8XZgF&1Ii107+ZQh*iTz= z-1ulphgfcNm#CiH{~*Qa%^s)735l&!9+N=dZhNHZS#mMdq+0#T-Rk=j5ow@&e36M{ zf;x57a^DuDB%bm>_=?#0Po{I|9UNiARkH%&~S zRO>@pcfr?Hwue{@jDZDt{a)9Wl<}x$JiY2?=ZeIKeSPy((C>hi1gH(W`~HI zgU!Dcbag%`hQg$Of)jc)!*F$^G~YY=Ad0g;`7Y}8lape!`?GO5pY_!8n?}3IFI!l; zWLwYo0+m?tE>fHpp&W`cXKI8J;X zef)wEG4@{fg#6AexDf!+Y{CfOWMJpvAXr{|Fh&5u{~Ihv(&nxFG=9I08^ZBfQ|{7` zbz$fZpJ@DMsDnN`^P`=pQVl=Uf&#e{`cn1xnX6(KENlg_KM=?a@+P&uy;EHR@&|zJ z)WZzFf?6|Q(C7hg7SKiP>O9m@_Wf2VbfL8rl;Je%AB@j*!J>*uAWfgD{P7Xuc&i|N zDP8tt0`>~d?Zr^3!K?yjIpLLzg-%>cDNxOIO3a(Z(!eJQ=;r>>(8 z)LkzpX*06!HqvwXB2W%@6+p?xK3rUpxU1O5I1%h3I|xG48e$#j)VzKGu_|VJ2T% ztL8;zJsXhCge^#V)ZLdAiB9I%f%)0e*P?>r6|YNhMH_!SMoxoiQZ(P_@rC(c;h!fx zuy?FkTF~Ya1u6@~IVS9x?)50H@LA0#$^_z3HIjFo-sU)c7<@9NTy=Ta1VjNP#8&)_aB?5XF;EAik}Up8Hch-fc_os8^sX11HTX8v@Z zY;iw#E8)e9N2;_PLNR0T{JlG@We{u+WJE|USk{kT>+JcEX0WVq*7qjEN4$5kvhnw6 zTPcqSm3%>j|7Q9aJbO=b2lvp^O1~qhi@q#xj??~ zRSMb`6jDh^Q{*`te8(X`C+=Mjdg}PjWNsQ>Rt`C5mV@)212h79U68mx1F^S1Am1o~ zdA+0z>I_zs7NW66(LqN&s+7$;m1*8f&)j!zNhL%3?iB%1 zwu;U}Bn8mlqrKX0QrKffZBCc%wiVA`S`!PK#q~F_^Lc$3{m46H+szA)bJpfC4?&@d zaH%H&R0w1YBqqB5a+0pnLd^8PoJ9Wrc(Z>ySmYlkDbBg#B;Lm$s(%v$t-1c`TJ8zz zKD$8d6LkB`)WeCq?tOv1H%qKo5L-!s z-z34YoV;KBkQ%%a@_z_PZqWY{k}QDcj`rb%BF7xzo-d8j?=Y>S4?c zi*XJ+K6>;P;ioN?*8T9i`uY%coRLo(w;x6lLvgn=JF3rl_X%razvCX#rNAvCp(AP~ zDGVBjaS(RhI2}Pz_(7gPDPO2)%7{H~Z1jf%DGj@X%dn*U&s1I6jHeQxDrFx_!`!7%P%Ns;vg614B`Y^s8{=`(;P!AA6#_bNJXLqsXR*U1^siAg@`tK`% zh|r7q>xdAjB1Z+o4S`Mk+r=3byE^LFUBkJIlzi_Ma$QIQhZnTBX(Nrbs0U*ADv|Ly z_VIWyzZJwnX}FxvqBXKFiN5Lel?y%CcKdYh0gHChoN~AXVx?KBn zMbKvq!u+4Ku6-tuzk^Mrf^>Vy&6i6-A71Dd`eJXBTS$;w9#BMwc)kH zmX*6sCa|aDT6O+=LDqXAzeJ+%iDL^hY!}@*Sgq2{oESVUxH^9)y&c4pdI0X^kPxS2=&h)@{;}M28oz}+w<0H8u!<^`x$Y^r)-+g{52{BiO!kAwvA$sKZ@8u%M zAec~esoY~kR*cy64ID>H%;?Uw@329{#G~!FHM>7T6`>ge%G0~102@()LK?v$YKZ`6k@bQug?-?8C|KB&^M>i^u6aX)5PwuX;ObRV~VVn9M}DZ)!e;(MWVp zUG@nMrhYbNEuN{iP?u@?cTSaLu!Yxww{)L@Gt@WW1_@rEQq2u+X@Q$BmZX*l2-@7{Y!14WT9b5Guy!(i;jC=ScO3cj)5WB!`jN$%I9&&ZaB=6vitvMf9-_wS=PC11P=?lOAyW`Zp) zfwsdn+zUTYMwKJxWyYh1eQ<36rgqS!e0iu4AY0(+iw$SlaUk0_m#?MTi#{l9x&wvI zpL-Gz*3k6arhUlJMlzFGsE+r-01)siLLbyQiY4H>UHzlv{fm9D2cT-DImivlPoIl9e}V5V$Yar;)Q8y^A9VD{Qh7-PBBlXILB zx(b(KXr_GXj(*;o+1yi^yg`vKEFdOeb3o4zn}=r=BpQpCT64Nht@T>uWpVuMqe6rl z-&sin7!wDn{>kjfHBk#zeP{X{egCe8^GWbi#5f-<{+cxuV58GnjaMx z0EY^oZ3vh_+lDav_7)fanGV4$vQogtZF`DImJO1kFzZKX0ls?6u3rnbbmyPP+`Dl9 zny09_7?7=ufRFJ-zR$)sM5^&4$SXL7!A|Nx(9{C~F6;!U6)S)o-F&kS&cXgw(>dY! z{6>$%RQ@N+Sfb|snwzE<1DXeT{r&FJ!(*RMfAOY-c(1x#;9!pkt6^E?#uDs-GUK^ zAO)cM9<(%`U~Sym79Sj7;$@`!7+dJ%uI@#yTW@5wu>1H!sx2XtU7FchL+@|hJwm}g zGAooAxA;0-^0a%kf{|TAFUEvD)qJDq*5LDT*vkM*1ReW$J7_>oR_S>GouNiyaFXZ) zB(gZw)da1f&(C_TnDT2Skv^n6qflV~Bcv~}3ki@~)6ufvt*dwHmhx4m)q>0?mUf20 znS6+eDFy5xgSlv1{Fe{+4|z Q>p%kBXj9&KM#JuA*3eO(qsuGtwz%4YlUX2W|8; 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 I#5GzKO7kU+S9^afV<^hie+5)7+yw! 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%0AnvT&k~lQYrkUGIwi)}JK3Q$MeCa634g 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

    d8jpY=v}T#Q+oycwm*q!C-;t=qiG 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

    =6&|7AZ@2Y~sx76MjT_WMsJo`GNe$2olqU!9_ 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

    wmY|Wu%Ijgy>y99!^cHQ+| zNZ7*eZOfGA=0|Z5# zg$6;zcYOj@u3#`wd}IN-@AO^i%sKfTUOj2~8VX@eV%m9oY2^{(ypQ#!1*w5k18hhM zz@!2DL<6{;m}IR8$RGv&dhnj;_k*O1jm$_et;RufJ!u`AX+}RFeZS10txk2|oVQ82 z**N=Y@UyZDjpKSB7=+84>hPj@A< zrXibs9PaZ&@UPM#jy};E3bPz8Z>adY4N5fgWiDP-e_fhGbkqMTL){73H^BNA;{lU&0dl= znM3!R(y(2gRiN~Nps{`t+?Ti_04)m%pWpzb?#7dH#L$&~-3Rm{?=efLeX1GI#59^7ulREb3ViF*kR+@*X^VESaszBAfZsp}b_}M?VF*zNEHVg)7fcB}wAt3o-H}UBZ)PEWdX&6@alk7oU%Dtb% zQut5_fRwX-JpP)=p2p`G#5Eavx7ZUP<8w zlqEpyQvlnS0Cj{tkXP9g9Wg~^O{3dZtPCuu-dET*G|sHsa7@dVt)ud-KF&%^p2dyR zs|-LY>u=cSt0graWB)ajg{v3w>V=jXr&Y!Ve456LG_Xe}w?nALQd<~(d__g{lh&1A0L$P8jIyXoa-b)|R)qN|;c z+nd+lpWx3Mm^?(RbhD07mQX{!v`Kjo)*$nEBrQ`m~Um;j0=NX@C(xxzag_$e(woa=Q2D< zNwr#XnPVwdf-bf)=F1R{CFRcyY4+dTe&Bxt3ev%3=>Gr(u;t%K1ROPRNB%FOAPtoP zr6-^j8VEY-XIFXnmZ?h`D?M}^-xD*j#^voC`A)@?jk{M5k7Td)2bq4ZwexE29w@Uu z5jVoH52nFJBIYK2*!1b#rd?C+e|{UGBTT9ga8802czAEpVwKPuiJA-RcQN+jjov|{ zj^l&KH}6mA_k^T=8SEM#2rXP`<1W`ep#Stc>q9Sj)M;yRIQ9ZbPQK_`CR}(r#r{%2K#V(LkJVj-q%6tooE+mMK#w zHBzpNmvvT^y7|nVa(O>mLY!T7-ft*Dg|C^Ca$v2ENtUPq?GLyHHu4F+b`4lN2@dLQ z{JZwm5NWk$+xXsFi%=Dlb@PbD9|1fldr}ri5j^LwJJ3z4O}&+AMzSxxRV!~~tjbzKK|@U4@SWh#V;gcUMV$Uv-eQCmdef|LLeA&b&yO}okp5mLy9e--93_a`E`1;2aVJh8wmK^3) z5BZk7<*oe~YVCdm4t~UdUqAJ=G!~ao-yG55W^~coN4!h=BsY1PKge&;A11X2j?Q^F4=w-6^r3I%*)DW8ANbg?w~-?jL1J==D7Hl5v5i9IFYo;$qd$t zB?IuQrQpR}1#5ZyN59XlvxAuB`33s$tAV@Z4$&m&YGvYArS#g8HzOxM9%b{Y_`fXGFE%*;^fD zasTm%IgS;@><57k`5k=>$}iWc_^-2qW>y%g%n!~*^Dg^KUSEoZEjm4quD|BfWnU3= zGAqM{X!E9{?1_r;$SBjYw2$csGYp@j)$vVQ-%QrnBu&lzyp+b7SEem1?WacmPF1%Z z$ds^?xA4frile9S9o>ea;+B4Qy|Q#X5XUob-Tds!mj-`!0zPuNHLg#uzhUI=nqs4)xSK+kSqB$ zc0iBguwyCm&`19Y-^3$2$gA{6F*6eVBQ35;gG_I?*(1XUimaPD{hHg|tq6kkz<@&F z9je}I4x1g>({c~pag_O?UV5+FaVQ1f=tl+0Dp@5`&Vh=4Qw-f*<@Vqj%H8YxJ%y}& zI4dM+Rs?15!eBy;_uGQD^ zZ&y*$?Rm24ub5_WyaFKs8;oWggaqa=2swC! zCpQyO5bD3GK&KYXIj1JuiDi=XcjTN@5XO?(q?aH%N33Z4ezQ~v-pKmli+Mk)&+kuW zeo$QX)!n74_$?>UNyJGW>>VWmCl6&qgl*%{$zgm4lVC%p_e70oKXsU);y8!vJxW9W zz^qnEauw}SmiIvhEvnuIzfe2BdFHfS^4q<&XL!3AyXA{yY}S^-sgXAiD_$=rxOIc^FjA(8s^ce@~yk&Qzc(wtxJfCiq%P`O^Py7RXNx%t8lQARll7iz)GL5Z}MH);8_h z6k-d_(MP=R>90T_^srEu_Qe8Y4?Al~cfG1VdV#_nn_gB~R{>pwpr!|6vdSDqh54v; zAsLzH6?A#@-~>Refwlk7q^-LkEk0|A4tYu>i3wo=Ux0I64rKjTqE6k5!cC$Fcvgx($+o6zK$);O{*&FCv4fF>o(F+<&YQ8A50bsxercv{M>~C!U_NFAS!glkh?R@`(dY4udQ9Q{rd|~y$uxppV~s%pTGU@iDuoU@Tmqmw|@e1;Fl&CW*Vw$_acW} z+nWM1L|cD=ADNNb_E-+lAxdxg=|BXbzi2wy1^K&Oyhl|@szrU@zY_l-eN*$g{?g9G z=Kt77Lf$Q@49qJf$TyNmV;lMd+QLj)Y`C!m>l)Tth zC>-k>QNy@x;oHZtR#(X&ue?!fG3tg$ z!`L&my3+!F2}7?I3AX@w-oHW+@Dev>kbc6JJmD50k;XA;C?epzKIC$1dz@@SH#FQO zKhJW9rGMzeZqOZ1 z=6gHE6Q%Ig*b~9tN>Am$aHt}_{9v_MF-pA~Zc9jGb6A}sE7f9T?E`m`)mJe(v7e^A z*3ihT*1m+Tt_=5A88^I@PU#GqvmWrcr={>lD2Eixg0R~Qs6jD=`g`q3ZhX&<*(s_;i9>?Pj`Vb6V~JbWz5i&K8b^7Sk-G(788Rtbex zLjQ2Tenl%Af{PW}aGvRWa#w&Cf7%B+0;O{PjajJu6VX`1wz7c|+d6Z}09MW6b|5so zc>4Wol(p&lRtI7LmXC#=x!Oiyu0-$4JKEoIN>zG$`EMEty!qP}xK4$wOJ}DB4nG)f z<{YaMNIgbcW=*hS1-Luh5fJp2NK3zm9VEz6?uk}%ot!S}h^PCY5kLPSsH}~fMOwul z5tA#x9JOcg8C9E@P3w5dVFoLsCPCGoZabajFk^@B*;mT`Cr?m$GBgBg!ArG+_q7z= z`YzSKG~2nR?|SFjaTqBsY$ej^uAe#&CNtw<#&P9duPp*N9oU-Z#AH zf0RX_6Rrlq@mN1Ipm{?tPvb7Y=J!!47C%Ir;~0yZ_5o$#pkTBK&nfHzME6|p5g@BT zeV1PWSo-;2HBhUQitn~XTYB)UoK#6Sbv#mt%Hh25+sjMjrFTv#Re6)Mb+5d4sxOM77-HvwNN z*Y^>ZOw&KryUu5StDb(6b=tneR4nXnWh$}N`crubVIm~i*a>Bd4l|ymR%5ks{|~WH zR5wUQ$mHDifIml?@?}}3@N^MX&#;+p;esmQkS2azjT{nvKe0n3n)}tzL_ysk;Qm^u z(RPp=f?XdH>iI}yIx>y6xuW0Z(~{c)T!4TyI;81~BAA4}^o%_Jod|L!=5L}EUET1DA(h}KUaP{y7DK=Fey^FveAcUe8uV19!$kVXd}Vr& zFnl7Q!9H=2w;SB5Gy?2R19;PGmvYj3q5~Q@OUZgg5qUCQNj=p1FkWO4weRmG_TmaV zsogqm-eeIJ2gmcl-7>Ns`$)!V$+YTwuC(@Qt=Y?+?5%v=XbS0a;RZbG$Yt=~&oep7lJAms5Mx0^-^|s@2 z2q6Q)ApSMBSIhDHVEBide&-(R;ov+i^ zT&?hYZ8RCI4aLK-rj98!9@iPa zaih!^W+6DNZX*_utB+8rwsoeb<8>fCPoTYwdn^x_-6Z?qXfF}4*B-A>%yr14KYN9) z7SBM3q&UPv`RTHg7c6-3ycY>vMRk3ZpIUl41)={(dSUuH6w6Hx*}We37`X}9|lMdJYfZt`$>$9XiTJC zmck^rq|l!8dvSLWkI6qfG%9`fk*U$(6Y(Cs^&VzQWfoJyFge&%A~OEj4Z*(I*u3XQ-EO>( zM#{W=x@$60l{@Xh$YxJb%z4+g>7a3wKr1;;-1Z)Gv>pchP$s#NevU$V@plc`<$C#-J&MS6c)_|+r{dwAnPq#e#8tW48zqqq zBDBMA2Yr6L3CZsk+nKz=v2gv3zDzny=m3l2M;eBF|B}2XdTp}8=)&WneSDt>AMYej z_)L?LIKW{oSVdC7cZzIrOFUNYO<^V?FB7Z`gX^OBnu5vkJC(a;nWctSms)T-Tp8$G zfw4(@ffjf6M1QLaSyNSKC)IE)T@1`$Su(J{d^aG2WR`+8AcsTGf^E@xElo1)e(7Jq z?LN?LYdEm}rpxU`_Z2&h%ykF(D=@|M9c*+SSdVuIkaX}Wg0bdMZ0_75A>g6Ucx%)~ zfx2FYS}7@pGPQXACfn0IB4j5d1HkEehsvq8S-Yj_L4P)_Lb#l#+CZb@ppm zk5hZi1Ne>h7}jJpZS2aj@JF+3`b<83a)smrSJujl1E$5ps-O7ecwI>C> z#Fou(RV^_r9)U8wg@Ygo7K{Ui)Qq$80qhcs5=|HmP=1LDfuQ{(Gs-blZjAj`d#FP( zcGi}AIu?Aga4HwPl=QT&TtfGzpC(YJ!p6Ud#Nc&{Uk879JCgK8ssA=R5syDob4~iw z?YBahA3hYYdjllYKQH*d+JmFuZL82g?4Qma{F=EPMXlnnEQ&kFP*Tq;F;ERqav{B0 zkes}`Fo<9#ALNahDD7AXRmS&G@D*14c(+p)M^i(Fdw4&DB9`ipY66G?=d0UD7Dg>mnM zqFGXZrLWN;Q`e5IYxoS#9%y=>PC%CDecb|RQZ=A-`B(ugNtE>)TEXY9H^ilwthf>H z&U@^9m7sND6MR(ml50413iTqaRQpgKr)xbgZ0~EX=HjNinnF$fDDVFoHSk|-Mb8S5 z%735=oO~$g;Qt6X2BQ9_OhO0p-$Q@Z37ez|6MH6_Uupc$o+)ezjUmD#VRR8W36<9( z7#&1E^e}7dRppCCMo3u5Wh&pc6SUZK(Qj-}?H(`VNlW0;fZqf1px%@q4>}SCuZMAO zZByYHoQPLsf4=tRoRfBHW2YNqFSj=dJTO9`@!Jm{(ir1^4vD&Z|5&n}}=5syq%7pD}^43k~;>Y!NZ7-k?7E zjN}^cK}Ut#=#@(*z+R-V>azuA zB8*Stsl`Wjpu|6!zbpT*o}yH#@7@|_qAt4lvnO2sI9;fn)%`JBe41_@KUoa@S^L_HD z;u6C0=V{{=55m6)b3Dtxeq-+b-O7q|%OcqU(z9M*HY}SfrY9h;u>fJTsDSKPRDhJp z3$D3?;*po_Z=zHpj5bdC>go$n!-pV5-WKxpC=A!{`@KG2i04y3#Lb%E(c4we=36&6 ziZJ$3SIw>eShPP3rhFp8bQ7dOx*=%dHktuOLkQIXrSP=HDFgE2@1dFo$b4Tv;4j9H ztDHoee|LG_9&}M`mHk0g_EbGZ!G~7gUz}#(^T7n;7kd=G5zlv_XI+Mq6&Un|4_AI7 zMqPk2h=D?;f<8k0gFXV!+cq+R>ebu2-b@{m4K^vRi)SgUuSBi=N|yX1_*$Ac1e(&DuRRPpnJ(FtFcvcR%sF{xM^f~3hhImLXpp@UH+!@(_86vq0KVe z^OJiNA8wnAHzGhWum?PM&_U#UMkH1``%Wr_BB3hgqt*?>XktjZ^9=`o+ddEd4fBt{ zkeul07xHT{6)PN+SD`p&;t%#MnAX*$JY}WVUE!Ft3|LMnutgb&@Cg#Iqzmvwv;R6M zF(;I0CRz(e2sb z)+S1>nD|s{bh!px2hIWzh7Q)kUA1ap=&HR^zx@0+s1cefwV|6#w5Yiy>tc!|N?oQ$ z_8R9}GPS_B&*rYY1s&J#<9k$GD>Azdln*f<7`YuP(z3}%__0or25%-f(ZZ`gAc=@M z4__RPn)OT%#0-RB09EDvM^!=7V-CqV+fvgDnpE{QSL>FGLvT3^z8AU8$RiK{>L?t# zebjFxm3h57kJ6-t+SfK9&WaW0`+Sa4Pm_|1GvEv;-~(^I!#`jKK2S;%XOVl`FfTo{ zzzaqQ-quf`Sv*YBpQRy`NrW~L^$7TN`*shgUG4SQAkF13+w2Jluw57n5IR|E`yn!p zLmG~)&Q7BZd30itN>{H978?k`S3tXbd_KHgJ``L)#<`aLe^cFalXr((=Tes`L@xz2 z7hKjQDQuY&Z7^WfWJQv$e2O%$p*lU%<@eR~!b;_~LWGVr`6iD;tV%VAoNF@`>j5$h z-Y_rF$GDN_tbXs;$dBrnsZcbAU<(=G(P$$=2Em?t&H!#`?(d^1 zvMa7D#`QyFl&=1^y6IxguK@r&dnOWlxK$~ z(%D~@OH>I)Ws-rxyDcCS-BOHVfn!hedZsi4A^f{~Np`%iRg|#!qXf*Bq<77u6AZ}@ z4mD+6EHu_3t~w4n10jBLTqk^)YQk))s?71SE_^>aM7NqE8hhuWjpXnAxzkbfWm-5r zBb+&{Fqj?#U8=JZkI>qpuAXuBW=t5$=_5#{DGU?^IJ;_lJQsJmG>Wi9v>ZcI`a9R;1+s;8H(AOGGUC{8o*zu zCH?TA(^d9)(u#L_pfH{I#Qu?*4%zxmRu+GHyP2h+#tVH4Afhz@QTCdy26mQ9GzZF9 zRkNg*4c#SA#pKY7?mWy3cung$=tHc~M~+A4dzKeMr2n9j26`&&6?IrdwC>;jF(2P$ zUE)d0V@(a#AhI79@-a{t>u)fyFeeCZk6W6}KQd&HSoTa6n|agIY{m`X<4QT9*dy5w z9Hu;BEcE@69e!WZ-F|X#aZGq_?B{0|>!Tv$aZX)fiIF@sI6xCtYYVDGD>-mq3fdtd z8SqICt9+=re)kjAO+{#7o!8VazohxN;-H4G2)Tqabw2mUq|J0i;!l~eVuy4eUK-h* zvVV9$CTi9x%_}H#3i|t^Ks9>qmf9CG>+uru@b5{EQEbasQJ!%)l*MXjJb9S!7M_c` z881S5Ay)igynLVaQ}zNWh9#nwMpx9Ln&#+fc+LRhUi0dGns8Rj^$#oHWr4H}pCd4z z4SBa|_lewMI%A<974@|Bn}j5b1|;UuA_~b@Enx#_xXdY2d~-%;WuHuCP$$^+cOq$ z-bt)sznBng6EV-%n_?MdV>*=POl+Q1jQ1FOTVZ2S6fT?4y@CBOz3I~v0VEh2pe6); zAF#buP~UFxjc0-!{}rr-X(jWRHKC6OSb_DqwVJZ`h~J%g?N=`8=ZA2L`*e;B2VT24 zj&LzpBE3{dukBT)X2-S7*L__lx9mBYgRTi4l6;u}Ouqg$I}Q;9f;-yCi)D``3~wp& zMEPGJWCKID$Ibt__5Z)W`~SH0a165CpO&K0KP^QdN4aMFs+k<2VPyp$(bfuk$$sEz z{U~qjJ@l1#fuX#}uLQh3ZoXeQJ2AoBZHB)`fnqT3vSf3s>cg}Lg6j6SZat~tEw&&V z{Wf6855D#6H})#tYz|3jF+J)lJGs`1BtZA0UZ6d%eim&*{P6S<8cR*s&JI)60hMRE z`->wH+1Ib|_B&CQ76s4aHSjxC{*eyl>H>drHXSZ4yOcWZHWYb`E#aE}iKQm}Jx8Wb zZnh%)7t2*K%W=vQ{VnZHeu!w@B}XJ_D_cHr5hY+38$uH^t(P2PtivAy(t>h!1896; z8MnfB=FzV%s_#u>uKH$L7_;c%lOXv*KBE@_Q>}hdNAcuHOgjm)9voKRbdExC!}P{yoEo;YMjj=G|yr&h@7fq33;% z2oS=|c1?yHf2{|V^+i(|4n0ThD#Ux|n=78ccs&kiI7xPRA zG5llI-@m805flxWx6dARh&bM~54gQxWVYswIpTBWJ|eJMVeQqvQ`D~P_({JjhW9hY z9o_j}AnfP}Fv%Ju$33|e_&Wm=Me31PNw2<-o;~I6WKivPJaMvDz^^oqQyhxXY(BVi zaX+Kq3?cBCTLWjXc>q~mYmB6nsD1e^S&NXFQGJ#px*srnMuZ!%^q@afh;U!v=op|+ z)BXx5dc|BC#p&UWM@=(yEvpZQ0Ynag@6)qz_0f1c>+Wqn!GQ8!g89 z0{It_o?OQ~B|TqyV7~(9;lRBa=&didhk64kg5I#c{tNQ@gLbMX6ie18R>NeNhrVUm z=I$SUw)u0C*HRU63!zs^JwCJG+!jkywqLVVfz(kp!6&ARU*LE0q}cwnnNBILPSOeZ z0_b*)iGX*zhJoF8oCx4UqQUOrNsT^xrP3qcaj}6=ZMB_mT{n*Lip6vMPp{}xlqkMl z!%Di--F1NlAA-Hxc(!x$MZw_e*+&fPPtg~q&#Ox@<(Cjps_|hGz91=Qnga|0xd*gX z(LeT3@FtJh-?dFTg<1ZI9=6?=b>8*lx(k%Dm%QSECsv6BMU483S&xtoliZ)jT^ik^ zrEsxPb$}rW$}A(m%w>Qsyo5sJK@XgFVynh7oPh1NdQL%O_v1m0#VhP#x%znqZO$LV zCN9z;Go3-Mce@=$@kjmmI5Afz(rZkWnZ-7j9*Z43Nop8F*<($oTy}|`0W@Wg0O2?X zlN`L=8(!UR5wU}?|9yGXn7=QCsCsTvC8MA^6Xvt2l3Ib!G7tR7lZmxdm{4*)ujk(M zJq$wM`5ipUg_*PIdUj_>iO&5lKB2tuX)G|G)J_|#eLkd5$O>c1W?dbv5unJT0~m8`nX4jk8+29 zgn@-Uo;p zIMEOKass6O){Uk!xW%2G{B@-7bLkBENnd%l(2>#^SFvQ>EU~UkbkZ!yhm=Xqe*aj8 z?U2-*C1l<-I?J?s-z{81tK_2j)B(Lxx3Qo=z`zZhI&h?ohv1I%3-J8>Zv+e>Mt`55 zwn!eTTbI-1!cD%s0?+*bpB8EA#zUjTM6N5FskU!9qraXnR|s6inY~Ycaeww@_ndST zyU6v&EcO7OT?az>Dnyt7x3nzmLyTz^2;!JqEmgRZ4R8J##2s~_w{Q!v4R?MbaGfUD6lvsp!y?{ z;gK9KPfwFyK#Xy)Mvuoy&iW%22s$Pj{fFH-_@oqi=@8_rZ(P-Bqr|Jipr8#HH zD7GD$H!z6Z@g2ev5+r?Myk`xcy;wr{wVQ-Q)RU;L@~m>TXngpYLE#H%>l$g`c^xHK z0H9L7hQ(}xWJ!xclu-JJqSRCNCw+|q9Hz)i>3eTqjFCHKidAG;N*eo%O6zYIv{$5f z{BmevNlL;?*!OuoB`nBuPvaNFiO36uOAUM-uKDx^6sg1SvB4lg(L38bNfo(i{r4? z9VeGkB(t=iOTJSJZq5Y^-YRG1!UPOyU_tQf?=;ZmLsk}OZ#9B^T;=1tS-3*JW=gqJ zZg^!aSm8T#czPk8ou&hegDc5#$AK@betz7lyF*RF&*+Kzv-Fq4^&L0jQWrEFUt4D& z2=IB~00Nf}_r6*m0Y(cjF_u*xE@?sHd*XUn?oJlGZzbid12ws?+%n-#mU#o~5JbJySjtgs-DJiG3x z;F_;q1uq@~dI-*M2_oZn;QqlNGF=o%Ig=82@#Z^o6lQD$HfLK}iu&P*_(W3oaEd0I z*Wz&(wU2b37S7NgF!+c|aDEm$mt%kbD+5Vdg>xc+k%7%Q#!~p3ub@UOVG|^%(+G0X zc-!*|wQzwlh^DpOJC2$R%laB}g6BHfjG%Aw6F1Rrv4?4{j_budyW8?@ zlr|$vpml6iCs=cLyf6u9L(W7mt!I6?@f{IUm}Ra9O|%5#+a0ZyS)?fsxBTZYiOLUa zKI>+Qc<1oMqV5z3n%l6_&~IOrbtmV|a=Xtta(C1F(^ou5B;tn0KN~4+y4Tg1>U>H4 z(XM*tzo^IOAjw)b#4D0oa+jo}uSs7B$Yym*2e5$5Cn(p*!>DznF2^G9k zns}wo3Z>sJo&=-ix8eD8AT#II?PSi zoP)w`=8(AdXED7(Q}HpdD}UXK^)dQczuy!%v5&y32bt!K9MCm!bVhU^b5GR4KVR6eG5aNJ;H(Guy-M5eGsD@ZH9T8Eo~>xw`<&&K zuff4B*uDZUQP#}>4Y%kCAEoK7DEE|R=NmH{B`pTq4zq%gONldysO@Khfozejc$LZK zBxK32BtqdcX?BHXs9B^z8HtTgp6BP4WqOW3ude->qypm%RzfRC_Vpe<=KKB5+{l_t*}c__f`=<)8|wI-1)NXm$M9!p{#U;J zzrsVuAB^%!&Y!|VjOxqrdma*|@AocRG+z_)9^w=C(lCDDl!l=Vv90h{?O79Nw!>9p1ve!+PshOhW9S@70fmWzedB5h_UE`F~|xt5gFKS z@ElMWjlhI9luw!PfJZbA@weW}#?Ns5db?qFvSbC;m#=3^o@Bk(_^ok1mE)T16&U>u zx6ktP^Kkhh*Q&GS6$1W37qrGpp)?&CQufDild?VlOv>3c{Pic;2`KHN@#Zq^*867uewo9hq$cUm^UjB98-X?W zYI_Udb%BBDO`s~0I5YB+de^Sx8Hvh#RVR)?p?YT!BZe?${nBZxG#f2$(rF!d3@hnjWsKcU25o*bkk zjYLAzVqi!`4W1pMO=^FmEWLK~>FZO94tztB@IJXeofUVV<6130OLv!|Uh_=?Vv~!@ zkM{9?HnL(Rd;njE=M9L~KtZI<_cm{kdbF$Mv_@<9F2uAeFP_NJb(Zq0=R;|78n+7J zjNQv_sDjb6b|#^NU8Xwrl~2^u$HH>VXeNAUk;Y%S?`KPz~o4bZ1+1o>p4!uN} z6HlognFp8hi?tXo&T%e`r-1NY@!)?x)d<*V!A_JGR+7Ad>P}m=bvq{1ia`$iF`!@rW zLF(&^=InLmc-`N zp{tz>QX7weatZDP#QNzO3KBES5MxhfF%ox+ooVJ5B$V*B&Wk8*`QQTWMVE= z&$M5VqY}-nRbF)+`?uu1m&UKVlfL5U6qvJ_hdr-<`{5+I<7&+f6tpg3sk0z|2Bz}F zgTQ7>;w*#>lJfWJDi-g4o$S`*N{lC(>22vke3pOLSg-%83P(fv(Ph@Q)+@V)jt64z zdU`iAM~RlEcF+!Z#^$*ok1+Q}>xp}$z}3M?M=kICX$v+0Hofp;Yjiop0_60I{+1tW zC?kuiIao>>$)Jo!b#uF3cV-^EwIo@&`%5P5`o@jKQod$zXOBM9^?-VdH0Q&vg1=7? z&NJF?0jQx~j_{<*EfxbZWKttPJ%>|`?)c|A*q6+(7O(aOTC^((t_PKKh${+YkTTJ(gbYflr9l$e8YAGDnfy}J=eg?;=l6qP4{LC21gb{gMX_??M%y0)XvXwzo*}3 zhZ*8qCbL?)ofZ(aar=>2$!PCt7t1VV(R_R?IR#tgKMZk3o}gsXAOFXxWJ|h zY4kwvkjYuR9G2o7&HfWuFpe1&T%INhBInUVzGWG@O`J6`y;bJ@uvXm{!14< zsU1Q!)42fW$I?4bSZMdtdq{UIY*OXX5n*ExKQ`E8kRKa3;|tj+%)}`}ib7?6RP~oK zFYK<02{#cxeyl%OPgan@|77kOMaA)$&+eJyhk#c74dS0Q%u%WKQ;;CS`5HWHEkT(< zD9o$|aB<(VK4mmIflKB35oe?v4NvCEp@?GVyJtPAoObApOhqRsA1W~FxM#c^ zlYjPXIa&HYR~SxOo29Btz_ZXePJBQ*ah_+{6SxQt800AQ!r?ld2pEi-6Z(7F9LpNcx!J-~9ATiWnlzXb%f+=%>q&(%2^V>5`EexrU~l)BYzk0vSwY#EGqhzSMv z_W}Xp4(>0DV(T^=27hp*r6=6AA4WetcQ|~}ly(x~>SGp`=gwFv?uHp$i-C%pl(a6aEkRCqPn10I%vsOmr>m7N z-ODa0*(_}?VZQzQLZ7?TrT6n5 z`xqUb%Mpw-)mN7xnz4sL?ZjU`YE;1WpM0^^i8(Vg(eXz%hUb8Oy!a~{NcYmtiT3W* zj-&*@;+;}|cNeQ+mGE1)sdx+A`G9Vh=9fEA_T4R6=0~PI$_|AOn@81w&<8r+(j37O z4C5DLI$%kl)|9J(TJtsJx($68{nlyrG55WFQ4X!E0tYF4m)RLs9>@r3_}b5XM%tFh zt2`@I`}IsR!9UxgknHWp40Zo4D1Xn%DF0I21Eu2I6(O@AmTHoqx?PYxwOHVe1z|yd zeA{E&piW4U3-rg3`KP?LHL4gn27U}AW2ac@j1Pqsq1bw7x{@uR6in6qO3Y}xKT>yf z`S8zz7(~_BV6GO{Cv;g5RfK`if(o=Zwf;j)XvK}0hx|iKH1Lr1;?4Vp7g9f9Z`5Ie zX#2K5)H|{kf8eU##JlmZha;XLnN{8Y2DQ$urOKPi*?kqK^bm`P-_Toil}|`C`~UD? z=l;||{-wk1;Ot0~fBv=v&sqP)K+o3SA|`JC1fHfy1-H}(YgCd^9C9;>&WZ9hZE1;k z$XzM1$X>Jy^Z~wLY6GdrK9-PT|HV=qB3|@vKa_JTsb?|o8khznCyxGSAOA%=i3b1- zz2koyLP!V@lDVKdW$kTGdA*g6?Fe9Gy%YbIDqy#q-QANv$2IqEA>Bh+8lSrh6OSJ~ zlV)){>i(u5lswAK;$!oA69L#W6h1JxtqE3iOP?fJg=KL-#jn@-YkagKh+gf;OGoJP z!+=lv)J4gld+RD)OL6;Ra=Fh;H2J3qvdgzm$`5XyC#kMaJXPmlzk$KcW2^z(*k-`X zFN#|DH7%D->IYl*{f+EAMhMXzzcmsny;^vh8QT%XB2^>FaCB{4wwQ*~>x&@9o*Z;c{IM z6}6;8g=Yd0wm=dq|3YHo^+Sj7!Y99GwKrx2KFf391ue2I;vQAbagz4cS;)R~Cgx{t zr^L5ZeG6Yr@Ecey>p~8M&sv}EX?{ziqV_78tiq&gzELeu`K0v*i-hlDP)L+mz3Z9g zGg&moK>4pjLS@}6KN>@7ljGDY%M-kQdKne6-GVjfN5Hvd+`#vyQ^{?eN8>MPQ%c6x zO5w^rbG_B{^7BYi&J+&!{E>*dRc!Ei@zZeF^{T=6+}l$=p$_#36nA|W;l1bS(ibT3 zy%mG*bXfj1h%z;xCcN_#Yka5BBShC5%U@2<*?xz1dTckq47GpTHSs_B@|7@8iA%ZD z`)Ku$iA>ag@z|ks)v8?K05tvtZ%lYM`^ zq&M+s2Jg*3;$3`kh)pkPVQ$`X#mJDZqL$-WREiCHAH`bWb^_Iz*~2BYjgw1tmK!wl z=o{hC?sg}$EXt_hh6f->hF%u1pc|x#J(&b}vnOEu*?Hagen2KfeQN$RfMI|Ni#&6Z zN|o!2g`U(C(dKXOw0FbDxo>CP;i>`MsZ z_z$nSCN5oqHk5fzPf_(dXVQhXYVgksxZlEQ&(}2MVD&*rYw%-&qkE5zwd5dmz^OU; z+qClzH7j9+I(@IC0-shQu3LY5dw=-SOR4f575zc7Y3Igk!A4w?g3OuDV&P3>H5KXj zxWQUQkW(52j_IFX==WQ^p`zPtn0@Mx=s)v6 zoGeX#KDHt;cpe_|kv-}1D3_oa22+t8_gGN8W1bdcM}`xAe=ya#w(jfm$(kJE9Jt-( zIfF6Rg0x^sCp;GRmzo%8@E$4cLo{aI#$Ri-edINEVz-lBxI>!c)n!~nEY0@nXjqd9 zX?|i>^P#e%t+BRsl9A{tfWcu_QR55BfW~b^LioR%1fU|H@JZkta`1Pv0pALR_JfD) z9Cv)r#L;bBc{i>EcIan^rx!|I6288hsurUDDj4|y`2*vFQP1rm9m5xHjlXt|&3ufJ zi{qH1z)1kF^mH0{rPGZJ7C9hkwzB6jOeG`yDnCet6i-FHaQ^3y{_^NcbdL{$l3O_B zH4rtMDpCs+j3FAnUkNW22?Cj4cZiv)G{*Z`l9_4BBO}4w@{s_F<~$o2^^?}&*`d5;G#e{A)f@c>qH-;|k&ofcY*euKKS6j(g$RcRz$$NC zs37maaRP4{YMl_0`U6oYq7Jpb=4tmd)Gs8|bw6 zDiEMsq^YFK54YNivt+hY%H$$!BE+VVkwPZDaSMo!H?#9PHJd8*^u!?0xy^F&zPPnd z0IkIX;$E_H@Md9`WuP?Bwoqh~10ns7geJl5uFptT*p!L@ZHs`X|G^M;$HmHUFGjx~ z=gB6g-+bIz_tls>Cqp3Bs4B8QbGoYFfz9UQLcaMTB~(fxP#L>@wv;hQj*v6x)vbG* zC`)f_=)B3A;@~!N5q)m=q+N=>WVuA>%bbBfS8C#+$biCQ)Gl`I1`b#$rR+^`7(Xgf zv9fg*GFo|ZHzCNs-%h%W$O8WD*&l%L^ck4C82m(|BPlnBpva?$L#{Mq0x>$Zak7)*8gu_P$Ii}Ld?I4bF(A~})P8u6<(?`34dBCC85ac+l^J5_|D64kiO@PkQIkfH&_vMrANZL4Uyjer)A z6|o0d7m+rEM!OF*+9rc0Iv~CvfNbBSL~`XUMBYiJ6fBo;bZ!>b`MOp3r1O9IESM42 zGWGL}qV(jcM2WQ$pI4nBPwOG6%_#rF&&j9ZEs|t;J@K|W*4NT;21DxxXI+2)?AraU zh(Q?*`c=_e9gkAbzs@%K^zezza>-?dpwQKcsNknwTE%{K)k`H30fNBhOYiKfHuV|! zqL_lrnv8My1^3Lg`wJtyPjie_9MSUiKB&f2lXJA6J+*{4zP=@q^NhG~P2Bo!lzhMD zV02~Bae=jU!56~Q5_yRua@ccAR4GDca-0KnJZnc!s)T&D~n z>u%zZ`5RfQ(~4gdpCaHdI>{ zagisCzSpQ=x9IN}mVZglDH+6^j|#M$x=cdjmy-FaCb|9eL7>F|3_Y7-9f6$x2(%VJ zAgfY;+x9RajG$5ZGNI+c9SjHu1py8Q)^kKOz>NlhOo5t%`#%7%w&Clj-v34ft<$WJ zOqw@>dHKHW(|ma1=+*EdEkTI#d2Fj?k^0e5Et$I5qS+Ud8M|A7G=)qjw`~tp;>vz| zU?|gj#=!|L{vUqOlj8q-h8q9xXU7Pv%bSQmwD>wAxc&%?Y_&~AXniBy_nbO57GulxJRNePtb5I8}qLkG%YKI&cK8Ep~Oj~rX@opm^6iJ4jM~w(Eno} zwb9pp5-cYgj4Z7jB4(%yZ!WV#>d(wZKa?`XmIzAH1qa?~s{Zav5%gqcmtauKD9ROJTdW5{SYQIWL({o^7 zswX*>6Y&1;H-Jg_XaEf%1KW?j?nvypoKd-j1L6Jo?Bkwdws8I1=9fH=inZ}y>pX_F z4l^iV)KtE*Nk&}>H#mN%^kX4f?0%wyiN&L5{9au>8mw->W<`RfiKz(vtf3FKK$^A%gE$BpeHJOL1#OTa$ zh0p7~+;H^Z)#VZS{mDO~o)OdbI~coV20*|;EtB{Jc-WsnJ20@^g9nRh3Y4t4i=KuG zmsSc-s-9WH8ku>VL#d^H3-lNYGErE)WE6PSE@7OQn^Qx^VEU8`jg4C^(^{-EHD}cb zF;FT4v&lu*mjx-xslBk=wwa05vp3{*cRGnxIBs#XO&q)+kCeStbgVGVRIMVtgDEYI zsd!=Ab2gdD)ALoxnRUsDY4PKaF}PE-Of(X#3N*AMetjlTZ*AJqkOCkKpeG4#%~wAs z*u)Y#M>mjEB{bc_{xkGREp0>8S#HGBA8pU)V6XW3Mt2@KG?SOMX2yOxUg7EYJ^B^b z=1>O3BqB*G6Mg`GyDStYSqBdRSnAi5sJ|gKerHusyk3rEt2o2BpL#4+uWf%ynZ_D3 zJrc?bd@{0P&>_p<9bTMy!f)5~=4Wd{>Sz(#h55s*+kdL_0C^QyuN4YdJN<)c0M;UO zzj8;SGpF?CYP~^gQn_uFu~4Pu)s(fb5@QXIq%bH@zd#@T3OwzN zWY5yxr{k4@$5?}EjlS|nnD8fX{Qzi#6kPwT{8=*cQF0VH-e@gpO)9m zc#96yVo)XT8KC?6p=~5oQ|XRf>XDHnaRGyYXjJPC``f6N4KD4AHV>rhX2)>Zp468D zyAqhk8@z?s;n7pOchM4HlQ!S}PFisq2t zs5zsX4U<%EvF)O|ajuc`qchACWCjfsy}?&G*`YuKqB!-V_XU#1e6$;HaYWbQ_^+M* z_6Kik!W}OMF!OvrmN)U-AUmP*1N$-a5n(^>(DmBsrtGP%-^(6D4#_3qvB03dz4~^p zB&@*dbNQ_{n?}M~Gp3@&!(UDXujYMR{ms5(5;?nDBt>fVM^0)2`vI|%jzL&D6+n$J z0SIHv4C7$wv5Kby_k>}?&o&=ZyuGpo-z-*eIKHRTHmmOPmtfgAtchtH7m$rNPJtL_- zxq1?x#33>)Dj7UwkY*1CXFYPCPnHT2d2`HcGI6)(*E81TPEC!yv8e;{+Ukqn>3*AR za%-;Mb?}|KC$8CYmcu$u*-f7L7CrKFXE)09gMl*T&F-kZyT=Hh0vJ}Ub$B3JyXC{+Y0BMV^V9Wmb?*zA zkop}Q7is4oc_o?`MJEF(o)J$Es%py*mrI!R$$iMY!jU{c$i=YcHL1eKB?Ee}EJVc@ zVN3A{G;XLEsp5knig~Rh+*liE;W63{b4m|kg#7T_o(%zB?5jgXKkxJH4y*!4O$_GX z@(1*}>PTta)d|r_q^?L(uoo3DnDL*#<73Z(W;pk4DNp@}p9L;yVW}ktfTMKihGK<= zD!z;9Jgn;q=pa)M-3)%Gf69m9Sj9X%_fRNIPM?Tjq7bRSt>bn^9=ecos*PGUHyt=n zP}fZdWXZ7I3q+~unQa^G($U->WysSGo~NGM-p(S@--$9Ib%p$@4{LH*`7M9fJ@15v zOLFWA=7f@#1eAt8IaXC(xTi?S$d z{ooaWO;$$7-`fu)1h@a?LyOmw?Wa&{zJ}*t^gW%VuHNbjj`38v3KLQ$X1KRg!`{f( z+R<~**fUgH5(fApTjK~dIaQPgg%x-(gixZ846u$aC{E?&H1H{N6RyLI^J!!eF@ZYR zbG2w5_BzlL1d!UBbc7<{D@PX3m*(1@dwF;0YR^RTB~GK?jF5Nmu*SjAp`FMbhF`leScH|WKtfd)6(W*(E` zLrmk~hLXi+@wv17LeKJsZ%vFcAeF3H@#4wSy~3$@_#kNP^aUT6Ef8Yo6_7UQy2-BV zEs$Ii9s9M#VBoD`bKUu}Z6`{k&mSy&ZvHf~Y|M3^|C}+&CW0k9pExP~vDA#o3-GNRZg(ct;7h{8Tp^OnfS`#LwIdX7+sUdmb5TNnR$Pe>e)4qnQ@JT^-Hw%g zC%!|=Cdm8jzV>xZ6LMibhv0bzXy=e~{R1Gj=YMYqYWkZ*s8Z`EX9*9TbmSw<{c7ZawTG&YE1Ofjx3~5>py4s-vlceVs;z+J;#IpoA$^0 z``H+R{@yc0#ZFo=74O@)EaR&9H zT>m(kv!Cf_+TmGoZn`e6proaq9<2HlnD4M*c|9<+HHP?bG|?3@lZs)mAl?SRLdaZ3 zsD~u5c)f262!=9%0&2X8?t{yChltd?P%xcU1{E`srN1}SU}IwuNB^0p+=Q&`dM1Efl(} z=(5Y$rrPlCEo;<()wDqWgFu%0e)`PytsNq+cb7dD+N>Eb?S@R#z4O(mE9T9ZlDqiz zHzZZa%>I)xV`7_~LceR9y@m%f@D3UcXR?z13+!SY}+|_LTm=iv%<=bNS$?f$uX3-b(Wc z?*Qc2jk1hm!|%Hck-`w{#Bw-1%6at^bylRlSxD9W^KrXp)r5Oy8#{*Ub_SRBvqq79 zqz0CB0zDK_$~WdY>9(!jFT=q}15cQ(7U2meAVQ5)!zP+MEYMp2c;)1QLt>1iP7&@j2C{F^%(SjlCC>K^e|#r>2-;`E%$=0Sq7p9 z(^?Q{-q!a|Kr<1Vs?4u@Y%v!l+YB{&>8#HL;7|odTXqWl zZjBB6NU^KwZIKw!hoqzWtweKf{)j>i=NJtY^9NdcYhFz)Oqpgq7uZ`Cbo0fKGO?CPUVKeD{qvisnt}|#aerHl z0M$FA@d28=^5r;jUfUCO!~G%Y5j4$3+_E2*p_$?-Ye>AuWC?;VXnbjtTs@u99@>zf zpOb&4^q&yf&S1DGSoj!BLA)o*$K?Z15IMSm`1Bz`Xn^=MUa0r|+vCxsfrVc^&R=8N zCcdu{dpUHg&x2_=>x`ZT?!wfMGVt&elSp2Q%gEkzZ#KBZoc%dtTRhYSm-~x~n-6+; zAQKRuJ|tL!1WoR?gm2>CQcL!-prZOoNc7_f4@&xP^w@ZPWMKt#O4X(N?y(mFl1oZ; zuYZty+QLk*WXRxICU)eUz_V9|F#SXu-GAavcTHPv_5sl_Ar3YhcX($7@*K!IB3GS9 zN^#Zi8$6DzNLHf!@gnQMh88;Oq}Bvn7^!iwH`$5mlQ0DKEb(qJQUqZ;oc!ZIE6--#K$!R z92lD`pq@&D5c?a_FM?LH?-BZP%uy(y(U{b~x*e>9;U@XhWav$BPu=hH$`{1$%?Y9x z+yp%SSD!hVeE1YIDy4=C6=xsc<=#R(A)OrXgrZZ&uT$q^gZG)E3cnh^U7$UJYl%N` zR-b=kPImIt_{fvbS8QcOtp_*z_E|yt<`KjGrp}p8a>0k9BTCd}kp>g}GbiA+u?K)h zZb2@Ai-edxf~AD3<3f~f?8%hAt}yF}x(#+jKu#8&zR}|-+uT+~VjoSb3f*;P&(-Dl zKy0kOPoC;m>RgW_i|DM;HY@jPa4Qt-M+=Z%>Vw+>MFee-<^h2A5GAns$^jr*|EE{= z7eF<8dw#D1yLGoDQfmr$P@*{@X)B9k;p8nuJZfU%Z2$-F%QL; zY9{2Q6t%BJR=Ij5S0&zWW#zDOu#t^8Fr&*a4k%>ZT<(*5@eXj=!v19bwXJPnv+IaK z^5GjnU6D9v#h~3c*x_}1_>!QNTDuFCcKQ|pr$$ajkM7o(&!0B*TXZjI@WN{TpkU=X zmy+vZ)*Q7DyH`14%|7V-42}X=?8ihF=#Xk03qart-c?e)M$Yrp&CX;F`lBlAhD;6d zmy90rXq)9$x{Tq{u3GGmJK`q1^oES^!bwfuP^!{CLsk}S9WYsl6CcE?ky(Mjg6SpH zkpLwkU_|#aGv9}-fVljYGfl(wB$Mag$Q=6TL8a-pdH} zD8J?;MD1Y_e`tPpKF+Q$|KoyPks(%3S_$bLgM88fFWFL<$9+T+lb5RjhJgo0nP9uP zpdgfjBZ&qO0`d8=0Aay9VmD7S=8t_)JH=o%->oF61_GvO*@yR70w3CYk;x zS#T;fih?^UnoVp?;nU`XWnYDqtS&n^m&~5!Ng^&2km>Pb!MIPw0a{RXAkb@dZ>u&-wGsH-p5c)UHIAM>U5eb=|jI%(MC;FvKOaE;k6 zYwbx;I7&LGzJYZ?dI&O}Bg~P91Ste3m6ocA{Rc93bFBp9fw++UA3yasqs{m>lD>UM zouy}(eUCx^>6zcs2}1+Zr)T%MalQ-H>@`;FQko@2gm){%+1^*);C(luXL{|>faOU! zLQ#Otxb0AR#!Di#sqi3ZoS;OVp^#BOUDBq)T6hcf^;MoahHx8R=I2JPF*Lfwg28O7 z*J5b5cFjxf=le=<$Gr?L;4A+L%1m*QG|v#;oeS7&TSE%yvio?mS4xRt2)AAME4!WP zORIu6{&V@`Q>Z9B)8?Lnxox5Q_wev{_U;{qtIxtZWZF0iWZNAA6~yPt;5=%dGnyPSo@$mx zEep@AK7L+d@=&$Km6_RcA#Q zk3twsmir$C)Dw-wh&E*B!>zfj_X7wYT~PID1jc$k@GEH?95PaP;`1y5Z;* zMI`x`C5*-I>Vp-ZHwcw#-StSK7g6Zs2AF^#op8Go-Ux>ZAYzau5QF?XP|+bk?%Hr~ z+xFV$YW)BGrvDqs3BU8&@Bj2alfDFhKe|bwGvC8tg5*ni-V^Ew$f*cuk zvjf0G0nr7E&Y+FG8cmewLMkb$Ba{;pfz5j+$Mlo>xzXJy#=Fp7+#gSc599e}J-WUfCKT(oL zY0O_t0z>e8@YP`@CUaUZAu=S- z+~U1FxezaSnX7>53_B1;9{;yd}Y2pbPC})Y&H=X zh-v^!1avNZ$WhC>Of)d$!$uigLOX*jA-ZOJJW`n)&p)G(1>?z5Pju^_UeAW9xoDyn zVH?sLd4=AQv`&mW?`Ld&wLavv0sZi>F1Q|A;YIWPet?E60zWcPGIzs5@rZqfy!Pf1 zvC)!p{9Lxctdt?Aukx(1rU6RmYVQgUH4TZdP0l&lC!u{lu?=xc%FmE~n-?JB`Ufxo zcnR)^v4%rWaSq^ih#I4GDQg}SQ0A#Bm#-_BzS}}7+LRr8*f2mlWQL-5xA0TGe{<`w05?v3B(E{&SX%MUzeTf)vc@kAt`1#|-n?hr{J3pYx zSq}-a%{t*K8hHsZc2o*9Z|*-V+CCPq;G7_4@*CBmpUNL8i6$;Di=UuDeOT0EDnkW@ zvHk|Def2`D_ACqO5mu)K7KP$17r&A5ZvW{p-Xde+t7N|_q3c%!ZQxNxss z?Vh-=9R%(lSUDS?Boha-rhYr9s0$Qt1QqR86AHH#oeei!m<~ zIVrsGZxdC-`DD{*F)H(IO`6Zk2P2md8lgdV9N?Pw0G&aV)~v4g8z?fYQUp{`(EuN~ zO9(8)9Bv4Ku>iVu9CRnNy6l!1f@{(egk6t9!u0Z269Y{hQD!IMPW^;Pw*%W%qvv9j z%D*T3*9V#$MT)xmE^`q$Iv6;+)y1)d{Q9D7nzNzudF_~^nQ-n-04$?L9F+qfc8zu3 zcpi@rxq%9RD!%^E7j$wjl(hTPM05nlB*}UWT2Lqhp6R2)dfNwQQFKzl__Ku!y67{< z>XemYcUWLFk2)VxdJM#?&s5q zwx^DjH4K_R?tMXSy@O{&P}jCjoyf^bu7{s#p?Is`nmpd9KNNI4A^b`2RSB@Z1Hzm1 zRlf^y0c-z-3}`fc8`eCCJNSl=BW?HL0#6CaE`;UMc}&-n@Zp`DocVdLZ8xh8v0vjJ z2mRR_6qAx!NBsWl)-Gz|W^+i4`UnFFAOrFj5Rd@~B*ae?A&|TqRb(~+D~7f>RD~U( z{fV(YC#7#3v$ckJ92)p49P3$>2Xp)oq0Ti4pTudGi)}n7W)(=%p1=Cz9C5W*YyW@+ zRQ_%SmOH?n^B8l$!aw>c01Ic^;}g7Kw;K_pKP%y&{m8Y^$*MwwTvG8-Rl+9@4&0AB z2^XEgB-RBziw=i6{fEnS&L6eR(uCT=e%z|)IA!H4cTo0)Nlqh5NeC*}nbcM0a}c`` zKz`liYFs=O{LzwZq0cf%;P#FYYD(QGp|7e^JVfL}oyy{AX;R1VF?~4?F@imVBB+gW z1yF>OT^x4;c3rD-j5s|TXQ!D|BS`_~LaCF!jWN5r^r(aYD(GiT(|1lAe%I*;2D zKbfY8A={MSsqS)>S}w$RY%EvFWCqt2wBoz>mS48!jpVEI(<#i`VIO4aFceBlBoDtqQaZd$TMU&LSlK=fe(qcdle>mxo;*e5=joyxkbyLi#fAa$Z(@`i_+Xl93Ig1f-!kHkYm6gb6#LSvjU3ZvhYIV3 z3L>)aN6pvV){t%R2)x%g+b--;Dhv|mlU zB$V+NtIku2j?7ia>0KP6pYR|4TsHw}Rsz%jQz)At9(VyC>;WWh63+48nV$|VLexzX z;ve*J>N4ds@=XqQB0&XJ;m(UM)_&CFac``$BX zG?VYEhQViKI|rhX{BgvK1=6*GWVF=7K z6`^cx!SeOTfQ|4bj}0H%jhQ^93YGD7fo0(I>@zecd^vaD=_wJJ!P|kUy|cU}L{{bA zmenSL=~1kI!Kc?RpC!<<8$bDMJMOA99t=FNgGvO9d=xl-BSc^xQUp4lZ^Za5fwlf? zlMp^Vkv}hwSn^$})Cf;C!mQ9cnn?RumrpO23sZ1^MRv4Uy6^ed94RMeXIgPRd%U~g zNak@3(XxX|GYp45{{X5BkszJ`$i|RgH~{Vslp3G}Or9j4|BWgBf4}Wtukhbm!Wimx zO=BhmcsMupi_O0u{f#N0vyQL&w$wD+?W9_CUQR53+xUv?7s{cfdcet&8m=YfxoBWQ z40q!BW+3@-#8~A`_(jBa*OJggoi3V%HM+bw&~Xk-|GNGcX&|<^@%;k<;n;1ou46=B z)H%5Qo*Sk5n?yOffU{G=MXbE-$s&$Mf>%I4gtuqVp=XUit*DO9fdMbY;v`M20{K{c zH2WgpEeRPUNX94X%wls}FcTn#0_WTThCB`r#JU87%pjH#`C};Agxz6RD=4>Ue8rtA zArk&G?ahQv(GR~=K`)YlsC8fKcTpIS^B?9%eMc}3+T&r&M;N2?0|dzp0zUWZfyDx@ z;Nlp_j-4Y)dppSlrHr;$bQ{G@TwT0Z+*8+^ZnD$vAV3~CvnOLqB+rM-Uq zIg01?-OEmuNXs!Zw#C>ya&x0-WrSaO8$n|>bB=I&k6J!48u40wb^j2(!C=wYfs|md z9DSJY`(Y~S4{5ZNyI(YK^Lbyr($MFu0}l3MQt9BjBm^^lJ`dN^8Ap=fkbyzR(z3kit(zR zCMi(i*P}Czou9GV6BZUOetFODF=9D3UzL9P`q{{uUbLnIAF&#DIasaw^tys_x=&Ys zU+edK;q7l&s`;9?DO`g%f_T*7A?oO^UGbIAh4{}-%O+^s_KIRVdLD=F#*=R|Xl1IP z-74o<>-z?P9{&kylzSi((pd;%3BX_t=@PB^ODr+^*YLy7AE0#?+U(Px!i^$-ze~8a z7OtIr7v*lOkB%vJCED{ogF|syY5zn$Cb^zbNc^2g2L~_TS-E(k;MHv5iK_~O`+kK4 zgRH?<(SrS2!~q$`Wzp$nWSe)N_3g3cDf`^_cW#T)xO{OynZCf#(C8U)_jnm#je5E` zl_<>BbGN6F`TLoB2p4OOWtq*`A!D^R0%hX@REBSVyB?SD3j^rdc*u9Lp_^1^o}9Gf zzke&1jY{}y*i3d23@Gu~4BciVb2MMJP|YAZC%tFLqO4=0{n${IX$o@M#7PBbWd$t|Q#L zmpdoyo0Plx?cL8X_wz>lCLxB4{FPsc?)Now(aVsrzivfY z&+wjGe~Q0M_7rCPq(MnTuC3`e$7k+vg*f%Q1l})7P)FcDod0@~JO;p%{E&X#@<&YA zDZH;ssN2vnaluMpE9u9UvZ|?}Ugm<0 z;dB@S^=|dq#zQ7Ah2&~FCsWg7?Zl%z{6$rMH9FyIQ$cvzBbe~ zk&@m|u4#9A%lMe#y$ga|X6I;??!kxAp$~)T@mm^1`16<0YYqutd@!0m^d8;-j+7kV zQ5lmn_^v`%68~A4Tb`zdBk5t03uoUuHkFT277S*%#S+g;Q5SG{2EJz~voWTfJw9?} zv7C|;7rWoeafImpuZFQC!W%epq1T*BrANHE5az#v5531dJL-}vPaGM_4_lx(Uff_^ zH%ZgZJ^#u$=0EV;!9X@1->!_aS)e&R`G~vF4RfRl{S`HT2le)St+Amu#=yQIX4C%= z{GCmo1^PMgL(2gkWbS5tdNGTAi;C2(TR*5Inte__R!_}&P8yfkf0*)ID$UUPhAVd^ z>*IE0oAnMuRJL|uq`0OV!RKr-vq0i@}= z?@L_zI=_7Hrt^#a55-}|E|%Es>Z0@Czu%GU-8b^?VNx8g6-6U31YmOLdgS$@A3hH8-T)<9uHXe#)rgk+i-;XOF%oe$}zQS)00T6&N?_`KY5>)PMn{#cit4OEdAdUW*{xDh}<_7~944ndC)K8G!T?MWJ(m|A?uk zv@1}|>$}mpqC3s9rx7OQvve_*9C6Z)xR~L>_FsBtUfZ;PL{-e8UV0+E7v3UX<9V{n zP^J2cs>hzv_iFYyZ?Rgop`RHs(FE!aMdI)kK(0g64+4Ux4Rv>Wbvu@XjI}%Q%^S+5 zMMcnTwAw!87tNQZ=y7B*0oGFdA$`!{>ynmusCVDbrW0^LK*NMoU+vin9aKz6Fq@f37FXq3$0g zwHH~6wwc$*U?we_z);lM|7e>zkwXFms!^E()`94f0ByYAf#o^J!9pkfhz4oDIRvSy z-$h)29Q4lX(Z?{wF9#&Bt5tLR+9 zT;&{vUup|Cgy7!$P^(dID0AE}6e#>#5!@V@0e_4@UiKzp0qs6e#i`qEY8?AWlW{9j zH7NvXR8UsqZ;j|xq?yonP~%Snf<^<|i9~x_u;P4d+A36|G zBtMB(PlPaE)2Y5}`r8o*3Z0NxoDD2cT=@rOQICw2yNhEiSC0adK96kURh_LozKNT- z)Lh-WotYF-SrQq|pZ9g(RO_AWAf*TgX37{?yhzRc@pEsnmRkKwj;uI0C3jpbuFB7H0%f5Qpjd5>g=M2m>yFFWUc%a1YGS z7Ww}J6xC$L%_7Sllt8a8-hJL1;zm`P&h+|ZnF#ZZ@|0yho(T48?F1?D9_q-j#QhtC4D4RlHTDs(i69uZCVI=*FL}H;xpDcHu_U?7 zzwNN~$nS!|cVOs(@PTf7ALgS1TKP+h2j9?IZOaDJHz`NU3-)SqnYAHbE2o>TzuYo`Dhv}H zb?zJw->?_B+-6pEJ5fK5a7t`7FMXV{a>Cc~ezO^43~^7ubfS-eWD#t06!#~-Oi{jjfsEw zBJWCU?L_Bot4s_(V_vYoHl47^7*NpwNy-5r2KxwF=n1fUX^DUSrhwt{$UDVmA{nWVRQa_ zC%m{=)ATUFCC>5@3h4yqxizYV>*K#D32(nj@^7KBH~R8aC5ry4MU!YgPu?QU+1iv% zuQ$JQ%w4Jf_{D7{(foX5qj>>6R>=<+I?7us?T?<$Zp`7TAe)-4`ziCR4Q(j+=0Q|0_-!wbzw?!8}&tKBqO88_-` z&a2$Kxyt^JwZ1&aA4StYB>lT};2FWN?*mg;48j-itOJ%xri?_GS|LWoP&RJn{>sFX zvPE3g?*RDEgT0&VQTLVWhYtmVx?3sC(3IaV=Np9%bMRtX-D&Ny$6T=15fcmQu#Qqd z{0A{l`-h4l3;>fSovKs(qwt}Drkb?vcqy}sD6SrjryM$5!I0k)lB?$#?VraQn+eGq zK1XQYvsfz&xJvDGd`lKQ(_liq+p*wd+}vK7{N4ndNG#zHY^M=@h=mdf@&{aN_&K=N zo2fc@(Blzal>Ap;P&nQmOP$nx#Ag$E(XRQ5fQHWsFRRfI^KO-s2f6EgQ3&oVKAO~1 z-om32HXgzPl7vNvI`6v4YkP7I3$&p54r|V&`3|gVC|)Re(!Sdw&-_5zbbr1Z&(wl& zCE1i?|6K{A-^dJBPYwQjqR@;-m4du;4!-L`y|`s`O66=`bEk^tb>p!W9~XkOjx-je z*^c$!UQf|QCmMFbw=4Kn?G*Ec|4>xyd}U5|OUb_T#Ew(FkBmGyyIBc$Dp*cE>zRleg%nI-7u{!{FiOe1L}RC`oFutDny3n&6XzRLarIm;_^)v2*ypQ>P0bILnT8${J7 zak7ar?gBD9EWp?Dkm%BqN0Sg>-Y|cPMSYL`M{%iR_{CSNjAtyB^q$eO`Sncrb{>Td<%}3o_vB&E1!f96egYxihY46 z&3;JRLZ9TK*2rsfZ=sxCihTYW^^!jFN3A>&G1+UaEoaw{pP%)&5$mv-62fb9xVdm9 zlMm>PPMKHs4+#7-B&X`+1!W#UVco{!;-EDeLAjRd$7E`K-eQ5?_eZIh(_f^_nWHfp|diV*2mj^q=apxuT6>i!X?*=xzRQxMzqSjjHi`##Rn0y3YB!lN=2_B|>7uA%r%MX! z7BAr=cS8l)NK1MHnx)b!-3*1SaUiU0liydu;-t~Hs{ZhC`8saHm}`Iowv7y-1jhEm zTxQVJ-{9f<+#%rAHM;JAVW#yN%aitJU>hnbV7 zW!j}UoZG(ecN$GsvTrskE0bPo9KNmg+*jx#Kj&XaJC8l8M@ipbCj}5rBFIk8LRgLp}lyt#(d@a|YK;RWBtJI>y-Qe6>t_^QW zs&3|*Q-Xdvywlyid~`24i{Oo-Q@Mpi4LkFh1Ff1-Q=g^`gbbj`fz|2|5Wqs;Edu6< zLsN%#=uNR!7ha2rxn#diuC*qBxAoCV7GeZ%EL~P1Rv0~xPk;**fLU)UBHoyJH(JgO! z6|vg0T5t;~`jOWG$DBA0Rrp<_8Pu2P?7W#!A+~p!qRxAZD7K*`$xCwYMSV$QRdoED z*9;9SKpWInQ=BEf;6pcS65tF6eupTY3-@xjtk|V!%hzGIG?Buc;2fNxzPV0(QSISY;1I&aw&3Qx0s2&T}$48 zD5h3DLaT#mtzS*x9Ko;`sQe1XLIFor@|B73*8OM0Xrax^dcT0v9L1eLiX74-@V^6 zW=VN^D@Z`O1`=q z11XF?Bln4Fto0;jHe0kg?s4kz1e&JJs5alXmdCVKzf*PZA#MqKl%^0iaw**pQhQIi z=Ord`^q8ErxD4&(`8r02ccR46L!I7FJ}5G@!J=G~wzZ@dsyquu^KLuDd1O(C;xrzL z!A(hQXm1kcfmqGr7Eo@|wSeUu!9&-K-tHCDn>VvQ#=X%S>wO!gkB_FNh|UfBDF?l! zIrFmJHx`&Hvm7DKM)>*p?{E=g+?3IRQTGEk=`ezI&(lqyB37ZWN=CQ=EF+qR8n`kT zqRSoo5|5|n`OQ*;OXLVAliuE1K9NyM`Bk2Eq<9Ihu~#$9$D2S$wuN>)7XPMs$9LS8 zbQM+Nx1-y`)5p?$cp#`|q_E;dq10&kkLW)=u3d?VoU>nLI?f@nx;-7mSbU zIsQfu$1Q)uH1@apNKby~3kCAc>#BV%7+b677o5$Vx$>FY4fUAIx8gVaqS)8HWu zW>5af3I7{T5d6iRo%xG93#FdV!m?>r`I2O2tXjfXKAGLw%UB+?Ij6i? zyEmtq(J@!nsu)rj?usa)P3A~1$k4VX9THQG@^e==Voz+V2s$cucWEuI#k=ANNqQg1K@8j?u&n1 zM0Q#zLi3*d-u|*cW>h?>Z%XbZ4tyZjs(dcP(^m7s9tW1LP>ZN%fFK3y17dABB4QQ9 zgJ9m+HzuwgyTM`X&~jDTC~;0aoDgJxlVV>~(>AJS=_#m5OoH*I#zE*+lR8^^F|KLZ zV(mhc`0E>TOSi>>#1zuOkOSzQ^+h`a!{Z;f<&F{TdLW0|5wX{`KSP;Ks>H&+eZMs> z&2&%$i79N~VtlY1g(8ME?39n-sfJ05Og@*7=*&~uXANd+e>NsPbdLpp|9<-46@w-z zt?36Ht+_tFIfoOE)lk0Rzn*8cMcroSZw6= z<6gfn#T)OTRNF&AbFkcWiV*dEoXI}AL=fGOWEyO`_b9}pq4aUzKJ}ZZqw~-u1;n`m zS4<}qI8XlfW3QcKj#nM&+$dAuUR)5)yNR4GLTr8)!&bTj*lbg)sj*Lyu<>Gpf`1|( zQT9KfaV>s%<%o{-F!xpb)+FT}6sO-H`bSirhNJ+b)k-45LOuGxva~3hTFFnm%o|Yi zc}<|=wTS!eX9D_nq{!6ohJqhQN&=m(ahS*Ko}o5&T00Z>f@ohW13* zq%XHj%F02slU^){;rD8dt$xJm7~FCU*tFXaNq{GaN!Zr%S#W8+rCyOnOY^>?=U55T z7>Da|h`h?Ox_HE=0z*|qrS~)9%RG{QZJuLq0GfOD0uZ9lCL!d$7s!2UvdF)oEw5tZ zACfm~7OYq!9mO8rsXv>uR+G1g>T1=`pEGH_s^MpELs22mvuYLn9>6;C_{sA_{eiW=MnqS`OFfYj;>t1AizS&(1DMTv=>}fuTXRA*TYz$Cg z(ZXP?nUu%f{lazhUimSCMa^GjwsfQHWVt{TzK(54?H9SG6u~)@vL+JKRE>t^Ug1z% zliK9=w0Fe+!yuny73iuR25=6Dv7?{h*Zc)o*f_IPTEnB1yjO8E+n&8H_7%kkQ zCJM-EKaSQCcES>oYUI%qm%dnj0?lKizcX`-yS8@lEEQ|@Q=n85a;$;BH!F<$&I-T{ z8rVVL233Nr!IXc?aQrpi)yz$fQ526?F=bB6`L#gY*8_`5ZIe{UmpoR?MH;N%u1$<* z@sXFUk~>ih_N3A8?pm%s-E(!;twBfLPTUq1U>wR?r?oe4`7czsfxQbfNskbq7z5olh11 zp7&3?Bxg2FdjE_0gezklY3i0`?h*b6o$LcFg{w|7U9!gsA&hw%Z)a8f?ZjRqWI|aB zwon9iy(_B)koTs9S&k_?Ta1rUJ%6zJzrH0JtN6@gcEvoKoO6>Ufya&|U9Zhd`R4(x zKe=>sP?#rCTriz`cTn7z{z!zNj||9%UbeqM^l*dx4{_1B8 z90I@4=xkY)q(+7M1MG<&S zT7p0c)pb!Li!2K#to+lR*J#rWgT0;($B3p*wU;?!O3ouc`*P-ltgypSY~YFE&4W8w zH2r7b(i3^=lob<=Sc%?8?QrRzMT_LbEHS2vOcLygOFOm58QK*G>7 zkK{^OJj3+PA89?v%wtt%AFJuw?JY>NjVjgad70mDywE(3rSJ4bAb@#+(mi0zB!=YT z^j@cR&l%pEH9MNu!}IP;C}pUp+3XD?I%)7rS)&D%R(8r)6rD~h zm+vbkm79ovw^RIK!`&GP%ZLj+qWn<<$wJcoaT~BJ7rOcDj_3` z)=S|y22|;kuyRtG0z}~`5s21d7?{=p{^7O%8LdKhp7!w(41x;Xee`LsN}ckHQzlzA~!nZT)(0*mSqFl$3NxNq0zzbV*4|mvnch zG*SvkBi*HhAf+JEjUY-%_^yqdbMF}U{r3068E5ce?e$yntS9E2Pjz*EhZIc9A&4wn zpbjPL8&p#T?HfBi-JhQxxA{XB{PJt1D5gG*gP$Y$2KZ|3_a}TI;R0VeP=Vxb#Q*sF1;oz(D4rYISqakC=R z(S;^@Aq5M3FNBRBs!ojs!V%G@jas~nUq3PBY?q>D#Nj8` zHAxnnTNSWbLsu#{Rt65DpLgrA`%c%9o>lFDe1%HgLp*GxT3^7cRo*o9hW0~RzyLpm z+j}n&=thO#>+lC#x{vwsygHK5VttS_RPPLthHLS`BxsR#VPlEVT^$g5NPtQPoS_j5 z5LGA&GeW6@1DWAf}TJG&Nf+G^sddxKoY zlTQkRcABDsQUMKwmCB5cjA_5td@u2qcetl5i@(%s6?Hk>^_UGkquqQmd+DZv(W@l?KVOyCixiHT1sLa0lSA>Q z>jdRVfdIjEPibRUJq`MX^umzNGQ0XkCVamBKel%s9xov?yn8q4K`yuHiZ|j-``bbD zR649HsVTD-F$9b*3h?flvM}fdyd@cpJaFaf)i$3k$I5^=6XqS2|VyCg~ZxPi(E-}E6LtHvVX9Jvzuzd;7h$nmH~!Z7W1Q2vw}ZmmREaZ3g*zfEkxSq zx+}=CB{O)Q{EU=)quyC3giVS_;wpy6*Sdxkc(n8K(98e}z(2LnVGbY@%8iZy0k11+ zc38g_I>i3g1`Y)&EODlNQ$i#@$aR!b+Q20%Cy|#v<|vk8`+-Hkgfe#o!&?j;37Z^G zxUj%*tebi$<`}j7MT_vPdz0Fx7$k~*0vq@u0sg+Cf=g9RW2BM<@wqiA!%YeZj?*%q z`OF$tJ6-Xmw`eLQma{4|Nm^9&=DbyzE;87HQj4wk{Z`3!evQylV~3wz9>r)^d>AlW z`%Y;Ew}5WQuucLQ9?+Ohf#*{QNHao8qx2Sj#nP(?AP^% zdI5Nd687Y~qlmc>UxI@VrxKrAgRc}d*y<&m%A*(I#QG9@Kmr|UqKXuFf@o7}t&K2#Dez*iR#eQ6f~TaPgRd4VEiALT0dvi*Q89ww z=fjw&iqTIE^J|z*Pn>b-ka0N^g=gnP@!NuGb9hSU^E0sbA;s{7l3Z?ER z6g4(-bt}r4M22MJ(SFO<%s~%V5U}M>%UQJQ9wB4M?}?ObNn1RxCX9cvc*^l8b%gW@ zyj>-%ZdnEgmV48>{hD4dbCk(;Z~6Uf!Yo%$z*Hn}Vew~zAyGvmR5lMma> zC>9NV&wnO;!kd)jtzt{LD!)l zzIhW;lojxfhZIN3>&kK8Ln9Z&h1g9P!PxVW!Xb^3!@z!EKhzXDB|LWIqO8>4bN9>B zFLS?qpedW88^>{Osr}MUxddA#qv6B5#Ur1&fzCSqT;JsUZMk_b*yo0>hgA4NL|Y)< z>ZX!OhRr3wiBeEPk6rsisy58$qc(II@dpBb&UA@hK^>1+*90It+~1jBJ=K5s97_Us zO^xK+i74)fJgSuf%-}^Xguzs~z>EAYHB{mTCDKndQE-*|d85YD*bQmtr&tZmi49ZSz;{(7TOLpU z><-Ry<^vv0)gALR>OZG)Z&Jz%9y}H9t291D`&FV__&`+%4i6zJKY)t_!TrgEuf!1C zTk}NwLmp~w?N+juU=}cZg*DheI}J-cstA5hG(xU^;d?-?zq1S07zYYFcndeFyWsTxI?vRC?EM`ZiS5vu zzgL0xJ^K&GM=TgvVKHbt@*dN3HXn7F%;HjM_Ugs0ll@s+1W;grEElGu(-OB66P?s@ zd3WKwl#J5m#-iH6MBxnc2tXi&he3RF;V;51Q@@}^Z00Sy9PHJ2gUmq=e})HUQjfi} z(BZ@6rI{ZR-sIT43_PUrXUohl<4Gr^y-B$3w520>WB)p7mZ0%5?0tyED7X>AYGjB{ zykpOX9%7JSU8v4SDcfEM-w}Q3Dw@bp`iR5Jc{`xtd;xj*4%1^nr1Dw6$8+sxywvkT z%q30LDb?~qTFao4de_)O29|Q88!xIx>i>gn!K5u1MNyZ6Kd|d_TbKW!O^!p*J(H79 zHX*2r2iKJyh2fu-I_vxKToD5@dMeeC4*ZDAVLA=!in=`Dg1MuC`5i@DlpIO{*~5O( zCrUIqW)X~An*3}~*CLdvjH))-T~~G2NR1UTyGeY0vI8ozji6u88IRcrzV&)3pl+IR zkdQ5xZg$}Ch-wPS_CsLPpfCW52t>bGL^(w@_85n=JlUN*^3yx|GGn#OS>6bqCK~7S zb*>a1MVJoJ*Nn0PjU4gM=8}F0B(T}1%}voK`^o&+NHj#e0E-w7g*hXFNp?hSGaQNr zizBZpuFuW=esND3lWf!?s->>p)v_!S%XhpTmemWSe5LLzY6Rv{caV7efn znq#hn{HCeAv8q272@Jd)#sYx$-w-%3R@i7VY8Wgb*V1Dxef%pCo@c@t_ev(5qTm4kw=Vq0Gwn-3G zzAsuu?nK68`v>Q*pE*4Hm6k25Z;p--d#@v}6v*u+$EftRkNXS_iWFYUrA-v{f<8(L zu=ZHs^C&ata`Ax3|;igooO(1}P7taNHB}aqqe-dVndqs9)SZ&wPXTq#|am zM)}*;r{D)+luf3H%h2-Oq_N0AiMKttR;kQgSLq)^4*-rsvJX(#KJKFji`2qrAj#;sn3_mk6zle?m!y^SmCN&xG};m39UklS*J{ zmFZe^69*2`%n*k2@OFnRbf~u9TvI<7?l=hj7OrmEC_UBkn5`Fm#(7G&>rTnox%L`I zKI1#83NgRF11|R$GlJEZ+mX+Rdx)xkJJIU6ty+F9VV8Vuv^pWyHl8?dmMWyx0&c-F z4=~&bX{O)gL5uGbFk8!PVENc|Rv)p!Jg|9JBMaxhv2 z!7qY;|E*$G^7n5&>A)YmWr4H^!d0yFZ~g?#lg|m;=Iq-D=@=DH=8jh~X=9;fd(yZ^ zzwSM-W_)r+s*G!^(!$TT<~MxYrW?I^6qS<2SD-y`JeuLi5-CmtK!X2MrqSgB&EVbv zE;wk05Yhbe6S|M+vC}b9N;6M8KAXqz&u|NVus`8d` zSIJX9+KX#{*A$tx7=QdD6zgJf7Lq>DLeMF>+aEE~dZ9^+;BXp>frXN7`<){G58V{f z+bMKKaPNSem1p>0d0(A$0QQQ2muGZuuXXCOTbhDZjB>;(n$&$Xvz8iy^#wIDn6v-yfWfke)b{o%6sS!~T80Lp1HZlWJZu z2jz>cZw7yKP#(94aouQ;keB|=Il!gef5SCM$ZjWGS*YM>?HJs=(&6hZ9PeEJ8Szo+ zUhCzAGee^KeYwM4==gYO8MR<@#prm=0tWBeu}jRwvylTK8s%z~8C4)r24{3?#{lK6 zu#-NSRzSWRt9$x9wF=EI?1!LwQ{;!Aue==ZBJ$vnI~i{reqS6iLzlW%{*^JOW-;rd z?UNC`JgsybaO51Wx$O0P!%d15uDokn10sYQHCH$(tZwqeYJ*H$t*WkEsZp;a{!wMw zYtky?l95vvy6VS;k41CFk&AsSy~6{2yW^`7&_6vDw#gGd(tBaV*mXC_<%Y^gmjKdb zKz|nQ-c&VjW6*pYZvn!0H=hv*G6AS8Nukf|OTgjJq!Sx&7-WUgf* zuYJ8{)itV%(|-&`1i_P=GswZ7l=fTb9*Pc_su2)13GL_j?`pj0#X>LI`|R%5Pg&i| zC7gYT{G-yCfRrOcRT#syx2454Si`}Fh9%v0v$|5JwneYXZB7vr0fxH)N^=z<@Hlbs z&mXmG1Yb_R%#qe|BJ77<4o)YfW{NTf(TZmpl1}GeiCXA2)->P6WIZ9Sviks!sQ>J)K?14bJE9s}Cl2P&FFR{>~m#T$hr}rOM9*rKNGCafMhs8A~OP zG;S~?H0vo@5R7pe=elP~oB7T-^ztEC&?+b_u?lGqws3CUawxuwJG^9bJwih_N#a0P zhQcc-Sx%(qBaEyfwN9RScv#`{-Re#jCH>1>hPWJG%Rf%k)y(V-B6pe_+kCtFRV)5( z5C?b>Am0PyZ?=4|q9?ac@mIZanC|&2tj0nOBLUK~9)~iZ#-Yun(%)Y+7#&2hu3lj6{@* z$LB?LG0-h~6sl4icgJlIzw^5bzhXDvhcLyxYk+m0y~8$d9woGt?P=a#Nc|ziSCvW* z>+M48!N$4me|IcHMiXIUe;!?nJ$XO1b*GJ>elAq`SC9=Yxf(}oCXoTvwhdoKJz4mR z#GZ`{mSpxQGH z^PmUOf8Ou1Obngzi&IOoe4D?Rpeo#%Wrf+TZa;t=3K5xr%(Y)8z`CCy+|+Siv8fmFT!UMfNG*z1m&^E}atynJw{v1KJjAy?iK2<+ilD0o|+!Z7dn?_T^nviXHZO z?n5Xu+$~&KX&G}>ZCRMUQ&si{Rv1&rb0F}mB0?9TXb`Ib?*Zg7W{RlpF_Y;^#a@Ke7YQ35e@t_suvC zVl~?bR2}T!&|$7H%&FJIHqP63WUE8fkCOi8NcjgbU=K&oB0@zW12-69J_QIrzzEk~ z-D^gJh}NfV9yc)_CFfH+ z20E9j8hs%?D)ZKl4677SXCc)9r(_B+S}})_reMD>BWn*u8L-xZ5r5OkJ)rDm%Xx8M!5`<%T zMc}Zvl5h*;Ls2BTMahMh8C#b*s`|}$Mr@g7wtOT~Nd)GePtZEhJ$eMb%62v=KP68I z@o=hXSZ(pk3^rFIp45{8~ZIm0d?K#KB% zwJiaHn-wBFriaA@=BWK$NGNL%4ij$<^FrF^T1-lLujcx0(jwpg&kgc~wyUuff zjfUXW#dOuM{?>)*`c1``Zvyt7AM^nXA}+xOX(Um!gI=8Vljp~e`q0xjyE&_w#9;x3 zdAx>2*QLf=j_W;vOJ)JNXX$sv6*@=uXNM6Tn{2n;9o&(LuMVu828CqjU@#ki#e~<2 ztiX(4VWXhgA3&agNtgVcG*m{fu(mp_O&5Z*d>1Q+pEa}JZmq*(^;A%x6X*RgwLZ^o zE(Og(;pGQ4Mcdc&t6?0!y*9(Rhn}kyHc4~;hBLH*%mt*JcnjlJ)M^`)O#Tf=70s{OGH_M+Idm|ez6e!lemFh%-#L+}OwQLC?sfOwAC z1AYX~2Uo)jV9mpYie zTfDuMs*kw)3YO4&k|Ggs4jkU*?Eq)(KP3F+yP(@SCOrNla)ToYP%9Gq`Ck8{TnE)^ z3f@A&jF zhn>~^#-L=6pe>4dnt)6b6#LY=OL*kP7XmA=XUKq!lrWqFm*Lq28Mb5iD4m~n+!ddy zO!V~XRY<`Z#g2*T$>SyGM<$t6T!+QpWjnTyo9pn{o~Phce>RHJrkA4HJYdL+)EDAA z2ey{@2=FCVB=m0ega(}RIX}8^n8+aJdo#DXiGBR_d~ls7Qs9Dej}#BLrBGylZGoN& zF_f;XoR9Rui?^k^VKbMpPWG(34uabUlO$l8{e06fyj&2@OhaMEIUoR?I|b4#xc@M# zp)T|nYYlfubne@*Ca^bTJ-~h3(2G)Ys^f40y9zpZJ?zfpC^dT`%OMowG8c>|1G81z zd{s#2%5slSDdwHY%FQA}WSOhrTPO+4PR7IO8x5eWTSMt?aB7a3rY6Q;Ee_jCB#tOt zWT=R?xLo#V>_D&yI1>$T2@f$EJ+R`szPfBY(?kDyRa7GuM^#iiNz^~|6Z>YNU13I_ zkS>9cSR~-X2aUw{=kxmKVBVCoe&;xDkvH(QD)CWt8_xhX%9{3neMlt!QL%pV@8#}7uao; z40yJ0XkCY&!9#GME2Dzu3V97zs7Pnhqw7>?JI^X}5-sD6jUfDnyCBW7;&p~Lbl+Hn zmJpvuv!?h+;*CZ7WB?a-qg~M-M?=kUDe0I{>`!7Pb8rCn0s$bQM#M2Ff=iGM#W6r3 ztx-52G*O3k@6iQp3a}quiYRC0h?&pa3y%Qg!d~5$&e6I@6 z(nnRoMi9_30^rNV4Z!xiDu9Pd1?YnZ)pOds^&1Ank2+&T)b#wDKM!~@h|LMJDivr1 z*5#x#NXu(H_x|p+Ggc^?_JbhdK~-vlHWMzyLD&QGA+Gg3_8Mu)Hw)BS?mfHNHr}Wn}eOfL4Z-EfG1@L#&v49zIy0VEeY8lK6*F6vi|T}zs+hG1cT@lxw6Q423_II@vIT^K%PfOvtVQEo#bZYSF| z8u+ETQ6EM1(%E_M zEU0DoYgmY^KdSsYS=DT?zFplB@Td{m+b(*4#8n}4mE+|@(@1yoEO&`+EOJk(5G>Pb zQs1^Ed`$1+7sKb0wwS#&diVOrlzpDRSV2Tbukd+Q6cTF(kqi$e|Cv^l@gi5 z&^wX#AXCt}o5*?0DLth8VbN%cv~R~RsyX>n_jIj16zy|d{*z^gH&vy7oC>}^?0-Ta zFf))$-U&;R13TG;=tJ+qMo?71UO^fNTq_B_eY4P;@T+ZiN(oCFNwOe3L$w zl`gB~WATdXk+B7Pk%kzsk_kioC4 zJto6FSWC=}Mg8{KUkE@|)$g|q#~t?f_1Q=~O8B5Ne)8)xVW-V>rnDE-X?X2HG(Pb` zD!Ekb_-o4Wmy4qJmKf-z+9)Eg$c1Fj5MUetXbr!yY~VnJ1U|7}hOmPp1urfiw#?sI zB|0Uti&`1any(9Kbvy5nL>nYsE=NnHGPC?@oBYi4KJDIo7j9E|Xv6y_mmPLGHc7_w z1NZV0PGaB!$caq={5JL5VhLEk6(Q!-2A1hleFCxH@Qs(tX+e$NRZCJ2%w@q$Xv3qjO+%BXz1bP~;3b zc4wkArBui2>X~qto)Brim)Il9bYg|1={e21A{i|t8%|uSGh=+CA7<8{RhCZc z*NIGlrA#m9dZ8K{x7ccy%zVO*>-z2)T3PFf6X$9L zxw}0{Eh(3FLc9IRfJk)~(RW4EGV#24-gPV-es6bU&s-%dLe>Q!i+s~*Ho$m|L5QOpIC)B>Lyk>frIC7%OoU!|8y&sb@`Mq+Ye*5 zw5*}{?aI11O|;8}w8{}`=JRZP{QkJ*UtuU%FXtPYG#ycVB%0}2hP|kt;TcoxoQFn? z5pF&Q0qTE?WfhkHw^&vhaHP}D;bK_@U@esaJYx{jBi3^=&RmOQQfK_LHq<3{glYuK zD(e)({Uy7~WUN}LqOk^vyswc%?=>dMqdQ-bR{Kn)RrT_0okMVjq$&RsbPz?tzEs0u z8Z%(Of_{@mLOz4vfaAz6HMr%F+Ki|z1dx{d&oIyf)Fsq^PcRXeR7m1!_X#Q62rhKd zQY{K~xiFm`GBvBSo>-yxtvo3+`}hzK-}XPh@NZZXa)lIrC>sNB;|!`w6k@Q0WYk`2 zoI*~qJDS5Z1P=2OBjP7I%g$42Z|R>R`5Q6uA6UpRhl($&if6@o6J1u&eON0p7ZHBh zeCg>6{4`X07>vdV=&`{43QFt;-Rx4O7o8pOni9JGzbLl zX}{@~3s!!8a{V!ZDyw>mFEm?WuTGn4JXvug0`B%LN&}PkF$+E#t5#UYpET!T3;DP6 z_LSPVM~<)J=nL2-1eS(9=VK#Z!~&kDj*-jg2_^f3cM}s%ATSGVRc6~jaWB3Q#PmyIM;cb0%c6g=c`MW{%r z?@l+QpnlaeA85--lswwfP8=o6M}dY1AMP;<$Tp8f!-*i=ttlQDENWQ0ftA@>c0AN{ zA{vbf`$4HQtTTS7pM}+iP^GE9Dcg-%fhQvkFqB>idV;a*vqPqgl6ujF3K`|CEO3x_lp`a^WoRev~QuzpwGc`l&z zt2|;)XtRx-tlL7U?2?%Yd^Emn&@!Wo4ScBN{U7$o#;jl2TIs&84f!32rJ@z94{G3c zo%+0@9YI;9)uDQx&#C@4VR78I340?RrHf<5`;qzbrk+Q-Gmaa4uyl05QOSw{hXiP4 zi4Q7Oj3?f~pP`-_a3Zzmk=HQ8i%3I@r@rSt{e6#A!(09A0C!xVZF0o5XnwtEu$tzJ zY&37jgjr}uR@T6I<5wZKq*N4GZ$45#YTH>K!`7jwMnvSg{Tqck9c?>OhJ&)nm)Lvv zFfxDaInQAfKyZUUWIdLmt)!OGM3h1d5uX@cO($+NJZp9BPsf}(*$=A}w%cklHG7*HV)H(uT;Z41 zk6E6ZTUa~?%HjDG|dkGR!;hZ=>rbH}B|>h@ZvQand;((;3*#t%%Keq?*Z&rSm6ceIDCtlL^4aOl}POuq_NWw9%_v% zu8Cv4=6-<5rNkO7%|aUXJ16qPq38=AbV=M45jVElpQxxK-6?!fkz+6qPQ_!7Hgm2mOW8jlTInanYG0u z726eSnugUwWl{L|J5$15+&8(rLkjjIT9Y zN6s@y{jIYTSww2I5N^gniFeAzoDx~_`vr%0z**l9V!gPe1oc^BNuvavIqRRo$=2IP z0XT|+foBRs-IVTi?KB#_tvL_CY~lLD_XTC0pb!G^{I{j|(>_Lru>QSTNWTik#>opm zU(3HbNZRMHS>U=9n5B)0H5_w5!DjPvVBOra&fN`|8JnejOsuISB1KM3!aJ!V00t|Ea}RMEJ_QJbrn`Qed8)tfn8>WFu$=+ek;Pf zS9ijScczhFPPycha(;C3l@aLlacB-vo;9gbl3rb`#sDO(P4x28FZbdC^5 z$VA_On2;pVmL*9KjB9WgH)LrSNn+a-hjKE~SMIUXcJf}0H&B6z!v zGG^9EVukUW;!L0sFr|fhlq6R07dKAkz@D;8($g=Q4JC?DanD+DuLhopf>n&VvgZ#7 z)eQo^ME4qndRZwJBiyxv^Be%vAv2T+;OeqU->p{c&D7Z%OGmxe2zha*$@^LAYOcXY zv{$_DGLl{_mTyUbfOpTLn=6^my&ZfyC#r0-w-rX8vc@gWl3L-f1+fkm-x|!I0%;4< z!lrO2nx}fFk<+K;l?_jsItwfZWhmF|Q!;ni&-=Ef{AjEySwG!QkX#(_Tn(U3FbMT&7pzhIXRrh`<`k<^hd2#(9CyVtIUPYU$aGC zaUw0n2G0IrGFbaO+Wqy%3gJLW;F0w&SI_H(Ytn6yvL%m4ng)Wz(=_!Wa6K$u5N3eG z0l5h?>Oz%{U;V=%87wKk4CZjRCvsxKmrZ?x?qyHZtnTr2rKLg-sEb#o7Q;(an3)t3IKBIOw z%;gSyEN*cq_M57<&(rPQHP2ZPCFuu0{E0Ox@mITM%tD!^EuY+v*MlksKkQT6Bd5*Y z{J?+fVI4;QH-qFeV2}j;SMlWlocoa5bN|M=A>39+Dy@cJ!`7+ALw#c$$5yCC~!w~*NQ z94RQM71(pi&|`GFMiHq5Efev8^qhb$*d_^w4pDZ39~#<%QotE@GxVJW@CQ>^5ltZEm%<|-wBPYmlC$)5sU7c>iPBNI&lc#i8t~RV=MooD6Tf$Q z6Umvxl!n}qsH3I3CbueKUAROD09y&KaJ&5i74FyJGBO~e@o_$}^fBRkQqj#PPSKf4 zMop)9-Pbg0)+u!4#ndi_(Xxd#d7C!L@zKPNCejz31F^|NI1O&gjEx1Jbui2sAuSoO zgP$a1N??bXz}pd@dcTObM~0Mj?+L|jt$UI>^r-oS(_^u9Xu7KOcu*BP#n~ZN&m*KV zS1M}hewry~aEPjopBo9mDu4{uJ0NNT$cu3AX*xmfi(Ot(7vVH+iVfz$ zJ9UbO4#JkA#+UtyeV<4!c9;rk;_g3FpJsBmo&S`yWb$1hviNKO?~a)f{fg2?65M+_ zeFuWWz2AKn!-t|XKmP<6qujIShcIy>k}b5hI%a74FS6$TbRNQ>zI&B{!CHJ7LyWS+ za+V3fKFWFtM9P z5D>VELl=_wdL7O3ZP6(lAyH8RA*{4?YZ&JT6vC?Fm18!xn}t7Af>0M4oEC#;*)ehh zTWU|ney}Mdx7cs=$n|qE3GuDF6~aEH1N(o81Q`Q@1th=V>*jf5k>?>{NNSS2Gc?J8B0$p?^yYp4Ia%;vDb>;06 z@Z%)`(rH`|h}SIU!`n%$5#px4vAsl_nAas%Ud4u%*X^}X=BcoqFnjgCo? z5nn_N^V_4S{;1VTA(2*)hkZn0Ob*Mh#QCOZzukX2+ET0DJ@Q3#uXmgiMsiy6ls?jZ z*hENH1_5T52L21zPk>w(Ozk&=Uh02~ObCyiN7nK5D0gA;A0Qr#m!3bjg7OnaitvNu z4}VC^&*W21+IZC;p-YWxwfBfA$9q}6h)NXSv6_y(L;NWNczBXv@G><9L)cNy%`HVC z)rDxD+a*3HzjyYrl>Eo%e3aVfB`R5)>%PvOPOgDQ+x;UdbIvLV5nXrbcV-N%GL4MO z^gAGL$@(7lLdk&MGM^DlO&=V!>--x#ixDqvvs_4bPku1i0_SLAeNO8Kq(nx9>(||zzqZY7MRN(0f-N?Er=u6X^TJN(C|zRb za{@-`7@N&ZKt5Q+9&Ykt5I)^DMA?2#-U zQ?B1*%2ZQ-S*h{$l^q54+fQ}EvJ(jm;%=HFYvX?5^NYf?;|O7Og(ZJFyE)BPO2Nk~ zKw$~UGTgXT@J<2vexQ&wM8`&&&FwPxuy*@%D;5qSliyN?^d4dUV#QUzL;5qHBsUV_ z@83lP)A2rfJ_#hC+(#3pn4+lQlzej{gV*p-MMzc|3S;E~w7rNlnKZDX_sCH38xN~j z^5$BfR#Tl>^X7S}@Ond6%b33yZWVoHEXKBp_0*#eWEkEXF2Kz|O=reJbk}gVeTbG_ z$<8x%!vUpf11&|eFNQY{MOh{+6dfRp`Ie`iO;#dz%FFpHwjDo2idp=W!5OVTF?>+} zD%{n{a<1#`HH!533ZM4q8Ajz#-xU*gIikfKAHgauY)Hhzzmfv13|ld6V;Ni@DaR|Fyx!$HwkWdh7{%Om88TcQV(6iM5~E$UrZex&tLU^xq)x z1jG`E_HY*@tozeVs(}r{n-dpatP{bDQ7AR-$(YE0Y-8d%iE+(2t7%bw_)BCvOCx3R zsmGewWMfpeJNc+bTM|Frlf0q~$F;r5a4;Y+(wB`O=Qbko@h1M}+DpKj>|(nwd-pP8 z-agV>eDW-Q)>y82ZCn^|4l5cD$$ea;i| zwNK*b_Z>T~XF0ni=wD=gS`iN@sky&eK;_QZdiCsS!?Q@Zx5oDdvc;^3Px)6;L8ORz z+2s7EyiF(zM+;xEa{>10;|jg+63jguKSWWTey07wM*F_@izzFgZ#7O0+H}gde|!** z%G~5$q&U3`=fHs#sO(@+guIuqzbX6lR&b7z7dK)SPdWv3dFH*0fu#+a(a%fV&@d4zgf74?%OC z4p7+s=QIB0anJx^rhl6SlJ|pVfi0JCD#zX1W2sVQz!Q&zuheT;&@kqp^?r8XYvfC$ z@GJm7 z7kCfqykCkkC7CQ~BYNuYVqD&Xy>ZD386iTd6g)xBG0a~MDvB5D!M8}P!49ZNZ+n}U zU0m@1@)EXlvUPeqsVJxjMoa4Xn+}QxRyYC_x)X1ws#!<)lJ?BsG~FUz56dzzpL^RZ zHYvNh#wwzMSDP?vzQBLZMsl3^d!*@^=G%bmXQ4GOao)X>wcPuL&H=rO{yWvT-GF8B z`=XC#5=1)&t-LDS3mS=+rcY)CiKNwgGP6@iez?x1-)B>djW^NmIaNt8;FE4yj`jFe z-n!@WC%bsfx?eio$bH+{ngvU7bK(vxo>@VbFk4 zg$I@mazSvZ^eA9V%B}(8<>lX{fSPpbD`)K!V4u9+XJ%C9U@=tw^F^_LBx(-nhw4+j z(77FTUG;sBFj)+Xu-!K`O&7}v!)Co(-vgp6XhyQG>Ho$&kY(mK08ViD5AgOYJTqiS z1;k};yd9_+Yy8uVy=WERn$^D7jCtZbfu^6Ix>5O?y#Mn3W$d?LV4ww19w5{sPQPB# zj~x2Gpy*@yWh<(OvO_6yq49~3x$G1Kk|JyHS8jRdM9|=$p^>bJ_3AW|lJ2VsUnuW- zGDJ1%F{;!eo?%9+OIjZnXE^B_^m^~?eEy0?CVlt>Ylv5a`AJ@5eZHHL@0}0jB%N?$ z2trqH6j-1qsOMM%{FAfbj5X7<0Q3ucn*PUE?atg5Uv~m8KYrYxua9`_a@^N}p*qsp z6vQ+eB#bn&8OY3=;K5}c8Ysc1Ya_X)!=@OI2pb0?o7}+f8wIJtt(^W;PsrHqO1Kcm z3VKp)e@7o#e$Czg;ocpRj%Nj1e};>Z?2r@VvF{VEN=k@tpLB&1hiAR3k|foUni~&J*ik#^)Z1oS1TwS5+mL^Ic|g5vzjWC?^yHd(h%fiz zB!XP1qqP0p{JoT}LC)^V-BQ9B@hy|P&0GS4pCsjYYS6u2@uF0-9n^-UHhI6+f+U-rN(^lG33saxmx66uWwnb{M$l2aSDOUl*S4-mj#0*b%09>ve1hy=&jv z5mot$qbmFmH(Kx#pf1|?fdjJ@s$dAZx7jtTv6?me>!c@mnIacl;1w>2V6gPpoSF}j z2I6LFyl&zBv)wKhPxg)I_50(bX`BrHc#EmIOGARMNKkwrlLJ6~gY#e$0Y|9o+FnzDFo2uOD>ewXe3QAH=KyrJxihG2wXKe*Q*r>6DszJF`7qlYk9Q&W(8 zd-_mT77?!I0_)50l7(p98oZ<*$=-fPwW69TJ}#F{do5zmXt3K}h(C}C)HM?)I+=+p zPf~l4IK6uvtrMRSlw`TjW2`x)44yuM_u)Rj1~{a`NQOxOR8R4+*Sx~b zw(QCHWd*zAtylcxoB&<(gF=ntJ@(lF^EVVh{LJ?_o?b^c5BoS_I(&>zL2_@~bN_Ow>4FxTsion4Frig7<@7h7npa;7`vHpxaPXZp#-q?@@`En~w1TRh)gX ziRuvOth>luGyb8-*Rt3yv^_Scq1kU;(c$YmyJ0jJ0v!v06@?F%BQ{-RdinUSDCta_ z@sS)$`Y)TlZ_Dmzzp}DUuBo>^`((!UPMO87+%2&3UzC?u{>aKd@u5I_3?cgy_0Ksc zc+_1j3XxSS2TFhXOs}Y?m`M{l(ZAiGdNV)7geBkbY;02Zf;vyFPyr0LwFUEqjNRmPfEU2 zc3dbizHg4j{}bBFwM&CG9X)MWm^tn)NC&Z`(nW<;w*VYZ6CxxUyq8g?QjrNadd>`& zH_c$){#A5F0`00|jOVM5nr5tOv6{~Uh`p#OIK}o^{Ut*mN%IeU^0UZfs}Bry4f{qm zLxw`bSp9rhuM$s1p}O^vjCd019FhsHwSyIO-`XEC!*+2fT5YMKS>Ga(&hz?74%#c0 z_}OTat|#Gj`+HCprI1x*_Uba!r}&Yd*{h03b?#`tS(jgOn{z_Q7w#pvdw*r59&8rm z5%EI|NCx;1NV?afq}A@`uF7pcq~WMF*+rLgobk&&Sj!k)*jasnGN|#8{#v4FV&>O* zy_uaa&9JT1YoRYcoF*KQxGc~TP5@EK+C}IwIt-%EZ~>I3t*H)0oA=BOX0Np|1|NuP zCz$s$c@PNn665|-A;x0a5c`On`M$vHOiK67y;w!`{kTfYS!Vt9?XGC-A$@2Dqi_{9 z9B{Qb#c%+4S-^K!}M86tPtTjvCqL>2^(wm0laG(zdk1|zSu-^)H4 zZtY}~JI!=S;?@kt#dYJGaJT1{p#k!Xf9zstA{tT;*~1eY-)H`z*C)6mpQ2->S7--UEqqby#coFH5u*yBke82 zs_cTc;SFq3Qo6fCLb_8zy1Toj1WBbsKtfU)X^>Rul#-GV1VkDHq)Xyk8@=!QdynV& z_Z$a*xPGjC#jII#&YW`&ms2tIJ@dWP>Ex=1H>z`;+=qeaN(!APT8S`2Eu2bs&!L=@QD+dZxus?yv;!PceHQ zx2Z??<|uIUp7i-5U=Xn3ysq1GZ)5QHUZVff41(E*CIa-$Aqt=mV-`qP-4z`+38G^r z{%H&E|3Civf05t6fwr3X9XR-Z+QKc}?ylv({SQM}xxw1P%kC}#AGJ6{zUHI;)6ZU>^H%dlPm zAzc4j+6qO28}4t~=VxI9IV>MBWpdu43(_kZGzTdsesXC?egom#pOs%13NUPhi^SS5oi5VuL)jTVU8tqm4w@m_-$uT#oli@Re z#<12lg4YS?@~^;w(@$NF2QdO-B>jI*9ih8Z=iT2CWJlhzfp6-u__{b6pBfME<0fOW zn|DwI6Lo78o#r!QdLXcmg*y-2rbrWIF zV?pB4N}v?(;rBf`?(ak@JC8c|5B62_ELI5Z zF3KO8Vo^vOPQR7Ft9?T^rG_s~Mu@CsTMoEPyq8cPfF`*w;UEuzTTedoErNIhgN5De zZ~F1#(H|Pp*n2s>8OIBSAw_69+Y=ry?{&J%&cTQEY&{e>LnJuju0(4f{gB>(A{B@8 z9^N+o3eiua@D~n@n(HG;Ujl2)*aR8Fv!dQ+0vQViw7t<7tH8E-sW){x5hN5@yN`Xi z&kb)|kDqNc+HBJwP#&8S@W{t0=FEIJ+orF@%V=G_2dx1>b(6Og$|wiy>nh_8`ChnC z(y&uF_9NR1g+WVk)*P2lC0}2^Tkoqv;tLwIoK5L8W^lb>3y4OtT-kS@*5*gx+Stjls{Ic_8;r`YW{%HDB=u1M798o_6g}!?& zpwI_BY6eyGjNgE0h5D!G2lNXMz_TMSBYZ)XoL38vK%y$|oJR7PD~uJu!KZrq<>fXd zN=>$5M~EJZesq}NnAV32!%3EgEIjhaAkU7(7)}m6AzmEbCy+<21Yr{U5(5}e?T~jF zPgL$T-8?X}Np`*LW+`q;*2?XylOw}0CA_y9FhZMfW5eJn;g5+oA%HaQNrS7iITnQ3 za)95G#wH{OG}&&g>8GI;h4jtFtC^GdoABOq8 zqck=B7*IErs)mC`fyt@d!3dC0;0nHqR^K%xz|1s2b#v%R-7tsv3kUo_F*zXlkpP2_JOG^f zZ8W$*NIFxbTevHj6&2fn&?u~h|1jgV{9XAE??} zG#WBjr_OaS9}ww!NrjXk%KSMy!e{86Q3x6L9L+U}Ar-^M1QIN611n;K-b%n9haPSK zGw%syAVz~+{5kR99#xf-i#7`JzN5DFRW92|>v_ZSw@p|@BV zsr%t9*Q}CWS7u}3`wQ&RN&=5utuFL@}w2CtzGXk3+Hu7RQph`CI^ z8{a$%xl;bYTN^j!s7~{Y6-lW)$7&Wmju@xVEj+;LK(mrCuIE*GK{(WC$(>B z*U2(!vuTnO|3II4%Br=A1QYYZBDmZXpLT{jqID0=Vq{WZ`<=eVHW9Ai7suw8&eyxA zv_9y|CBKx`LSd8xVDhZ30B6>Oyu7NNAJi*FOyQd z8df#!+Li=tSi{5>U9gqnaIa^L$u+(I zMSbAWEu**w2PIObr-eSxj#}6k^Zj1rC49OsKVi(`;r45kj`3sdO4+O-)%mWDwH|U% zOLue0#&g0}an^^!D$;}rfnzNWky6(N**>%38@g{)Vf(wf20ZLdCnz=n=d(Ah^f0Kg zz3WM!yq^O;orgL(e4jj!p|I;v@>!Row9&#S{#rD;jcDq$)5!4R6B=XEQ@NXtI*wEw zhv3*!5IK_YV0xiJdp{wXLAK-O_r*f_ncVAkpe;HYAwO;S4fupdXZBCuKQ1%<<)th- zC3pBv!TOa$NfbtXyHC$7w9@a0Wm+Ulf(O;>PWq?gIFxp{>)uyHt>J_!GFsN z|Ducl7`}o)MqqV|ztxfGKbOY-mNKGNTkGhhzA-u~cYQfymZmk=Svc8kU#wLLREmzJ z7af`ls{i=CEcz9;l2jEgU3+fv0nZ8kEgOTeWtq;WKu|9JAEgYquXn$Bhp=!W=?-S@ z{yn_`Jsr^78R9=B`e^jiuU36_8e`(|&L?8BEP&{T(35%~_?Ct%Auf%eiz|gNCOttuTxUCG3(_!uIu_ES61*~XoTeIIu z=C7>@N)mJy&Z7A3@U*0V3S<*{t&0f9OXCzDygH5`w`>vLGB9FpF_GHGa!+Ts_4bAQ z**rhu5W7&4PkX?E(r~ZBTFTP;t~MTSJ5e`gMwiwXK0))aC3wus{_Z<|gNzPmy8(Mk zP4N@Fra$^(jB0hZe09NafeG0qWULZQiK?SjOYH} zoNsbHFAvo$S}eo0p>qy5#WaYLsshqlBrgAu@m zWReck`{56qK5vQ)YO`&M&}$75eA5`X@3clUTl3DFRJhnb<12;U;2LpeUWV3S^|MHT0nblnp{hzOfD z-jq5aY;1Vzsdn{CxGrLS>)}lqlKiJ3$`7J3Y4D1kBzJKF=NMq@$nE@{Qx|pp${=>R zuSP3dK#U5?;msA&=6fCce)_6cXup2W#Pn9@cTD(hrGMNlc2F=z3jfo?C+M9*=_t{$ zDN~HEgtYJRol(X_^VDrgXOkV!YE zM{CV2go=F}QE`sFnXoL#dHazOWUAD4!B9p0O+e_CK!7|3cGVvW&Un4QXM9Zx&!t!i z&)6uBPQH}c??N8p$5jN*TQg*eT<6HD8RLxOONq{E@3qr%@NfkdHPu7~iHCQ%a&umd zX+F?B{0ckc@vo>9Oz!qrX#U+;#TIM^$xrTPkop@l@@WsXt@5(T50*w(pA*nX$KO9U zG%>wzm^@mG)V}`VqVd>nK#}zaTGG9_7qVef$j1B|mv>_oAt?$JfI>$BqOy*otr_FW znn47cu5|Dtvk@8{@l*V`dm_1xKO4&Ddf}&uHo;ju$^ZqDUHd#>C%Qp{P)ejx$?ORQr zZ_>WePm*eoc`;3oMozywdgG=|BGw zPlM~rJQvWB=}&dph^7~#TA4u8=kmuEi4^MbWA;W9S$yqRE@#K^nK?(C3_oT@5uJZ>zKv3rQ0Y+i;0BfJZG#z~ZAV#>_r^E8}a+J8--b)e6iEu)6aPBk8V*FYw#PKJXdarK|-&ucKAF zJLHEyk|_Lqex-@6?uaXZ%9%stQz((U8_IV45Ro8|alV*_v_7^69v&Y|3*a(C{4;dC zRNwj@v@zEnboY*uRk&?$;u?J*Mt3twXbItaRPo$(iux@<{2SAh-c!ya!tm5(YHXmb zRB^RC$<%#gm&sJ6_T0#IV0tnA{GA}!I4IvgA(%Tscdph_fPIYlqKAiKeEC9lA3Jk; zUyBO=+KZ`0l;(kO5AJUnb{`jP<}d7P0YpAmm;CiF;R9G|FxL;?|?-BJ+4dN!514NLPIIWAP1GXPT4ho%&vs@&O64l9>4_`go z_yKoO@188}{mn}6L4l5eMHo@3^1QGvEZ3a+4g@d>lCF0V>ZESP2j!MPx7RYM7s#0A zzhy?1o{ncYUlHEorHxncS|a_j`HACKUdol=aiDX*ab(O)%&Hg4DEDf0VU^6xlwCH~ovm@l~ES6uIQ0@{fX0l6qj>v<9dYv zW!4pQq03v-fu^ozgO#bgX$jToRzyK@e>Gk*&Y>f@O_TF90ex52v%dv4URcHooMbRg zTOV~h7%%6Q| z6xqgmf#6Axv(CQQzLj4xsT^7kl=AZ{rVxyxPsH^R0-mwjPEVd9DqK_YT)+vvU@QR(O`P)%ISgj$`l&rnA}Ib zRxHns8Kce0@-x&gAgmD0mS6PYl7?kkTEe6q6Y1vuynTELn>@jK{+Dv`?+dB&YKS|v zU7^pIfF8RmJj5M%!mcESF%*d3pN|c9rlwf2C3qb*BjRwc=^SM;vb#6ALBb$#BE9w2 zQ#H^^9*r?%8pEFuHQj*|a=-d^Xowugilag8du^R(CeP`NnW5-~Uy%%n~h+awPnWpgnN` z!SG=dWLt{cer!KrxZzE(Ib1T{J(w|Rr$QHQfc@u6o`HOys_HZP8JBi}E6S75VX7|b zI80-a7>GoLskfe;EWhQ`!sJ}*sR+$&$E62&Kgxn~D<FlD{J2*TsfCBU!J15DmQI5o$1(ads!Xr_n(B={<` zM7Z}tPTzaC&*K%Rq$WR}=yoKuMlDIM@74M0D0}+gBNe65q8-h{!)?=?OCtkn(*HmZ zx(}dm7Ju1LQ7BsAKRlGHb%Ds<);9RITe&`Eyx2tYtP(036;BT8`BK*q6uxf=K$P6D=k`wt z27~gcSCQDEU;tLiED2u13H$r2M(QxlwwKA_(Rn@pgkF@~|6iUXv*^y9LDP!>pKBecLv2Aa{yqTKi;fl7M+~p)y(B)&%odz< zZWagDpZYr5jefN=Zm!cDv-x5)$HSs6{RwT{P?lmPWU^OY%fiBL0d8NbA=DE*04Qkq zBGVhAjKuW9ZGk<0zrHuCLj&xn7*TK>^{2tg{6w-N4=7AJotNJ0YJ69& z&r#oRm@-1icU&C{$M~`Pm_KSE`yv;5(RBG}%1}PD)E5yw-E60F>)TMe$xQi=cX!iu zgQDp9pob?g06{Oe_aLn{?Cew8LCq*J@ zo=^5ajGL-0o#tv6GzLu*>P+Uw4}n}>GV~$vkg&Ln6zu5DyQWENatIH2qac+Dw{GNT zm+?@cADK$=VCy+E3zw&(rQwu0Dut$8AARVt2v3c~WYPW)D!9JDhopGsCE|g{xKT|5 zQRV|)S?v(OT8Bt8D?lLD`_Msp5VPZ$@ybIa0oAIDx)kFJMC$K%V=8USOmKOCAw~$5 z5fja_;_1Y1eLOb)?Ujkx<(s~!#)-xqZPchjpA#h#mp85w{+&)kWnwKc*Ea^T^E@ri z;JXFFLmijt4fo}WVKEv=gS>ZRFyY@}8MsW;oYa_r6EiLhVbEmT;!m}Fv1mI_{DOx{ zy3y`lL-E6!=W7Kn1*Q(DhwK6H7^^-OMwH?oh2#R@p;8XA0nqv)g#aK+NNK75!Khic zWirB8&z=lEx{igcW?uz+c$(+Re5$lf(D8!*^OBm^x&4KDFehASt!#d&u;P}&KFuZz z+`hA53NJ5oN)}kb>76(LJL*aEVXz6?#`u}~yRKG|&lJZG;-Y!`1KF?PzX*I@B3Ik9 zj7*|nwOS}765c4&MG9!mcQ4y(P~iI6dXrfN%lRP7gVnk+VK&8KtVMY=gimWsnylUT zn7Gv6z&XYhKfAY%-lA^R`F9+KeVMNDH>+sdnC|LseNp&Fg$~#ubO{3G8qC4&Jb|#) z_#5b7KtEnuivyDv8Y4}t*&*e8GIwRQXzjK#o|DUH@F3i{p8Y%?ZLHFB>ZBuEe7Hjc z-L|&sGMSHcF647@iHG9Ya_l2*B>oj4IY1n7;0NJh#%ox3C}XCnUA;$U&7|RD@e2Vx zso@imK*BfnDS5(bGThspKIsBZG_@fww3P9$3f|e#s^|4wnaw1+iUUYjjjd_ku<&q9 z5p=`pH~N9t4N=5iq$Py3;YbR*0x`+m=blA7f&YDatt2 zEHGqBp;;2sYZNPDGIhQp?1eomLml8f7s4R(W8uwBGk*cL&B|5@ZnNpGg*4HVyblo} zcIHTLcRPBRED;D$#A40}$u_*`ex7S1rZ-RLvn1_=MsM*A|9D*kTPzqIJZKxxk^zyX zauRQIYa%jkTVPx|il6t3HAc22237k6fwAhP#vFegtj01^_ z`9D1zTeY*8b2cq#Z-X;8y9-_nfXkKk@=4b^SLi zFKyk1O4dvcA9KuOhDGr^v?wyx`;ia#MU5?ABl;)cly1kGbri{Wp^18f9XShuUJJ^Z z!$A&!U+I^;s8oj>|9ujhr;HkFpU?w*2Py zU_?{w?Q1G40`z`~Az4h3Uejt=FYgv4|F18xGvP3u z%gbvfTFEi^HLX{~%={|#-7iK}a|okZ`~qdoIijQL=iX0}weZu=g{|7fZnRx~^x<^Tyz z^bC&v={RP`>?;id!QvQEvo%RN`MP+#p1A=#<&zn2hkaffRUvH<*g`TD${{_He^N=# z{OZpH3RMbjML!-Fl_wL0?l62e$b3Wd!rjnTE8EIX2J_(A60IDUUuZ4kqjrj2>+7$p z$v*=gP@@MK?LUI`RDg}~m>yVP&#OD@b4irsOAGoc-fli^DbO&T`Kqwma>OSBe_EuI zd)u*w=f<~y%WJ}?%B5FZ_1#EVfzJ4B)43M%^^JV$9#_#s> zJ?ac|vNjrnx&@Zw2Pa(`wx4fbt-eSu-bz>5n(^6gkqr`(^Mr#|fvPTdFcc<}2CX_H z-hov9HL(=3XLP|c^OH7wyC;brQx~#$I}^^wIS7i?uSVUXShDc$_Ycz%AlV#Alss<9 z-1Ao=hxeI`m2=2Va%J%T-49^CC%}~01AsVjd38sec2unn*JTepn4TEz>%^4HUq_Hn!284{SbKgJ!04>@&g2V6CiksO zJ2=~+KjyUY(;E&QY5zra3bQo{bv%C>}jRo8O&2kOKfvBH@FwgrW1bxRX8qM?bp!m z$~zfDNI9^uu})TJN=Vn=clxH2ql&tGPmX_TB0hT6$5-3K$9sehgTUXB|N9Fx6MI|^ zy6rJMxN)wu%UBvNgz7eo6}i6v6GIoGhg z;FEWj%lU_-HCRFD?MdRn#`eY^QyE!PAU(WYYgiVq&|XY zs($5byFGhuD+$LxXjR?DWa)f1r{=D*>l`g7%V@F5yXa_{fBT#%?|+H{CoqbH7!aTT()^3iCxsgMs3i_wl z9KG1_6`MZ_M~qQqH%-k&u=HHs{CBtiQrk4fK$8mSLx9SRAx@+0U-y8yqX@bU&_{h>%WdchLTlMZP~`QT*NaIoRD8X5&2Y9=TH086?s0O zm-Ydhf+7Z!J+Lq^%&s%zPdT~hkDG~vwEy+D!!(0yNIJ=ApHO#pDM`gkrv2KI^HAG~ zd(ee!lBK^t@04z;eU%i`bbS8JS96j}jSTI~K?q)M72TEbM-eiN!V8Yc!W)>o%>c*b zo2Xu1Y)HZ1{WkGAu~XfA5+!WctUsog(mIFa&5Mn<9~f2yYP&yYLX3K`Y$ive>bda;H@beK%IMm8|%7KFxVIS(gC$yU@%k9;~3Qr z57&(&zBk!)Zuo8PS!I2&%!3thKH>`Ru{yw!SToC#-X>}_@efO`BgjDlE1L{3llm16 z;Gx?2z=!oqHvgS6FgUfXfOo->{xX<5d&ssR=PI&IxZ7dC+b(DNB5-f8WJVZi_}4U0 zeIMn9II}Z9I}YEU{loiw9-#_eq`tLPV9O` z;$H1G2nBNlY%W4N3IrLrv1HLI2>IWay7ctjNBk$eCXw==!a{3WeXLMW6TBMs6N6`$ ztc5S&cAiHcyQfMB4C3w_Qz9FhpJp#2r8X(NJM)ui$b=Io1$PVZ=Q|3(G5?xycP{*} zo2cD(%%U)TQhG2e`ei|6tZcxh_p#~V=#CDXk>^+~!J=DJza{Z~er9b|#^LJBaY{Hr z$E(e zTkoi^m62b$j7hANQJ#IgJr!qq$mQ2E^7GNt@yzSUjmI!{k|GqLSQZPm8IA$?hU`ev z!Wua=AnYoT=d1;yvAmaGPQ&54D{QuwO>Z3D4!e= zp5sQgMW!PTAq-}E(@)sObimb7!}Vp~4YzGT^h9a7>-1RVkiVh(c&?>Up8h!) z`Qre7czFtQI6LfKg_7v|i3DuK)wC4c%Kd_8+M%D!EUcIjP z^fUL)j9SDSF}2f+;;Cs*4C}x7+50H(?k8eu`IRC@RA`zwZ#OJB7(Mlm|3fJZS^tB; zLB}|>CN#YO$jIPAYGFl8K+GCKxG(;qO4U&=)C{B$?y35>)w;I#aChS9CMtJ)Ut-!!JH8x`S6urD&Xxc5BfMnJvz2Zk{3!fw=n1y$DRw=qoo{V>Ut$Oy z`{mDX422Kj1Q2=H@rs=w`RWC;eO8&DUN_eL#^;z6u>Nwj$q?CO_w+Z;M+HhfzoN;> zDE3_Df`FZ%a}@(2d@KB2Xjr1$E(8(;_CO1Dw{qIQI@ux(k@m~`Vz{D)(bepXt13*^rQSVpx9^+t+^yf!b9&F2$MGBcIq!tc*u~`6rS({H zz$c{~)Tx|WKaFB^{w<1SD|f6F_HN_d?Wg<5oa6>^zx6OFR32mJ^^?a5f%b5y zKoa<3{O}MW@bD9$O`Pwq10ZYc)j%YWCJsQ-CM?YNezz20_C7#3<0F$6n*MKfg{hZX zF&p3KPTnYZXiK=XmcB!fW@c3q9U1G0wnjw|bq9|Q7B@ha^%QcLxia36vf%((OMFvjy^D=hmD?^%*;angnB>%$zhEXs@HwsQrGIcRZ1ygqF!mI2pD#g%CdHlXe&1I7+l$ib`AK#S?_5gYsEB_ZXRGWd`7yWRd7oNDx4}iCr2H zCvmz!-8s4gXp({+-)G>1Z{`s>H^N}~{ZL>}L&BrXIC>EQ10||Zw+;&D_>jU-*$#FA z#7L~m0yr&wH~tEPFJEFFAot{VP{zs7rH9!RC)1;Pthu2Yt@iAd3(0{wIQfH!F_2{T zs(mpDGTj|V$Tn-P4b|-CP2+SJtaFCDd7pmr|)bFl; z6fgRIa%{0!v#s2W?WkH2^l0Jq0sl03RkRQMr<{~O-f+=46(;)!ZLhW3C=~V0$CJ|U z+;AtVSmK0yiTtLv>@dC)Jiw>dp4Fkd^&ebOH)$5@oqpFY%<;fZb%5$3&~ zXGAU=Z*`Y36NEYgD`1C66_hIv?4Bw(2pM>p9oJV7&c6YVDqCgAYl^Pt&k*|$gctVK z9?RxB4ccVuCz*hd+%{Ua;ywf;c4p1 z*z5-fo;EZGw)ez#H4agwqWcQSM`u^U+71O9zutE%0`aMMHERm!UN*BEkbrDDl72gq zQSyBO7fFWvc^}jMS?+kT2yxkA>C&Kp)}d8ZwHCV!y_CP>n#j&=oU;bLW@{UFW+weP z4z3=vFKE_tgJ>!wal6661RFu=^Q|)lMB}d$F`ezW_PL^~wbGkTexPVH7;&cmDj`Sc zw%Yu$BeSnP^Q3?%)%UZN)_xrkdlu|qW1*rCZH z&*@=Gb41lG(G0B<|22&V(=Cboho*!o2K`)?a+@DOY?v z?SIuLfM_cvcpDD{5B^8-VrBV%VwcH3*J@xH-@n*pc^QUX%I+?KXvE^7NoqcBl}tDh z@k5sF3p?7Oa^mJIe%Or?@0)wMw_|9KlDsWz+#WIdR3 z=vz_NfkO354KNz>u_>hy>*4S`uuK>%Znj;}jLMq@U@8}f19@xLJnWYFOm_G4@t741P z^G$kwC3Kl)tsr_mM{#`gqZWnOf40l~>vAakm7~#c{rs+#8usgPG|qkTNBIC=sVBiO z%01|32zbGBQLuYN^rK3nX6zPCJ^ye-0v#xkYqjHadLtZ7b zsBV`S&QQilYJQMFQtMvGSOeTxxS2&?1)PV{vyXy;=mH`Uf*&Gc=4nmK7!i&i+%ceI z2Y@>SdeG)*A%lDPvRURa~ zllIrNsf%Uw%!o8emu4$4lE=5qOC&kC*y>n2;jP*MoyrYFGUlNARV3uU`?AV4_D5zd%N)AKe|i&&Sj!PGjjkAj3l& zu>@u1aK!tGm-5~wfUu{{85!v$i*8WRly8f~;ZQ1pL6WT@4gWoVV z;u^Tu?MOj)$o^jw$q-V&db~+s*0O$>qP#EHHm*h^RZmwXbunEOiGn!$+X?SC%Hk0_ zHD@S0wy7UwG9GU{btqIe);1i&u8v_3-0NLZb`dFT*Rzzhqq~B^TceN`H#@6S7ze2LhY| zZK~bOxHqRK)35lyD!6cBir~6}vC`)I_}jhm_f=3kgxXkjr8*=n+}){>B6Av`&95tY zlD9^8#5jtjpX}acI+YDU^m&sj%L~>k#4yo(Lz4aWeMgJyO~H#}C8Wc5-6pkmL97o; z#m3a)@(OI9*aVb+d#i7#)YvuN#YMC{hVf45A%}v@-aYmGyY*5$fV;^mf#J;x^Q}oD z{_s8r4!&(|RS9o59+nQ|HZ@W6kJUR1MjJop^qI!thn|0%7SeQR`>NMJ~g}B(%{W_@tWO@28pvDB@#O z?HzT4^tJajw1*HkKU;s_<@8&lOB2+-E&Gw6x%?^dj8Y7g!MwPj#IS}-7DNaku=kxX z-w*#x28C-0>Sbe^XWkD0!wvWFQf^Zd!_uJpgRO7UHz%Xtj3b?&P9hRkj_E&%?fjTi z^sM)ph$07DomK4_{R&rk?SsGe9&-${_b6cRRg%ljAO4xC4cERl*pB;zv{Q$_zt203 zophV&hKTbu)9)uzP8Ial>VYf7J;B8dW716>Upa*r2TW-~auaoE?y>Vl8;UFQhW_y? z>0e-r$AUZ0y7^EGNh8N4mCKq*XANJ@!YqwV8&uYMK3GEYAdrSqTHZ{x*u#V;lnDq4qK z3#3A}SZ6F~4$YE)bv`&JaJAQ<_nocZqEr?4-j4%Zq+V92i(i5_40=p5c1DjkTb#Xqml1 zDy4crfAN~)73mj@1=5_lZ*cPRpETl13Y+h5PXgRtlqx|!oCb1`(rTUwh{ z>WT1#kGsoc3nKE(3=+nZo2MkQSUxEgX6hcP$YI+1B}8U-%U`tpNTw&`0Tu-W3MapU zvc{!3&1p`Zzgmr%bY6fRK?F{m+ga;H58z>?@#y{d(+bn#i(FA#DF)%bm~1QDB@( z^`yfaTPq#o8|#=OO_rS`Lu%@>IztPRyJ(6;T%kMHi#WHrXYDm&aelkxqC#>9Q0RgR zczmGM^94M9OSYgQWd85tpPlqf$1g7@h>o7BPL95GFhmxOL(xGC8Q|O~MI&JRu=tBW zpV)R~g3c;Zz&DxhI7mbhG3(hDuB3@=rg^h9xLI)MoeyMT_rY4aF+DIvL_q+a0-(qA zKfUeBQ}G2a|A8LEaLa2p+ehkqkmr#x%2cmexbtObNiOVVqaF+xJtHLuF9<|1Vn1Bu zBt$V$CU?7@QlGz%W4Owu5^Q_EXyGmJzr@cPEB_OEsQkIs`2T|*>MJnlF?M$eP&eTj zy5E)P?9n{RD7!!LcA{y>iCc|2UMRLi2O{OcH?xXKLg+a9iP!-7j2`jgo4gjSs4?3V z+2@KOwbSiSC?FH`5A^sqj>o{egC74+k3GVlYtgVl0)HV8`kza&uuH&Nkep~V=b9?i zHlLfUYFM2U!zpzl*vbt2RCYw>*(bEHDUoUr%8&Z6_1gEX0ld{P8OIS$<|m!XNlE4x zo?FGBh`@ynal-M0?yaLGm_qXmwu<}>bv?TDse{i@ag;W z6M-CB`^=|I{e;z7n_>!Xzs>jznX7sESey;Xe=UDmYV`l_(LgTs$pzTd`GA203=!L< zg64@wljn~4I|546LEn#O542Kcy_3+sFZF+y%zU^o(>mkgor`>gEwOnf03CAv;Jn;t z+0@hTxpxqxasYA*5F4%uC|U)uMNn5c0He}S-e2_aPW;p63SI|JQydY8^*oEj%g~4r zb%D;<9+h3$Sj5^0?R}N{?O4qll;jl)Iiu0AY5fb+bi%jpk@~#X)D*EKY zAm{oD{e{)l5q?lLzxLYdMk=UK2fbrQdQ z`{~Fo%>&Prkk6ckw-RkWXghbxNy{+(@V>x__zxM)nP1oQA9FfOMikV=FF3Pm8(Coq zYLsu22$CoJauqPN4&wUMBp&PzQR$o%4CkH*Uh*@uKt_C~L)2-M&p7IZyb02b69FzE zM6A=Bt;5_aLSLh$Mibr8e>qDpepygJo)wbo1j_&Hvd7TLWZ8S*fr(tz9|cIc6Ss<% zDgXG8mvo5Hc;Xg++gPG-Y2nrvkioak3!ktv{F?yVYo{rQqza#H^_czFEW?i<@U{f- z+IJCB7cO|-aC6Bh$$bfmmdZB2ShU$sp@DK4T|(*_W1_b;&RV3O$wue>-n(1`R8v=G zR)lkf$p|QEcEzpSkS>0*`rKQ+!Y5n%{y9wge*^Gd<88q_L%@4|0V9MI_G-IA;{Ha+ zbf9Xva^^d34UWTEb{=$r zmpmK|?nAepU6NwplLMsiJnawd6{M^{OS=Bq-FOX{H>St<2A>z?q!Qm)r5me&41L^E zvzvL6sXstHIU6VORcxT~xlm_2 zd&stWEN9>}${UChk1!p-3%Y|1Md3{E4y`JN%`s$ml)1Kku}sLxw7PW3Uf{u?`o!t7 zG0Bgdbs*m&>UHS%{F1b_`x!b4i0K^^M77_`5KQDUKE(FDtFV}A$Su1ImIfV=y%oaKnCC#z${@tl^OdFnjXGG z)7spSLV%`kUnF zRHmZmMyWka?usZY>mn>UVI$aM(c1jbHl;P)FV5cV?}}X3iI7IOV0d^c(Adxv!&Ji5 zav`KG0~(r4`N5Y=dku@81ao5=DUVFmYn$Vi;Mz;I3a{wLhT*J&)SX+1KNb2C#VBQM zFWk!r2*h%^3h~6j0Mc|3MGsq32-8#EBRd$w75hbUmCB_8znQm_p27`#X@yarJkMf!v!=VbwpHpWRrSCXY~5sI?Ka*YkY z+iOBZ76n!=UiyzsRg!LVNd6-GtZ$hshuC?Pp33JDpO+M*%f{UuHTU7sK;g0*A2bzI zb<%_HqpEsDH6*p-)Xe`ywTTXb0mq*+n#hM6k7A&ypV}EPtElb&{;{(e7)iP0tE!^_d&J!*(B$TyzJKZb|%X858lv2dax+RKlMbCCzB@v!r;M@q=L+(USl=e1;ST2A3Q zq%zYdeA8H%dcTIFT@fs%+ao6g2hj!=Q+DNR{V#`I!##;sXLSjIx4Y4qjhUpGZEzn+ zxzrmk{2~7LcOz)7={T1xWHR&p0)jDht2#gKKZbARZxPDi2?EU z^Sl>#@wR>e4m_vc1AA?0HuW`CGL~TpTUOjoLhNQfmVJ?z{(*gKHtt-t?Db>sq`gCu zeHYR3j4h-eG%*Jr@(zt@3W61ZBgG~M{d6@7pRIA{-i}!?is+G;D ztdWDez5A*vMyzT6(OC)Zb^yGJF9J!1&PMkAdujrU8ln$~DSxzM$xFOu9omO~;hh2e zv0_6S)O!tvhYi8vg_w@$B+-}fjkf3FcP0#-*d zP4lMA@B!)0{^<+ zR(~JeQsi2Z8fQ*Cx-yFUMusy`j^;&%v}+lTboBoDRHJzflDt z(|=I~Ai6?k0#5VD8#u!i!QYRB};x;{}!h}ioO zot3b-1_5L8zdnZQT^N-d?Ba%)(cS9;@$%su)xekQ`(Fyr^r9TS--NfX5Pfmlz=!Q7 z{eC|GvcdE5R`>g`6H(kk_Paf-Y~-zH=Bq0$FR>r^5I4>N*e>x z1bnHATk!iEL&a2CD^xvmlEXLZzrTIj=EiQUwip^5L?}?()vcG0XM9OW^dlyc!8pC^ z(&?pVqFbfxD7M1){EU#*ea|EC*+Ak!MI9*&Ai}eNj)QBnxs825!|gKA`@BT7j&%O_ zNtL0gP!x}KOY=JgNc^7dWT6zaKPibbvcmB)#hyV@BEZQ=KNHLh1$8FXBftO(;Bkk9Jw}(8_}Y@4DdnSlEnAP^3wKJ=UEc=5YsnM7R!<6W-YR?0EN#^f)416c%(`MEz!KK1@FRl3RQRZ0&ifjr zAlX2ia2Kl>5nt78no%}9(IDhaHxXm zjPP&U0bHWphqesz?p|%UEu|ePx{47!v#}mu39Bimo=)=C+kHCemdXevAKn!4o@V-G5w{g0yFj5-$h%ISD27#X z-~F012jtIf;}QFDllKd%5~5N+ypR65huq%&i*9om#hyByi!9do(ftwWo2Celaj@PR zz!`(Y#dzOO?t)Y^m!OQCz&DAxRMg}C9A(n#_a=8qBwTV^34`-D3+!~fXpDTecD=u% zd~xUgCCs!uDB7-H&WiHtHAq~53?hS!lr0Aa0t6r2lRe#^;l1|)sQ(yY=p=%))|;$S zBQa8Q>s`8Jbpoqv8K0$=4Y#l$2gGG(r_Az?4(mwI(6zJq;^Io2t=g(X?ySdkcw})I zZH>^+fW$urh>Vi6k+!2F|AsB-U`n152*I?!Lac93)|9bs+^N^A>?bmx4mBPUyw5j# zQHbWt2l;V?)R4*T+2+m3sQrB~sP>3ybdp$cGdiet7!RL+pGHCV#f#FhDiF)U2l153 z)9JykGNgQgWM%~m4wEGv9@vHDTj^s?+s1!7@;5;bz^?b5Q0OW;k8c}lT)~Vm64l1M z>%c1+FnjOmN{UohX?^)436uWwECK0uD6H`{6E`aY3W%}*6~h_PHt6lR3;A#xF@8;- zEcb%!qZkW36)RB+jtMptgd-{edXquL9 zwj#a02RTsmD<62@uf;yR)$4CAVekR>(Z|Tx+7_piNE8o0&J@Yw@rD9;a1UniohdUp zLNb{g4?r^D^`br6TfKgEgN|jZO%6-ukahG&_Z0cl+8#;M6+yBZFOlI2e`(eS4 z_@)=r^eKnzq|bmT>Lj)`&W!s3pmWq^0qHF;(+|#gGM%une$zGrZ@oM~%ru%U+eys` z7c{Sx^3nZ3+dzt`%GZ~~dItU2`ujwl77?QSt>o2SomKPXpfs-rWxd6xPx))e8wpO& zY7`e>FwZTJI~WOqGua<&9F<>iUQq}emU1RsP1EmWxFfKfZXf98?dVeNj$&#|G;I0N zHjfZ6G|{@1%P^au_4K{HyC|L87Te%I906yt4`~1!1=(9ZAl5qn?}QwvH-QCR&rM(v zd>dGtwgyXB7558k9nL#kDD{pC(XjAOk?3O5WnW_^_&_7~{yaqe!FHXNvX7RI!Ffi+ z*uw6zp%vW4A3u~&ndJtoISm4A={{Z0foxqYxTZkInGXhF*@zojdl|P1=Zmh*Jc)qMYAGD5Ha_1v_bdjT{(#rbAjjSKa(c z)9%LgK~F!)gDnGzhYo|VrC=xnm^hke+~Z0Y1&9mQkV_HCu+>i7Y9v9}kEgiNbg4GR zo`1-P41_E2_;uZ8XpQpJx~vCqo@uie``4I3iBh(z?+GL>OJUxCpk6xDRUAlKp>!tFAe+wLj1olc3}yB#E`_+HikaUbvq5iHomfAYH@;{~=rZ zKH-Nqu5YBKJG;WZq6-ih0fIySSfp+UgjEy?q6QBMGT%b{ZjT#%dyf=Rw$?MPgwmP7 z021R(hJ2Sh)CL9}-y)J!rqTWX^y+(3d0{-|%cD8sKBThe3~UWkFv50pz8dbLeGd@i z@HsPCDo9(9BrI_ZtW!*(K;TMX-GM+F|A`6^r)XRv{wWrWGSmp0rP9)<)wp?voKL5-*Yv4;uhwED*p z{nwp7hLcf&KY1Lae5Ao`QJYN{Y~Oh z;BUwM1XI009uO*o@mA{0(^6bJqtg5{6AN)SCjM!4(B7EjYbE6-63njv-I`?Zdt z%CSj)78XB<)JKuqxG-j+FlbFamf7C77lJ*9Dt1R z-b=OvSpngtY|PN$4R}5;0w7pnVP{N1AfGTrSo8Z`fxhl^_8~Jqf3_FGfSKzc-b4B1PW@N@Yo1e74@J7u2~``?jw|2n^t<5|cgTk~ zvJ**mw4I4Qo?7@%wf{Y0xl@Q#>l_D&u$U>(&zAAK&*k8s(I7}BPwrtHsNy@XaIO2^ z$MdL|BPC6cmq|x%tk4NlR!S3eK%SBk{Jg# z3tYtjYr1lrzCv(X!vX!BiB+mrjCYH=s#fSj5s5>F$ZVCjD9DVaej2fvr5sOY>U1+7 z=2%3%S`~FGNVP(%GkV=>cWPrS^_!{I^@05`7{j~=W9~tk=h%b5@ggw4D}W@#ytR1G z%|lb0`D7hOo+*7fc-w=w5ObHwRN1;tU%%#Fh{&1}1_l{VQ*TO+KDwgK@mnI)4}nUt zt}O-xgg<^2pne4eEE0PF9{mA$-bvSVGr;a!vnS+}d;ZzU$M;2~7J~sNECEcKCZHj4IuZE~S9T!{u$DKQC`#dtv8;9!&jR#5s+%t(JFdZo{25Ub} z_ToUqX3KEDvAa5%NST@$gHkDFJ{!|AS+6|0|IMq_viR=-=MJukE-3OYw671%{W>2Q zGRE}8aefnsIyrS~&-wo4CYYu-1nQ8K2Y2LMXE^PYmGI+sP_fOvCCDxoxyybSDAx(E zc3;ckAE4=;^@M%JawW(+PJ@zH-^RL@k3UEBj#E?yb1+Q1F)-Q!mw zp${5K*5}DOOT;2Yd}c?Z|ruQgdIw1H0je$|ket zPIW(%wruIMpzo_6>WOGS1?^;6^d0wN$FC=p+=7hr`abt;a4BW^ckd~G--y0Pye{Ed zXd~|`&ZG-JmsdOBWg~)_09ZX#xRHrko|C}%dFMP)8luF~&T)Cn^i`?<=KD3;dV2-3 zh-N%@gTAx(1I$M1Pe1vEoJ8z>^-W77_#ntp_;3!qEUB*5O|B=y_|47h#>^(fvBbr5 zR6es@tRo3CrzKs>q++ngwTc=Pk^j-FlbdL8FD;jrtBVZby)TucV=am7E-@2ImcMPI zQ;;S8Upw>$ppPMgl_CcsDb|$hGMH&99YKBGPof6J3fhDIe9Ag?VA}pOJZ81o$vd&^ zq+<62o7IvvvAC;~Yry9;OC%xr!D!0}UsbC0ODaNLeV+@1NzBLc$@(qTK#!e0z9<27g@?{;c-ZAF3IlXYj#eR|E9Qge8dxMQ zytwZ_pQYx|LF*bYP&w+ZM&jybpTd2a87OS14LEcq+u&eB^H{x18Ihg6-=3!x7&q_5 zs7g7L#bNLMV7;=9OUTi+$XtU?Kpy#~6y;I+O%&w_3n_p{QC>hEODokZj*#G6QPiE# z?{(@f=cmAQg6&`HenDDMX&wE&7<~Njm2$Ixs$=D6?{8?XLt&${;rEROIVIc}B*xz% zqv_y|{aDU}%)_Io#wgfFar0t80wJ{ytXxBmd+&?a>#dp@`VDyw&@kNTo}D)lS<8@Z zqjnwtWc`s-qWUOB`ji!#r4zHM%MmMjqf^Rp+F$ zxFBI)>D)1lpRCtz1v(F=#0| z1M-x<;WQl`EP*HyQ;c(Et#V%0%j$X5tA5ZD)@JnC7QT9TDd`sA{Xk2j$)9r%1uk23r52r~hP) z<}HB>wo^b?3G{Wu(6HHZExjCt@!s?&Qq|ts-ekF%SsP4*bNh7Ch`1u#Q=cg9KbQBM z?V9|aa*sm3#0%?^nkX6S4~?R0z`@=(Yi(5V*V6F@d~%SC`Rk#?je zG!MP{MHL_!tfN}%g%mR$HqT8iY0DF#@vQW7ZkYWCrW!keyhD7v#PY4ZkradF2x1en zSwSG`Ofet;5Gwes`F|8JfZY&w2I;b{5;|F6*S44dI8eKe$!gB{vNpU zdspzlU@!Klz3ky$%ZS&zW*JgDv@Cpa<8$YVLEM4@n5L78sjz8)=c+A6iE+pT+URE~ z^E*HLF%+d{771!g83M~V`O64;V68B)+)l&|#mF)0D=qJFo`pKG{)g24nQ4tv)p*9P z%KC3zyN<|+o{EcQ__e!*o4h+M9LIk0tmUoKV{IG0gz3k|+YU-}N}<56K`a0yBV`bf zK)gY?q0K*m&MKfolHryO#K9-}?f#eVAVCDZlQft2J);?)&iH+sCy5ClOZYS)H?FNd zvst&VvaM)d>W&hWX0<7nTbTBanl_U6e#+2?4-amX#+(Es$&SFu24lZ&lF`>ITk4{5 z26>D3+U_nv=}GyI3j3Z_e@^NOnpIXkN97dUvxaW6O%{ z3d7odRqii@*s>f%GqP21ngozx8iPo<(77Tu|BShKVoJ*rUu|eMi4O))JWCSj?kqif z7W9OJk-fZG(f{`)W^7VPVGgGW*$4ZQ`#&fypMJj=4G;nny%3mgACd{AjEeWxsE;AA z5Ym2VBf?WgS$R8C@28?+Wg)63y(rWcyRx{qWi`_FzP%|;gx}8XJ(dIwxBdE>k4Xi+ zTd{DWmLlPC12$L`5ESw=N#S6O0eBK{@xkrAw z^?R}kCmr@sQZ~|+<#=FlebocK+LGrmutFua%CGe)q5LrW>J33*5goAUA73+t9*AK4 zJoJt_omon1c8#ndx{r}{l88E%flmQ?C(gAUH2fb|sk3~mh!@%Owr+9nd?E4MTPs;q z=m_GAvxUa)Eh0CG0CTnlcWxgbZU#0IuU2Pzc?ok#TFH5Q@S6>>cvjZJS@C(lwsTQ# z_^Gd3rE!4CJ8~v#R7PP*C(MFBbdD9D6@K7pl<@m=YgGmSZPJ*8p z7Pei}1D@+>7Z!BxmbI#Ecd)Z&a*tqwqsz<#|! zpD^sqPZsoppREW~JG3(5IC0hOj}vfDisdvMs}}1<9e91oUJgrSeS7Mu6ha&#zCed@ zWf6t9H6`0{ZSX=U>CH?xO{f<;$`dKJ}Qm<5>Sgm#U{$tR{~iAl$b`N=fz zNzm)tpM47X1{v8>(cSFqIJ2|7=qp}`(29GNHt&VBSTIveq$YLwtBYHJQ6W+e3{2=- z2RMk5Ah<_Fs=lyVM6gz#jvM{HF}hVRiT3%(>9eV6Lz&ab!s8eu;^!NMMM%j_B3B*- zYjH*THt%&&x?am~wyz>uv}l;XL#s|rxFO1huSWh{d%r4hIzJ_FV^wwX;w^4b)*@Pt zVBX#AIt4R367-SF$~?OBp&Wscca+8qS>&}ItQHq4m$St32ikq^?@Fbmo;>NIu!ay@ z6CsKmhaL!-wP-}b-p5%Gi<{D)`1W|LDLayP8a^6TzK;T;76^2k8q%>%4OE)7qaAPs zQntQ%_)HEj{vmf&(MFamdId8#VXAf$+o`7Y`LCzXs&@MnR$C@=%w~31LtHxWA<=qM z`e}7C&R+#Iq+McRChvfGj75Y`V8=MS>}#lGy2+cHli%dcjc*CM*in4FW?PVA?^iLV zH;sS&lEC^H&pi)8jWZ%st#GnDDW=%gf18(2YabVPUKiV+KHeM*bDDeRh#yA8CVG|x z@@DA-3o!LD=>-V9?Fx0|x-aqhzYtWuS3O;kL=7Q^V~A$1*Zf^PSqp5k@vYni7g#ID zV$C6Fam0_)81=64_$uh|2@N~T_xj(`2>K&39mA;ot!6pArUw zP89*FBtNJ}1@h|y9FSjRjgE33+nCi>^dD%m5}Xm}zk{dmQvI}lK>Q^ZG6vy5xNxY6 zY)q;D#vg9bhe zy;vtCoYi1ip`ql}6|gd{d3i!N)R4{}QHxX0__G&Aa;&feC|2pQe`*pqj!{#Vl$tl5CiZU$PD8JqJo-RVgx)Yf{!P>pfbP=gS`1`pP-Mo z`1ST5IWl{(#2C~xI4Y>HE_002h|w>Z&8Zhvm1C*l`Opd_(4d6wtu_W()!M1GRH$a^ zo|Tc6(fhxtf@c9iGorIFog)Vh6rv3xy1tZ!9*6;`DGY#`0{k7MTUSfy*`;PxRcBao z>>y}U%HQt{zA7d!Rad-}I1?f#vFSHO;T0&G|M?j?BW~h5%cL3O_phN^Pe3jvbhX1KwmB0!wQLgzJ|W zkXZ00E%4Dqske4q?Msr-AVyxo6wQxLG(^A2b!)|U=(4!P35JQ$N#QjQs=I~lLcei7 zmckdNIeeS%U1zcHm1pO4bXwn^RrT2eu8IU#5ZHD*_9+7gSs#Ir6$;SS5vzZ#Dy%!`XLH@Q#)C?$Tej|YswMXqD{R$7L%a-r3{d^7f z3#=O^rIZvbC?0U(KZa_`yEd<8J$L+#mu4gdnyAPc1ggpGr(Pj9F1@Dib=|;c-6r(3Qd51zT3g`&$`k z^PgL6)`kdP80SU|T*TC9@#7shW7#VhjCCYxiY%RY8ee_9x4KnOs4>=I{cXmgcxoz1 zY*vSNWRt0x(;G|-hF6D>2SBtli1q3(ibMxGy|q+wjNi;ZPcyIS!h(Pl*^iI#$=Db( z(RiMpvu1{)ysS4*f(#J;YO+0P$@V^K9P6qidjGrov2tGp$h*UZz}*Z&o>l0KJiO!~ z0m6hAATYuDCorL6tQ9NyCombawi1~t4jSJ=_yG$g>*}t=F$rMVd>mAgFUojz*L6;P z7_}28umrXlWN1Md%6|r`mkrgiX?{QsZ zz1Y|>pDd#BkLF@N-JVm#vPLK?DM^a9wc!#QkXb}1Y@6dj?!ybTfyp4l z01C90;K+rYgTlH$*mcBhVcp~NkSdntp`>5hnV9HO`i_;GmOW91I@6tjG;_K7VfE;s zCwpgM(`GX|S_Ta|C1Ef2qF4(m_jKJSFh`qxz2PY#fX4Ujy_iqG*wy(p#b()_C3s(*qA#o|VNdELH>9-Oqu5>Sh)a&5Qp)@hAT z$C;2)Q5fQE&|ZNdM2T>>LYfxm-L za$?{d3bA>Xgi_SWrquZr@v|Y>U%D%PbRZjK8g-Ke5JrX^7XRLx{dHCI**4&vNcv}F zVJ`$i@vKb*p22RR*)P-8FX8+Vv&Bf=_aQe4oUt2Y3g%b10%IERQ=9Bx$ag$K*zdxv z^JhoW{umOSddN{|_n~JBOv(BdDCt8fVRQ_f(heAr7dyuTlnf)QlI<7{rmNf%AF#$p z%jqe(L5ClEq6Qf(GWX6j3{X@NLVSQR=`!{N*~wr+NcgQidGjYQrrZm+H`qzieu5@6 znu5(p^Ui?7Iq%vK9pkhCdy3-92I&v03e!v01ys$9xAJL$$kT+Yi@#HR5o?u*|Jqbo z7CC_a&&Kte#~g^HqnGIsVp4O>hzliPKT)KPYl=~>qcq1u88E^<8*cIcIlsO`?q5zB zVzJ71^*ha-TZCvyPiUK0#Mn{I_bfvW^m$-j0e~}X`xhA6wG-x!47s@7YzDJX0+ulAwN9FviRb+#nOc5=tGsgEa%^Fgd%RA>7lk1>Y za=g#x;%hj{vX-wN%xU0D{EFU4rx0@|> zmzwSTwW66`c9r-2F&!*dKJCPUqt8Gm_p$ij%tgL+@>wmi0|_AxbB6IJgf=@jPT&UR1y+C&ea)+ zV8IBBQs7g95f)`PKBe@nPgxn}C?=gA@0by&xh?&IDgoW&cXSGRWOq z(bRoYD0{M?uMk0^ey+e9jfE%^UqG`ZV&-VI?rCk{F4`SR=`u~ZA~y6;|9-TIdSo&| z^{Wln1NSY5P^_W4QMl3}ZQt}HJgx^$Wx?e-6-b#hnMqp-2p{p;xt&YD&qtkYtmt(l zI*OY>;!bPT$-k5H)iCG#ZlOPaa2I#eE`3%|Ae7HxTMI0_pG6e8y~4hLH9xS zXX*Un#Z5+YJEN2yl;+-=&gDP5)JjOD_0;a)=MHJaaMI8M$4aw{Vd-F>u(qhRkN$Bjw_p96sZO>@_#<5zjG9H2VsFlhD%Z(56B%GPZ`12}x0*hNSd&Ujr5Eo#CXM zG+NAgEJ%XmQ1v7-RY_s|hdku9I&`dU&rPXt_o)%?i07wv#{>0G^WR7Jxd$Ye;tf6o zg`q>fd2j;`cz%%PI|c|@0FAxTvA)eg&&EHB?qT|>ZynOw8)AhD9v>b%N-n3UA10Ay z>=1Dn2C=qt^k#thpW&Oqfv5n1NfTNC2Q zsZrnS-4wC^#I}+>pd2tS`SOzB?zBV2;>vekk6i=w#;#0FoHq+r$=CjYH|hW>B?Ozj z$PI_D2>o)miTh5b2rGKZQzerxftO07EOierXc?Os5gzxE#m)F~Yab$#FxV{`^rpci zmt@8s7B=p);Jx-AQb}_&TLRVq95e_n;n5wAH3SF@*qTe`_&X4sTVu1X!d#YIfV3Gt z{|8B+%Q9Z(`Irkc-SKS18-w_3@BLGW zm?tWbPP5Go3>s%SE8Lj0F7F!Mx5sFTU-dR?>@5T|Kt1OMEv!EppA0xC!wr@0prSDyezI_4&t)9Fq-qOZ%G5OD&~v|N7-Xjvef@ zBfhvtcbjjLy^jzcE(-@m7wS}Z%K;5)L4GRG(P77><93{P^N{cWRzj>B9;f&x$Y zy(GqqZLC^sF}EI58a`Q^)4XrgE7p#dJK*HpZ|OPF67VML>s$UTpI09|_9X}NLj1Mw z?mRTD-wr6U)SKua zLK;2XjW zrmJcAsGDMW^|8lq7v&r*t^7-yKsAmoc->% zwysU|#3bnex}@$0t1lN@Ca$hKD(kZKC{Mm#9TH_Ym`}Ku*mgx1UBFKe$dt!V{1*fq zU4tMX_IAfOE!0j?BLN@Fk#oC(5%HO)l(jLQBBL;34<1WR7&AYgdG}4HJfLM6A>qIs z%jvFZf$Jhe#iHgugE`@-{_mR;1ePZ#09Q5O`UQR$u3S9?hl2PuOY2_6_i*0#o@<1E z*t$;l+TCXt9}+xx`7Dz7$AY{vS-eese?%woM7+lGnhuT>`rY7W2h}!LxZhQp_;<6K zz~UXjTY+EQZuTxE5nAZ*mtu8;AJ0np%5-e88y&SfMG-C!dhFZ?2xSny$?5E&q9}Zi zZ3yZFF-%7l%|45ohX z5?G$;v-5@@Oy@}OneFgp1!GyzkmB}YNv-6KwBb#x#?MEy3dK&3*^ ziXNd5hgAL7856R(%^<4$a0r)5YsA?WBH^#`opMO3=%IU$dm#@ax0d%hr*Y{T$F8A( z+1pJ13Ia1&*ASQy8w949!O^SwQcPUo(u6$5rk!~PUQ zG^%zyuF+(6345WEMgH3nrc0=J{&RsLF`~0Si*g_@eFupy2zC&`M0X%UY^xgDI{wt8 zk?4Dt`LZ?jOJvM6&9O$AStX;gqp(!;7n=v-u$j1{2ZTqB>hA4CHLAm;xKkMQ7RekK zU**K$iR8@)ke0qWl^r_}A*Ts{!UB4L5{)51Jb)5~TxpL%{BM^hIhV6E0D1_L{f=kd{wPG*PoPM z$)=OFnCkK_sda<7loIv`u*GPQWl1oWxVbhd7qN6q4BL-%22=6WudL!?W8NbP7880H z5GO6`%eBq6`A7Mb3C0+N<|{xAwJNkaN-#}(HZ(a&B&%G70p;$E7e&su`ap$vXU7j3$)~3S!CcIz2 zH3@sS5e@nRE0==9=jlj7qY-x0ni3m$bICc0gza^Gh}ihcHAZ3K4#2Z1Dweec0QRZD zhJ`Hqx&mZ{KWBN6++J_$%Zi{Hx*Xc2c~n>v4BQIrg#q2irMv;sDu{PJVYA|PphXrN;xvtLeQmo%8A!= zspqB?-$<)o^qvxM5rTQ>a*L&Iam>L!)nLrMJR^zOlA z*Bu2C)iuT-2TTAci2(Tu+>K@`UJz8TpWV#Af~Q;g4mLOGr~PxnI!|UNO2xR}Y4Xa& zs|!V^_Ks&Oed7!^(KNFZ_O#s_$5G^-uy`R}-&PfnEkf*`j=8?$a+-58RC(zP+Egaygw(s+G=9lJZDW#H32yZX{=>9ko0|0Blv#u8zQsf+ZP{=WO zp+T%?s4RN$2B{kdO@O3LYKbW}!m3qRO^K??o7LgN_mxF{VwUA8!_O~x%9uku`P+%Z z86m?u!<|(Ka(%^&MRaoml=~=iLJ!`8o*;OBn)ilajRUOSmRa{NORk_BeuM9D#f;lJ zx)Zlv(g8IQB4IMFCRUL(-!D3~)n>KyYd#Ciwxe7L0&64jQO=!d%r&yOttSGrDnCdzXw>cNle(TM zN0e3ckPOyjG2_O!Lg-taQfcmpYJN+Q28M3u}nz;YUuo14@C9WYN(yp zjzQ!Es&NPsF?Bmq;4CFKQRjzyQH(=(NL>}daN&2r2%N$D0HJb4!Pv;yl(~`PNu7Ak zSr(ov;rBFxYo*ro!WJ7*GN0)=(t8&g6NaCtY_Y9SG;^IUp|YeLe|t5)*jQzNAspoL z93~7Zup9{p5Po8gGMNnO-YmuI3EL`oTeiLAZ3~7+rvCns@|MY7|wT zK~>MGUNW*|XiQ3UAr|j4b_qPg+iY098}L#}i5ICunB~*ep>r%1KJQrO`h5}CtGuSw zP+ML;4ztU|M{q*hJryJ~SWy;T)qyNjC3*0iw^HKdE5+MC^}@Wr;thq##^lXou%^f6 zTgKgrsHNpFOfws1OCnRWTgf#7e@@X-obKw7IMlu#?mqt?2v}|f*krx50u<5$w6lb& z2cl9c44DAg$+Fw*+jcr$5s;5-+<#Ss9M#}b#GG@jzm z@E8Yv!&tlPBW`M7Dfk(m!Yrw6x#)-JtBpjM94K&4LFmfR9|1Iy&Xz;gQBwc>&PN`4RaI;m5gD=coud>xhc(de z1{N3fg^n7sN0FnE?)qLx*AGfFhk1BJ3O+5YFd_uYqonTef-N zsVrvg?j%W#|7e`LD*5JtyVUe@5V>2Scf<3JPU-g}2UOVP+1d_||4Puf;OYi{sYn<> z{wto%WTS8s9lO03p+;C%Y&Y6x&3q*S^2-ISzA{ z0}dTalwzg+^WXjr8nW~McL5{(@3V=E|H786{F?&C%_Gnx^P=ICnb0KP(wv?!gB5za zGlgeMQTE-AYD+GU5lCdp!wS^{|F`!AQ#daN2wgZniM6-5{?K-^*JI5)=4CDY`QJYN z4V6%rL0#d0sRKQ&dVgpta#tvpF_GOh>rq3&p!J= zS6-;`U6jCR^!L}MuN>yN&l?B?BTd`KE`Z%b#dZP{Ibci0U^xw_Q*zziK}ylsoI-O{ zY#FlOsgjjXHNRw2S<6kz^RzH?R^Fv}`D8a%K}ybWZsHoBU9i-Fdrs3P2#IZv;Bpo3 zzuo>THM>R-YQgzzWg5Xi4lpPHjf}5d5>;A|~6Al#LHeZ+b{d}odOb0^Nk8m`J94xyZ;DdXv z;4}6-UP#7Wbi5+sxW{kqJIPJb-6(INSetua;7(oE2d%z=CpD$R;(c*rLGyXc$g7&-NpLEOv;nIH)>SA3xt~>q(*u!Qh7ym-DDkLcTyp!~PtJuy z;p}ute&1x+D1)6Vdnr<$BRo157Z^=a+osSyKE=ao5n@Bhe!?YAJrn52x(k87d_^y~ zx-#J0R%Pj{j6_Z^5M%cl4Du}2#TT;lc&5`n#CgwcH-Bh>aTm)aKK_*2ow}u})@&ek zMa_0S_6DgU+)PS#v$;l10`AehtOi5hcW&mENgRk&j>n`Ik>;%}B}1*zpQvE)4+$9E zDQV{@;P_-%Z#ODlZ(U*RvGvogKK?#skg!f5XT4qrL3!B-UQk1n^&590GmQ(_)*C<^ z1<1%3z+Jd>rhNg~1d@bjYnKodtoIEA{Uvy?Xu2K|EADt^7^4m{T=Y)vD z)Feh4Dsog|&~`SFup^JiIV35HzT-(Y?Io+8E|>Am)%MBbBbFvMb^jBZkWa$-4D#Ra z`wmDlzh;d9pNJa)R-__T3QNigehw&&+fKh&9n5-I4m~FcXf-!IuPva@)OVd)B&=Ka zf66vY9rcLLB5jbUXP~!xte`xNURQQ2k39?;^CUEGu!`549Ae}66^0C_din~ddJ=>7 zLSq$xV@vq6ZxdBKK0lt9ne6l4N4xNh1s(4u0u&RBQZ=S_S9DW$Z#4;hf7as z(;=K(9nQOE6j}n(zF>d@ASmFNghH~x>z73VO2CT0uMhoT6vkH?tMiA?FwQ5j=AEbm zS5&l?Zy~V`lpM21JlicwAxz?F++f~XD*}z2ZDv@CyR0v@wwE1jcVV zaOk#gswIbD;5R%}hO_xBGc>X$Z7HPpw_WCA>t1D>*g*y=9fNJyZ7oJ}d$#e?j~2u3 zL{Esv!A_mAoY0l)iMuk_oFWW-Ips#~oPpXdE=ZBD044%Fx^38Wv@96;uvtyU=dl++ zV~_eJ!G}*qg@5pF)8zrX=M=WcWcaYglVEHZAaITRE>%^ZqjrkIZ9+$^Nomgd%YyHk z0co~dE&&n7odT!E!3DBO07I=I?6-QiFNBL#IP+c}L)cl;;G%lPy7|Rq-D;Eba0cG0 zf*pj+IXkxwOU7yoG=qD|#2dS0LehVFUB8K@cFHXpj0V$XWE>L}zZcYL@5^w>J z4}Cb}L80(ulQ>ELh0m*Q!ec=uI)3@)x2~Y;NqU`5qKhxb0ovkWGvfLMLli5Crwldm z1R>A4-&b3|WK97V4uA(O1yr!Gvg>s`;C7z~V+l09_ZXkY7SIS-=0pwBe9X5c>&~Qw z5g$%7uZKO9`+)W;-wNA2!w#4FOE%05uf8<+M`)!9zsAq3jbP)Iu?^^_Iv+tPFRGmG8TcPjd%rccdxWDQMc}Og+Ai`3Xw}TheQ*;QA!sLitH$Cas8I&rU9^mXU2vO7jpPm= zu7(?Y-aTACZDJreU!uj0l~`3(`8?)5vfEhABI+>FuwiA^;`sm;kXxa_is4L! z&tMQR`3ce`z6wW>SfN3RZdLiti|*fyFkTX_K>OC$w4Ys^mtNrBEeg!-udbMwKuJV_ z#vOB-Oe6TzrShK=A~inbe4XEYcKXTUeTifIv;k<}fva*FiWCNX++#dYhL4e{U;b^Y z!CYujy#G3|e)s*h19}-!Iq%a7sX|+~m3LiM8q3d=`PUmf^z9v7ev7-t&saJIN6rfB zI4@vc-aFW$>emQ8g2!MQTreCZq%hQu%>M5n2%EqX_L8!o#dlG$IHa>6dN|BAh?s@| zMc;V-=;tFGQ`Y_WwijVW-*)H1yIiMAhX%Y@Dj5myYZMmE-*tMbx~3+e!3(&e-_JEv#)!H*skmW5?bW(of>xrsGcVO0hP8690>C za_6B33F;kyQ3Ua*GsJZ00i>W?y0WZg?k!P|I-jXN}c$sInDdoGdd3N?Z90(C`mU1`;bqPPw20&XB8Kl1Br--BchUgZNdffr1WN!5OA|{T-UpQqDjlCe zr6UL%0zm@3QBZU~64emOgR-0MkBR@!-~G=izH#C0!5lyOcQ>KL3FsGvv%a!SpUT$F z90*n9QDwZ_l|Wlr3zCAlb03}`x;6@Jy}-cOIy$`itn$X^=YwBw<`+BD;yaoPA8&Nb zI&|ln2bbLZ0Ff~ld_v$?+#C4ESad%iqSAnJzL0hhQl#K$f;jzQf&FBDmmCRI9GcRZ zTuWOZ?R;(^$yJRu7uau`wYV%(J}-&;m2#HNfo{$u)RO-HkoJ{fRW)tf8`vNnQX&l^ zAuS*s(k(3l($dmONl14{Bb`zr(%s!9-Ccsx`OQY}`+2|Peg8dwjQwNQtXVVHTydV~ z1^wby_MfT$>(3*n{#!bMn}BmfhJgR$ajgE2y3M^*qCYt)PWwTQxAh{ic?1o@SrGK# z@Q5s9V%rS_7nw`K)c6EcM3v1HtQn>crbzEHBB+zu)~{pUc}}AVL*rl0HfpWITnAtV zkV1gj1%_ZE7#IT31t9?7IB3C@e)kMS?%$BaiJ8X(a(j^D{#qgq*N)vfg?B2Ii&YJ| zw4ynT>~$Yn*m!=4uP{mcn%_6tQ-wUkjA++Cv%4Srs$>ioW(@GJkcIJ~a97Z@FrfM& ztn_Q1|L04o$VH!Uq9qduKBFe0o_gWZHU4vq!%s1eM1^%4|6u)wU>|H8FQisL6PzSSk;uN;ko z{&X#YJM%akf=r0sgB)r^r~v}C6!_;~Jr4|SS%R5GZ4I+r&^l6zl45$^h?_FBR9% z_tnrdJSlw=$3UuXXG5d7FU8&5U+TB~?w`hZRG7uw0fqoliwdCWv7=y`$uQY%n*+Om z@r1Tu8$-vyNMwXL-+TH<3?^1(=G|hnTZo&FKgUo!2!r$@FNCalzS^HnTS}m}=V|q` zCRV;p91G9jaR7A->|2l-$_k_(KM=G_bh=nOy5`xt!t0_B1^s&(v~PK1+BbC!bgAz9*4L{=d**1kPUc$PXT#| zGcb}cT8abfsIn!Ntz~z=`;@K>A63unrgc^9zSC@1VhW>aUw+Xqx;3LCoOe!9C=b*J zGU+@7E#HJ^F6UIMEq2}b58my0E*2^#0#bd^R6vG51m$J94~H-!G&vW|B4sMhVk9?!1@OSi_nQ#PCN`b{J}DQ zE+LA`rv$|LXoMtk%2*%n9@);mjWtS% z(SLM5S=gN?WaU$A_$$uDDUsI&AEn&+yNjRQ`Fg>HAjjHp4y%8ExG2UBqWwLFUGY*Y zu1+3188gQ_)FE9^2Zwt>AlV>I#po-=&v>qxn;#M-UlF@b&Q}7x!*j$WmlUesQy^0T z;p7$wX7^|4{sk;!>vg}k@h!AA2@ns_gG-*alDOqL+B^_)GP zVXB6xc(3{=&2vsUuF18p@bBW-4z=oVjQT038pSPsy2Wl0jw)QlcDw>5 zwb?Y7LW3XXbt3<2$nU$p-TXCzOfXOSd3J2x;4DxasfR+*7pyK~?VZ zg@?(*QYKcJgS<&zmt<-^!kx(*ENhXp^Ve;o>EGYWlL{s}ggGX~$ivT(#y6e$cDu8smw-xGZmeW??uIW%etU zeNp2i`qdSXu9Tjo3E*Nha8Pe?P>(!FL~I6;a=`B`cVYpN{RV-U*b1^CZRfPi32Ezf zp-A(X*Q{mgGgB7++Ua^l+g@!P#NVNbV_j^gCXL z>?Af05hTsx{)8`!AN3d;R|b9Ti&gox9zv|S9FF#8N2JcxesDm+9^D;{j8<~tM}78) z;>U5o3EYBE2dcnq4hS$IRbD20qY#QevxN&+=ILTZt7o!&-v2IavBh#xx0&69WU1?# zgUfH+@S2um!MqR7)H%8EW~#xo`qwp;=j-v1MHCXXEX0-)3{GIvV9jW509F$gvjAp2 zbUqmLy4n7_7!k4vF-`?#2T=vzUIz>_8VQi zR@3<46W&p3en8!_cv5uH{dZx z9>YIPMxpLC{zQ;TPkT=2;$Ba^6B z-Dg&N$NA@4At#@T-X#*Vef}57&ucQw7wzm{UougC&AFs!WFkB9#ZrCjy#;@wmjzRN zfK&qch`#=9&?$$8uZv~x{#&wcs?V-U4nqE7U7lB;P042{pF9##_crn5l;Bv5Cdf=Y z3}I~YM&2s45PehsMJEwWI;YT|p%`|~6N^BmaR4+Kg2f8OYu|qxxA;4g8ViUCN;S|V z4n#S}6g(P+{}gaoZDHz~T=Qa73YBwxIb!!}T1CWeN^5Y0YsK^=3o8qbq^KSbD`rbaU< z5O*y5Hv9cnk51Tp!OJ+X3PxM*X9!x2dIOve?kD1C{WIrraTWNhTMXh)9hd8 zvp(f_7nk|a8$NU65O_z^maWX|1>23pt(C{bZcAo36kir%WK7o!Utl2Uus)&dWrt4} zr+S-pb^bY`g4a;z^Pd1mZXV>WH$BB+%{`if;wo@YXMQt%+vaAovz%bk>&iVo5d4Hp{~0$thl(Y2C3?N;+4rx0EkBs+QzQ6C_|B{^eEtTb6L1yNhWSJ;5#Ym)srs=chjiF2t@k=oH(* zQ<;20Wbd;L-73*SU*!9Wr$)^2tH>FluAxaPP&j?$rsTVVN-vuE zSFJ~jDwgMU!5NZ1LC%^>f$eMjeBepM-+4KG**C36O;=M|)-)BfT9~g}?u8?2VBI*4@qYHpdP3X3 z#m)Ybw!bCY(bX|ymx6wuCV)m6r9}w7tCK%zD(t~%ECB3v|b#PF8GLEoA-RdtciB@GV^1K)o83%%HPaogkJu@P6;Nc@Dymp`k>`SF4v&y@73*y zh|Oy@+rJlub*wpFZ=**3fd38l`XS>W7!A^h(gHaHGkXm;@#5k%V;&=uT(REp;@V!) za)0j2GsMmIx`bREY_cBacP}$(2B&`LKEB4V+Rm3~tY&3o5Fy8T8Vi*|;_R zi&q-wkIeKm>5p=HLi^I)b9@P=7`)EJ`!_Z%uhPnqcr~q!K{7et z>-bu%O99R<*z$rNZh&FM1O}UW|F$CtdBWCO^c{DFquz(k3sy#NJsnmOf5HJjUi;co zt{4`QS^WS#@>Uj#H_0O6-TL_}s`)s0o)1w{YT-eABMo(_qTz%>r^*oS%r4UaFRpS==tEI>8XwjjlhOt#NkqoO}^6Tpi5~CROm{ZK0 zR+E=-{3K@OhlI2XN6L!Flg6MKl_gsfbPWY@7jlKN3+|fT>wxU%2pIcI=+P?XtnFS= z?P|!sJ*36^Ex6Jo3La!m4s#?Jek2GZ;0*EEqm_f7#@=nEm&f|_D&Ig_vD=hz3meLDi%xo)Z4=z8(zEt*G7VQBFgU&Dx1MERSj9I)JYs)FlMFo&jLpXM->rWhK1 z66ks$cr3U)u4|A^Fz{IF9=fKeJ5xdS5nGspJ-bF@|IE)}oITMZ`5}+`3pQE~J}g=YgPqEA?=*`i&*CRkb!mS1YIm^2@bvtO;pH=Z z_*rkWs-{F(j8<`ZHO$+${?B5f~;e%SO~cZ=M;w*i-ixr7jPF!rpsdR|obsZYSba_Xb3 z-k$WskJ2pVr?A1~alzD1?xf~!ou7w5-(usgU0EzSu;R>}k40O~Y2|1vxX%K=Zc}AM9o_;r)uq z5|3MvP+)Ldkf2vehz8KS6qMEjK}`EJIX6_U7Z~9pZ!Y4IA$yKjvEf}Fh-HBSCDil0 z9wGiLoUC8uBr-m2lN(%EjNZJpruGYvA==Y)<*c1ol4*rNM!Q>piY8b)IP5If%sS9+ zLokBbKz{nDzgD8zGHnS>=02a%yJGl<8ME#EwN2F2}9}8xp<) z8r`D|n#eKg(4H?e>#!t$1n`z);T(%nA>AmrhoI1d-|OO6j`x1C1T&GZ{vm3ejaAO$ z2tBN)r7mlEs9ECVUnu7<{P@@qmI9YgZGJT5z^BQL_4JKg=R8N;l+KuhrAlpD0oXA9 zp%uV_5Cwm7>;H!KQnfl-%2CW*Lhw-K{vw88**?Q*Ti`au?RZ- zn?`x3ZHpr}Q8}*SjMs=@U#1JDO>p4}t9etlLPw|yrZL*=6}eN67blk;_b8Vc!2~}f zV1M$}8x6njA(B;12A^wDE#kcD86o&o>P8V~gFwdN<{O*wH`r(ypbUea2C6V$oDYPD zA9JBXJv$o$bCaIS3=LOxYz=hzTIyX!O?dxc$eU7sYwwmB%$QWF$uTG6XPjf5Md**d zp_0n$RKmV1B`z<`EAapk+V@7>23nDY(hgYrp9LCU54yF!I}>zVd{R}ORakwX#?Dz8 z!A^-C|B27Gt}kv)U}5)t_*$b3-fo%eH>7;&K@m?~#IP)EQJZv_U+l&P-nIb%ih-BJ zYCZ7Lx%?WV*&ll!?>*>&7eg2$VvxlQfA})?>sybL%jEL2n-=|zcHEG)@6Qel_7l)t zbtKQ4k@^HsRwyAbDGD3tL@~`{b{lv|ANbI#IyR8;zfsGxi|ya@?aZ(A1ytyKXuR76 zikt}wI7;V56~Ye0E8&OcF)B)y)3Sd1L((M`I5K!B_ST*X*6gHcz4eX6)B^HX&ub8% z!B-%HI|_hBa6I2M7FDbfKD2nypVeTD$vJ0~kFzq*DDLWvFe&!+g<25Qpt4*Dd{4oo zp*SdJk~+z~HT>2U?_@}6#{6`aA4u|TL0P;0q>T{3T=zxRtTZ7ke`hNwjkD3_Kcd=L zg2&1>lgTDD-y%q!`u;?xX8q-B)GRrXA&oEBh|elXpKgBowxjdhnw^jo+k0b4U6Eek z6*A0i2K$m#ie?1bmUJhZA(Wz}q~mn_!PT}=P3T_u7^0UC(woX+>M3(vuh%G#8&`aD z*b|PgalG3vO%hpa2Rj29_aldw-5Sz)Ex5kS@PhVTmSh;nP%-=x&t#`1o(4H#{h5J;-4Mrqnh|I8F zh&G~PL0du84MU$2st(R)=NRNj zpR0Sxifi<`wBp=jiX#fvku}c7>po2=z+E^V^WT<)WN8>2hsLS6rZl2N7(4(fqUQwMDb zp|3j-mfKSreq=`4&HmkPa$wO8;Zdr72MgyTDp@k=Z>O>pkgZ!d+$vGzmz^5Q54BMH zb~MjviHyUTEnOmJPOz-9z*Ykb<7{#loP>cQ#XVFAL<|!Gf=Wij1-8UC*y z^}pyP?@jK?BB0gSzrl&qpP&8)CoclusI`6C+?1R6aD8^1R2INDr8jt=GgyXMnJn{- zvyZ;y%WHe<5zQg;dY`rL^E_lU%=ae;AD#jL=xy7aqV}(i4u-e ztplQY#V?05>n^N23p@PnGf;fT%tT7j8SWxdlGkwlj!)Y%s`B8eeNZcJQC%7 zObkIfb-2X;;k2LqMu2Pi!>eH{fd2dq5MLSo?VJUW!@u@QN9+3xBHNfYb6B8bppZxs z`kM#r9_`zrFU{(1qKJMSYRdTKgfLGA%v&Q*vgJ#AuTae{aF7^wn-^Xbr383^H31MM z-U|>h*8qAc@LLVIV~EKP>m&K#y^%#-Rc~z~!=fLsI~Zm7#Q);G~Yl0e+?IOau2( zpVE`;M@t^6b|c5LOAG-Vdy4CI_MJ7y7H-}p+SYocW-D(_G~GIln@;Eq=TC#M{unFc zdv}PhJL$%OV1TAE`uqNGX=`n}CPr;Vjt!G3&~Erd>9xBQ815w_zn3FQ$~ca4JSHqC zLN#{aGxs;{w)-^sI4EuH#b|jwe{*5;efy3-?_ZS$Y-`;eOUEHF?{bFVrN@BwHiCC% z>86{?5ZPS4EJJX5*;h_};<*^5vp|`_v>!J4xw~IhIF??q%5YjJwBThpoM1iToB(O` zEvV}BpW8(g1rNIvhQkPa{s%zwNBUjyuk^dq2-{`AHTSxn0p}rVNfNRM>;6_(fYadC z3ke00qNE2a-?^sCvN_)Hc}zB_1f+4`PJqvMOIt|C2oAnS@%fpNe=-> zs6W|;OZMDSy8O;lYF-Iyc&H2#_!A-quEjzfYKZjTMfS`X`O#{!psdVK_VZ_;XK7G( zRbGmeIw9Fqx6;#5k>vX2jCxV)uIb*cQ-|@$Zd*1MJM~7{cVm$d63iq?#1XT_dU2 zk~7$1`^EjeoCJOQ=bN6@{R6FccfvscjWjzIJY*l(>D}YD7&XYxzw`CR-M2quS=kGn znUqgQ?UFd~u-!JkGNi5TemlyBT3A^{i);FbvuE8zA|vkfH=(`Q`&6W$2RCDGJp7{h zJTL<2CIm9c1wlFx43aD@ruyt)y~P=d)Zf;h-gune_gu4XC3Hnz;!T#Y1NBm^1Iysv zJ@Z{*!A~SaoXQ2$AFA|k3UYFp!b$D`N1)zb?V4==5-Cgt)I=h5rx$lcm=z1nT_F=oR3$HSCjc10|o z)A4f3fY4AP0UWUups5eOe0X=HYUgSVeW0PuJ5{kAwyo3Vhddrb85^Bo(K|GwqKMn+ zR4)n;s>^&64;0)AYt_W9OHZ^4HzfX7*}Wl7tgZ+bFLLI_qh>W3s1#X7Kx8aoPwzV*D6P0fL1&V3E{Mx-lfMCp9-r+QJMdi=V>jv~dt1?4&uDtkzp=6P{ zC9!B>*PE;$9(38HVSGFKxRm_)r|7a59WOKxFF)6nI%g}&nxgHXtn&iY0o1+^Ko>9{Q+ksSK#ovl>ri>_7K@K##GMgF7F~C&y4N-c5B|4bN)i*AyxGqtm=cN+e z;KJhZ8)0z_IP6m4f6CE+pgc8ya_ihIjgxtgn?3E-RV3ELrY4^=?t1Xds|Z&7kNjXs?Z(0r0UCzq16mV+o~HTS5w0!Q7f+aXxu zsqQyajZd+Ovo*PX267BFn=wD0LN3=<$NbAnnZrl}9Ic=cR{%GC6wr=2fC4sQ-7JmM zm9+!Gif8^e4nx$}X+1A`IU|flr!;=~O3Ew}(LKz)R8gSum(x8^714Tjlj1%2RH*Cz z6#Fh5Qn7^;uY?yov^yW{K`(e1ffSl`uIUBoBE{X3KM-tEe>NOtlPa&NRn?JO)Y$sC zzP-j-y1Z}T{!~gI!Leb~?2qu~O*12!9~Z(2n#Nvv38(CplD}W9=%;qAMg_{$K%ui8 zh{2GFZdht&V89J4&3-ft>OD+UDELa~cUIt21^T{5ghYgn;9AL_d&+ za>=2LczCN%r)AtHsTX|K;ZPEJ@pl1v0-vni2qaTz-C*~bkp0b?N0^GxU|B)|7UU51i&)z#&*zojKXmM_P4nQF^}-4B zo$=?xe#8h|=*QY|NBbXGNke6*;7Djm?)TNk37Jn8t5fdhey{MlZ>TECV==`EiI% zkf1L!2cn2G?Yb$B!;%WQoBEx6nu!sGcAw&l$>6U zrk*O^W*H@eAYjH0^~tgs^$S4e1$s|2Xq+D*8T21Pm8%(K8m<#p)LcK>_JhtHLv;~c(cvRxYc8!QrC#DSwT!WWfX`^)Ev_Z z#fV01hLO{N$UFq-jf3{5xRCijM+tE$D9N5*i=(JR)9~V@KvfNTaOlf+qZeYz*iR5m z80sE)7|C}~DObMS5Bf%HM;&P;ZW7t>!QI4JYW_owjF~pCQKS$EY8-HBzCbTR#m&KP zKX}juBQ7Vcm@9oZUjQ|-h4SfH(rdl5N$LB zg}hwrdWd=C?e2XgYEjHl?zYi*>i1iX^xwzbD!LxvrJaW1Gzrz0wg|?{siaPJS@22( z0*S6u2|GCG?Fl&gM+`+6U_odRaUqZ;xdY)5Xwob7!=F?9vnY^uIUf6bg0XMfPkj%1 zfaQIqH3*@L-6-@v@$Qn%?nm;8&1k#q{bug`T%O-Dtc|wI#q%*QQ2vI7eM5YY2zQ6~ zg4IRB0p4ryAH3K7gKmn^f5MOd`f2~WHsb&7t~L?|!+ZU$jfDRB=}-6pN24s6lGtf| zfHIwM-si&j#)j!Ie4g8{WdHs&_3g9g^xy5Ks$QqJNW4>&!${hH$Z&tdwc$!z(y((d zfUjV*5Sah}!EW!!`xl~x69BOU{zk|-jNRV;_a=CJ?=+o|;F>*a`}9 z8H*eu8}K|{KN8z?jvp{cns#@@G*fPQR;8LBHt$hT{|vg_yDk*@{3`H|rC!^G-2{MI zi9G4s4hCQSd;QYY&}2o57|9IbudP*$eXts<`H>T*zy*)wm=N%yT0hA0c_V+dFzAx( zNgtE){av^=oO$i1bJMMc7a~Zr+#n-y2gt$}gHmFnHza~c3V8YSV>P^2)N0?5q7uWo z@-AvD#@Dsw1*qym|bKvrJ687T1_vyB8k` z@^Rl?A|{-_aFO6K-GS>nOEy}^EmY_k`R22uG)kbW3Y#wgcX0uC=_VFLB+`g1#p4+& z1Nho}{8CCQo2zjTpL*JU^g9*0KJ1>T=&fyT_@w1d5?LN4=fbzuM$gf*@pg85obUJ= zMR&l+dc^rZQ5Eo-cz~ymTy@q)3Hll#vPQok{9x2oF!DViTBT9xk2^?N+q<_}4CTC5IgeFm12#1uD8E5@ah zQ+J-xSgMeYVmTg0nCXVHTN1u7rvdafc%GwcUH+hgL8gH~b|J%W`+M@5Ad>ZbT>Yt9178LBZ@PM32U z#QLSTu*qrHeU2WA_|o-Vkrk;$q^%z%iKS?6NvpzsxcBjdWQIo!b66BYNlD5lKP+0~ zPVc1U2fkX|g^z|Ur*VvgA5p_bn-l?~9VFbbvvnW-vOgDq^OKucn}#qrrSZEqjrN5E z1{6M&@54VST8>C*4p<%%{QUWyJvUm1@Dq*>iV69EUJ7*FeYVXe;6VW1DX|o|P0-;X zgy6%pB~=?i9)b@8E`PW*-Pc{tIJ4-@Z8nT`?Sw<@>-7VJ+mx@i=S1ee9&C7UaLp;8 zzyFZV%E|R&t8lZAl3rh_IXzXiMfo$YhBeWq+9zl;AB@TasG?BMcp$t4>qQAe1{xFA zXA2o7#u}j2C>!5s`I(~*kSkd%ectLpVFiu7DF)h&yR=m!E~ZX#!lFb^N&L|cBL=?i zn*Y{a#PXeQx;vU&)}U>yCHU%oIW#ta&0|`ul6f3tKV#HkQpqD9lLf7_0U*n=T*P*8?Yk(akOZAdH0a+z6jr?lF-G>dcRm>aX(?Bm zPvd3%Rn1c_yT-kBig-Kl!=0xxWA3O7vfD57&uzYD1`P?1^GX2f(s7RXDLdz%MEP0z z49Va7>*((>@;XRB|77hRGS}g9ZM8OgQ!h>{5tq=o%eU9%P;sBCC)c{YSmQgfWut97 zA=XO;A|sl~Vzi>KaP%xcP_>ocfMW!D8$2-p_A@N=E~DdLZ%+D+Pgx>llj`_%u2Tw) ztQlHL=y%`0c4q%ZAKe6l|2wz2(=fgC)E=7y(TLX$GM7;HU{fBgjSp zu`Bd6m!=Wo!_bEULH!prpPsM3MAA8dUio``hT9h7)z8-HEKZeNXFcJ5vu*Et_EiYKvnS!SVsfAGDK3|V zH|XCK$CEE|WEDPoeXL*4RXkrTZkWM~-D84%$PJ zK0!&0>b#BnpH9#Tw!<~?U8a}E{C$!IXqYGQGc-6DoqK#$CUk>VF@}2P!xg$Ky57SK z6S5lk*3qe3r$DpVrOR7)ApB>4@{+5AkNB%#lCL$kQSyeP2q<}>VoTXjZ&rF5Ikse( zF{^fL->jCYwVne zNEvT<=$9eTf8`ee7)=$6>yTYSQ}%-OY zJ$_pLN{0C}e*%SmjC_doc!)yV%X@6$Uu?`>0_`3-z?;dr;8)N~xtzqn~E&(PJbVUc6A}}%%L>SyCH9n7RkpJ-_;5rW^$nkIY9&Ky>Fe?1M8l{ji zm%{JMt6n1q_}wJ7G(Q^kTq=R1*db!srxBQH zWu-iMR|i;huyS6=I6ySi!0=8RCt-9GoJPVw^UWWbQb2~|p2LUi?P%I|IsPQrNmkt3 z&l|CRwEQqQ;u$t`FOY{j6lf#bo~UC?>vvkF9SmMtn`;O+3q-i?0gf&wXKqB8(XaN6IDh z&S?p`-|Vn^VFRFQpnWIeFcWivu)R}K(p0!+{xXq_#@s;Kg}CR(j6%0>e?D?DhEc47 zsN4f4Xn_LR`0`sFMQcVABKMLClQXxmlVQ8m3VB`$aB0;8zy&PhTn*L|sDy#4R^49< zd#2^%vN9)Ltk7{P`Qumrs_-I{lLm4g$&fjFSkCKCnZcC=HjbQzS5W!yLnL~u-?gkN zeIgoCN09yf~4RX#SS4>6Arm;~6y^=X~V-MGGLw+-M zVaC^*C~HLj#^~_jP3kc5Q=XY>*KQv?zRA4#X$*ffM~zUZ-3_P3%*^?dM_w%s+8Ykz zyOjW=m_w-#62iV2kRI5i0hVVJzh;$tCy7eOL#&cpj_;<5(rr{)63yzTTeY?0Jv6)g zUNJr0J?Cf6%ww6yd#~}HG7G<1*pw=K=xLAFkA9Dpm($S^9qOEh7znL7qn|hsB*0qh z!~9HPYWwL2XSKRV2%;9l1|Frt8IhOv;T!I%X!#tk$+!+i(l}z$o*1&v^Pi{{bwroh z^c%{_nEUZ=Wws$uc5WI4_6ax$E3mW0aXb_MkfGtoQbns8R{6MY8KiwOy(r;XA6(lL5Oozoi)!;gTxv zQ`1Q$d+H=wqExpTQwh%!F>yV91Ic@fXy?{5x;-IuIFVDj!hD0BythVKmmf5?bI_*z z=VX1m2WZyta><8~95CIHV4_V(5y%jZfeayR%BSs5*GpeS=1CV(*=(xfFFf)dR~)Rc zxo)>8IS&slfp3O)vQY?Zwef$Wd`0-`V;iF`Ge4oW-=kYm2Evv(81V7_f%r=xbl@8f zP6yMyvWw>DXHHB()hbSI$TvZy&lE{YR~-x>Gh>4vI+!`V;u`fi=z@mc;_DJ@QI?=) z99KP~ki8gkslMF{cH~v7<{W||Gb3&S6)aX{$mkvB0qEWxF@bJ06VU+la0BK(`FHMe z?UM_+EwQe-)lVW6D&ppllSn*8F_B2*8s}YxeYV9@5M_uF{^lg`81{Z$rP48VlTU83{ zZX{sx&s9swMVI`l2W`sFSFkmcyAo@+Ykj~#X6$}uY1w%9zn&LFZffv9>;v~km{v04QvN*M&YxW?vDa%^}@*If!SoGPrGTY1dp%s^NokNT& zkjw?#-liR;bHnEH;SG^Bx8(WF?DHD$hFKA&eq3r(IxRW?XYf90PN zfljAFMkPBG4VBa^ znDDaJ_uE*G!=qO)?W8v2=a@4vurGN3iPff7!>)Y7;IeF_E$elN*L|dvz3uW#w>Up_ zaN?u^IV5iocH)394PC!}JdX^?1^Zz0ZyO+0u)BZ{n_e(Ea}`kM>eMEh=C%%=pS5G`DS>A4{VjmBy5ony2ZKu8&2by% z2UsUJnQ2M8<46s%utME|d&c<|HjnwFs^gW;(`z|XFs{E6--ITl`yyfn6UWkt)x%Fz zPx39Aw+ee>acbo0%ewmVO6(&*BLLRIYX2YHjtju;6kqXh{;RYpEB655oyf0;oR6Z! zHdrCVf74HpYCmw#=J^mSx(ga^L0MWg+wH0;7DzB zK+h@yVy9UWlmR8&u9dmVNO^mh_}ZDxTu?Iy;1^_o^9#9Jn!Pg(Qo(QS`1=?41>3Iu z6FW)K&*HpF=b0#dGG-Xt@5g&&i{3krQCU!BQxtd}vRO*8H9m+q@=Tadi|6gwxXCD} zoj@81=use(nDi)j;o}Q#|45f>$<@o4a{Tu6s=+5Xq5<|Py#dN9m(2`PxYaeWCq)(_ z?|PAZp30RN$P7T}R9@4`jq7Gy-_#%;!J70^!9i;Z012z~Tw3EmP;Gj8JItQr%S!G& z%<}$@yv%mIV3q5$LHm1J=~7TDkz+3XG5DKz;(bq)+_2wF(D^5~N1HC6+VLLU#FI3C zBWiIJhTb0lS8*2t1OuGdF3LEF5`jMo1n2Lu)zmFT779oii#)1eKChJ^^@CINb57Hdn>1qKW@n&(s@(YzZ~M5T|DNe7S!hXea`I?7)6;PZ;Ns!CRyr`)PmUfGI>r zo3ttJg#OhD%DPkykN#&HEnMaCifZEsICl3gG5eOW9E(UCyC) z@*p~r8On?iWol)DPO8TL;l0zc-h~GdF?ZnsoHfd&n6U3M_p@^pS$Cu%#3kW(ymi+8 zwm5SxPyO;VktD>HcxE%S1E$Xyu$Fgc!|KI)IKM{3co*1etX^b+YCed05cOIAb&7GM zpb$7XbXdc897k9mGS-$P@T9*Y$dMC&L46HVM-q@kvod%I9d-tUjfQ{JezLHX{CsSZ@D z4@|l2`mSY(w?4^wU5Xl_n0M>h?Xe1{{udQ#Hplz>3x*$9d?T0a1NPo>Z9Rx2O!j?L z@C`MY$s8xuld~?yA^ICRLxyuc4Dh_Z2lgnKF3{$IZu|0#K-T`w*2e;!R@3gv^)fn* zk&LmBP{^M-;%)9O8;vR1k`=in!|Nq}w6`4XP48dn=4Gsxq>6IBHe_F%XCunn3h*b9 z{jxECQqqQ>p_L@J zYlJm^LuTiN!s$W#;>16JGEPX$m!6dRb-6alHu~3&2rrt=?m7&k=HKI za=F_sSbkd^-}^1!9jKuF7zG)(==oEx1%|2L6@_fd7D=x%-p3L?bMJ-!&cR5w_t@`63+xYy64tN76ap3R`q?@qlN9m~AyT$I5~ zZ_AHNjEJu>L<&}&zEMDD`@oGU-)tg4@{zbw^S9?LFMhk@OXzwp`1aQDka1w53q@8# zMgFZ2#_dz_|2ApBp`>mjjK&LGq!?Tj+xg<<-~CgGiZ^BmJ_{=$DclXfa3}Vbq|8gz zbU&*eyj3`8A66{lKXSMSK0YYC)RzPM+(apV=W!=gMT~P)tjop{frU zTT9OpL?DU4Stqp zbra~XY?>9c8YMj^M<}jDfWm^d<4JM;CVW7;JKV8rwtXn^ccV!ub=bC`fH|u=_c2`q z=qNY>dVM9qN}8|+(N(aHK>xJ(%ElvDX19KGukfpIVJ+6fvz<%JT2ELVNDBbU)RZQ35S||GJRG=R?QJPwN=*!S@3xullbj0cM$h0)=7V7V1F`=KLVFf9*qg-5Yn*YCN%f z{U^?3(}>TEy!q&CmxXGuH97fs&B#o%I~E?;aWWw-QCGA{DPCL&(dXG0Cy&bs$!0|x ziXwp*7z6t28v;Nfb|PL{{6MgZw4$5<%e6Vtp{oHK38`tPhkc)3r;lMi! zo3F)d-!r>UZ!)|ly$_YmG#)YaAPXxz_4~%CzfXb_XFb#=j-HeGB{JjRBM>t2yrG*Fo+9dwr0UHwI4RgbqNKx_6E9cU2#K(Ez%#RBIF6o< z&#yNzesaHvjIR#B4Pi8DNNzU`j79wc4F0Q`M_&A2j$4CAVQ@aW#lW{YA93BAPkB9j z`U}27*{7?*>IKJ!q_Q7Bc{D5?UA#|)4!lo)#qWNkkl+8K?<4hk@*66ZL|AkRMHU0S zLh7u_4+MK|-v4+Dq)%T&=kIN1mHb}ha&D3Gwx3@~7xHj@KKrq%k>2$|hd}7#TZb4< zRk}%rt;O&PeJmN~p}z6~L|r0%fGbfPl(2z=h=YkP*ZV^h{_ctiG@IMo4r}{;f)jsa zOE>F?MlKA8lGC1NUn6-5i^_Jn4WzyzIU>52if#nx)9C~wR8pbxsRd@w< zg$*3k76ow0!Qh~oBH%nec1MQjlH!`ZJP=$-QiQ%Hf@>#;-c$MH@lt&P%Q`>p z)Z zj-Ex|H>?%e=#85_Kg2xackJG9?hjrOZ4Qf36>AXxfKjj!b&o{5wzt~;=D3Bv_2Js5 z3(TBEUMzP;zkDu#Fk1lVV=sh>Up)p3QT3t!UrNUDb%s@g=LhO6dtGUtPG=dtr(A>C zpUe!Nd0=`(t)8!~X9sQ6+UdTU5SdLdY-YqwYMG!(lHu9oNv&+@RRTCT0D#zn(%aHF z0O<|mesE))I_3Qo_hQa>dzF$jqgE+6>N&S?B`Zm5Ha^|`C9r;YH~Fx^wbqzwv_`v@ zeo+4h=1s_C{D{V5=n4la3&gAYu%?!vKRkeLB7R3XURZ2?bV*N0vf2;5_K-qd)B<&oft)?<|$SsV}}Uka4Qk z|&Fwhlsd7QF`4f7M?@DwWzqOz!QKMpJ!T%ZXGp)YTTp8%5;;Sh)2Yz z1_8JX^t2Ty<}M>Zj=`JfTsr!XYGlo|e)#RaR5Ay<(+GbT`kd(xl$8rW#z&%o|BOk2E++yU_f?>z#Sf5G9{(V# zywU9+$Nm#8{P$1)|0)q^UWC?1j6 zaqp2kq0{*A{J9_L$6?mo-5J80``poC&+4sY8uk-A(1@&#!=9T0KN~#YuacI?@4MQ_ zjUS8`F3cT{?3PFqhuNG-0uUvLcn>l!V;pLpFR(Q7{h|r$k*(;R_IdW^gILDLLX`|7 zV|KI=sUFh`TaxAH-$P|}fzA|r3j|IdDg{_f$cdmYIZT|3Pijck3!V-=f}+|p&w%m3 zwwFyvGZ*f&I?^^p6HOcs`~M^DtD~yizG%;ZL#NUm($YvbNO!k@(n?5|NH<8AbV`FF zsYr{`DJ`jhv~<3G(0lLijrZpp>_)!g-}ws~eyAIayaLIMvk|Vp`ZvLm1CXW}KpHq3 zLi~jS&&^4Y-5x{TR@v{);*F?$lzMrOaEW6Zp$OmZ_>(4?%)Ls*J={DwKw<5y%HYI{0E^_bgv-OtBwXWj5d|DZ5*a2|rM z0jRkPA_2&2p+JEqO0&0}eTEJ>^mVm@#=V%h);d(`@oru%f~ox@BGgBp`7mr~=3DR| zIp{=O+gIInzDvN-EXwpF$v0P@0xnhJ9t}q{Kradw3fB>H{u^Ut8zM!ZelCvL)C+}X zqw0Yean$vn&iP()Ayak?ZW^7M>y0O0{W3v_e!n0r7R8!E=U!nkq09O8JNt7KO9&%4 zXwO0U9_~FI8z9pHpq=t*`c-C*^7zxTP^;h1`gLs@KOzhf;ZwhC{}wyJbJLwjE4E+Y ziRp*h|G?9$QO&FZ;YpeXdAxhkd!|>UKDt7(h6u3hL$D6dp^yV`#9G6^?zTO;oyw4D zl`Mx`{k4G8&}-|!imMG3Es<=VLm$LxXvScQ5RqrOF7| z=!3j%K|Y!ZOXs>6l%`IOA>FZ{NGHVG0W&#)+X`!ed+ZoGZO;QS{<|)^@gY*UpTk{Z zQapFmzv@2Lt_!1Q_=xeODM=a0aJ5sTm&~{$D8&56Z6i8UNPeM&PSM3efr0o1X|;}{ zLM)K9gj>Lwm%zRafu&i$vgO$mGvhCaXBVspl-!bdL^tbLO3&NztalN6$w(8u`5993 z1L997>@OtxkGyK*5!pFQU>8|7IgT((`FiYhev%$96t=|39 z80)Z3h=Zmh74BQJ{JuoSllPzXdYObbwR2nLhcPnn$*Rqbz$+|+zoGM*-VRb9bG;{K zN5?6^WNO8z7yG%f3(;wwK{e5S<&NafQ%sC2qSdPKgtClzU0mmm25VcEv~Ix$98_sD+1ud_<(Fub$($sK z(rJMG7)J7doGLT`nBvUo=TJU6ry0_KeFwiIvc1fZ$E*8&3x~Q>7wNms7=@hIPrPww zs%A_#oCM3M%QUQ#!11;qLEnrm?zo3SCY0<2V2U~LT!RcU!)fX+YQeUQJkB|vrP-VH zBhXVs=ELJ+yyPM#$BE3RS~aZ>k2%b(=5{#!&u2-wcSF9IHJ6)qqpzxk>yRWh`7zxl z${d;CacuzfNI-pPLJDnk8<@_Ty2BIb+wla$2!(mYLqBYpt8>_QY@x3hvncZ_zC>0U zClp#;Rq*l>1_d!lyW#h%Y(g79D!BI3V_5zQSWX~69SSyIb6yQw6(kdUdw6*Aw|k!@ z*m$T6Ujgsw8u+6@1){~tPdDkZTb;gXe9TFI1+Ub0R7gD0 zsfK5pUR>AO|NCnus)>jM9wC?}7a0=SIqgK)16q!`u7!&GX6Z*kMvP z7;r-h3K~e%3L?ZBoIX{eN`HEE;WJO8cQxuU^-+ITvg5txUh;bhLG7nH?MhB)k=UzmpXq(eORZIJzmsVJ_)f#% zR#X7L*YB=iG>Xk^`Sir@IzE;N_JG{R=jM2+H{=QSZiYLX$T{*( zqIX(J;t=YYd?ghIwjkgj{{;yo?XYepdRkadB0b#g{S_v38}@WByZSmnWB6DCx1(vr zZ{7cXf)aN-DuQ1+;3s3L^*%eK9Kw-2Y=<6wY(u~A!iEVLLqA#HY_$U$zjhsT*mgEx z?I-*(Azw8?him~k4#3;X#ow|DO6X*zq*ql|EWg;2|8gO`fVllFbAv6uiMb0~HFas4 zMIv9S!hwC#=qvj)R}4QRo6pS;quA~5E*aBsWzzEqq$t?&5p(69SbnRv50?79+3&RP z3tU*_?vZ{hpk39z>tLn%CZgfGR*qouvh&ju*<%c{f*t3_WNw$~z zK@}*oVAHF>!eefyJ&H98Xk^}c4UV77QLu-J%Tbid-`5eMrNDftu5~xlsLhlsZE+v1 z<%6SR7{2xdK`tLm44<|^hWF03e4nh}k`S+ojw3{aB^C2_FP5_X5I7C*qGa0*#fZs} zu+$-sHK_J~J!$!N3^7Z#kgzMC#t$FqJ1<9XEz`;KYGR*f&%VBEBz-jrEv=?^S8RvC zh*Ur;ATSF)NAZS1&2iIO0KaxX_rQ!$$+}4{^SeJbxS( z{{Z_&5Uq4BgS{}3>-~r|KUsFkAOXC|e*gh#&0@qYH?LCUC8hqBULQ)w#X?-qTd2N^ zxYqasuiW{Q5>D4-{h1E>FQL81(}RkD0cB+OjbUrej1BVsfH8Ssr+2gTfebvd9>OBMOU>8%>)VJ4u*eC{1c+){(RMukNG zy*oO5lnX;2$ZQEeUM|V{P2}`T(y(Xz2ld0OVml7ed;@InYHtq%_PNxHH=Mbu{*kIbA=zj}5BJ$!GTH+43v z79E2`zSWIbV*imDeH!ii^XdlhlI^?-5HmstOt{v(35axQ?W5QmXd*`dYbS%;VFKh1 za6k_wnxHmI_&0C(|NguGPu^g@dhQ^KEoyv>%~+ z5Np1Li#%2>j5M$LyK7;+2whyGto1`u?Ax|9bf0aTQp(R7apBE7?{8zy|F#)Qg#K+a zK;3ZR!o1m_)i4Dn!~a3ze|5u=#_y<4=Bm0iK^`Cvz3fxtV>W6QtGj1;r>5FMXX=x6 zR;}9LJrjk-b>YK^5+BLpXLmnqendx6OmB9S_qT?kgT!J30(FJe8iLCGT<&eNVftu# zzcSQyLJu5ox{rB9f)u^0);Gg&HQ77>$;_H87KDeb};;ulEuk8(B(?}pK+!=jrbhE9;ab5gDS?K5~ zi)#ItTe8e)z;u{`OlyI|fKM{O8a5>Q%V3niAerPd;p6yLk8&^+^INzZ|sOele2XQa{;DkaEZ#k{5z4c`y z%o;nDnXoNRUw;xyhTz`goZ$OF@*d2lZ5M!BY5bI#c28_c`1ShyoE?uyw(Ok3qlY5AA53h5Ktcd`)c~a@FGLNV9s&3VhX!8$OlEsKCTGJ+`^~`^|6Emc0xxcxhn) zz^Mc_6@GikZPtc$#7JhL%iSmOROaDmqB$xhHlk=#z>ctZgE1L%(Q$7@LozB%{oZ%Z zW1)9`l5$a#hU=>;Kh@TSX62Qmo0{NDn?o`IAp zVtVq5yGQuv;Y~bWjhQEM2#*A>r&Y?9GP4CUEGd6PrWy24aBLQ=JM31v3xrQKW_4#; zm?aOEsVISY84X8*D3~)IeI<9)pIO+`7=sgt9Y{>iL1GFY0LbFi{pApqdRHj8HPM=3 zLMwYX(dBD41K^KBB zNR#b%ZZH7=gy}7R$5=xe|L)v<{dnP%EsYqVZ%U@i&`@XHHdf^`{^0mj|0A9{hRBAu zgYSE@s}1&s-JQeL!et4zg)J&PF~9siqDyMPmJ|W`5)SVL>_s1a2Bgs553tlQD6LYM zy_mmDef0h6e@Ew9pjS|Ahc3t^s30R6S2tRf>qux$u`K($wV zGHw;7W|9N%w}=7EtGVrO*g^hp-+j{)(($=!+)E&q6w)yU+rO(DjA$ry0fjucV$%dP zA@#Ir)lR8q&$We^@YCBI;lUw(vHpj&z=x^amD-edG3}im;ic3UHdSf7inUbN+EuU5 zFyy_R&W;A|;|q}7(m`P;pMjym9Q5&R?G%;JUfjzui(R0USmeZxo?;H8W?F+Grswta zj7QHEf!qikOXvsfRp*CzMJ4N0nNKR=D=w73_d%Hg#g(F z(WUszi|W=u9^Svk!qsda^m}PN-zkJdQoju=KXX6B{3%E=_fd)4^W$(_c(Q~4Pr^Xn zm>An(Ji8ZfUJoAlJ|8BCORy{Z@gYMM6zKX_;l2C3o7=a=)_L`%{ZhO4rC_J3py{lP zk4_rbVQ9qgGal@1w}U5N+D~2y&eUwy^M{DUag0CV<850+_OeKgdQI*4o%if5`2C=f znSvtw0uinWg+Cev!T34qE~Qv;pRnTJneSs z1fv^V?eq%RDX1|0Lr?-L4!a%Spq3KW$=4?JP`#YqpD)6Wmg~ZqnHgcjtwt=vB=pNl zNI~f?F_O)BkraZ}A+0BR9WOj`O#<7O@gB-pe0N9<7vund&KiX9%|8P=6+wUdA1HL{K^wA={0$UPq+v8crt52q&IE&mW>?fxd#7G#bM| zZ>WNgK>GEUBlpW&nTTie^kv-Z5QsH67mNPW>yW2^V;2{Z5DJc*A|C(dyAztKre&CA z7tuy)K=PxIoCGvR2JFt5n67Cq<84@Y~Il*ykeV7`Et#{hi1n|O9Hl|6&QDXDWRgl1bYHH0Tw#E zu;^Z-Zn&;{Aox~??Sv}4kf=XP0Ob$7l9A2j`xw0A97m^P@UAI=K@Rrd=t+&hXY+{( z=R)#(_c3VlF_E8sJayvs{xy;s$Qp8~QQVc-bme493ObKmDgc4M$b%zrH}Lc}Y)W*H zXZ!wrya1umF@hCBb4EwX+xNCfi^5GrpM|~pYAH?(W%L|NR1TBSd}aqqKe3`|7kXRP z>$-a4?kT9wT&3dsjbv zy2vaZ{5h<$ppi)OCsv`#Kife z{a5PpLIfq-k(ix-9L9cGrSvG@^?NiUip|!LkePP5^BaTEO@Szi=tCjzc=jY$AxxMt zyTXO=d-@Ai<8%(*Gnn~h33CRKLJDRq2Q6>&^Pkmaj zev~kF8<8ROI9RVE|H2kz-ZE?BFVnX}W*(!j zZ&QiemjJ1R0`54<2_AJ=A$qJd-R}ln$@uc^v~G5oN`$WmY8lE{<)`)DMNPbE?zP4O z)2=u4I@P^ciN#q7b0}i_RIz|H3UZbIO(k-|5&vN<{Y@p3K`OENKO-AiU<;^$I95d= zRW}>AZ@WUn!jsv_fZ_T;#d5@JTWlfwJL*l`?|}Na8i&wQ@#P)T^O|K{R!pBanuO-H zJK+f{O%fKsOzZzjlAtcI;Ao^U)bQgjB;YZn#9z2ZM`u-$HjODgYG+NKTVwe# z*Y~TtsWLVg(*^YRe+lJq(*nOBkWE52VC;VgLGX!jbv0wj&4(LaUTHU}Z}FYN`){U( zk&A~3KXxl@yF4t73&OAZ;ME4Po%@7itQPuKDQI)n?P0^$?}d-ny%$XE@>&Q$F}U9q zM)Mh73>JGn6cp%Q2mWc4nE0m{EDcjOLVCh24TZ^WAPu4Z2=3Oo50U#DO3V^NQqsI9 z&$t$tJVPucOec@--o^WrYZbVV!(;<)K7z=RfrYZJhI(TQrVG4ZNtlcovXP-W9FvV+ zW6P2lAW}*5_Ca!)3*nrAU|<5&2ZdyVR(KBJ4pKES?2Cr+C8X}8e*1z+a#DIkhPa){ zWTH|XslWFS-R)QCq{+PNLFZ?h+-D^OVQs|JO)O;|?8DYO??yIr%+U1!gX z#>wBkc&)W~Q1R&`V1)21k#2d|_hl@c1S`EK7{n?_czvwjd37uW>KI48^LgKi)niS- ziR%16k-{L&G(X{J4#{CE(^k7uI>eO>qhvs^K_%=_%x9)i;>T^RRr*(ZtAnw6gf(Bs zEF+2U#5;^Q#V{N_JXS>Z8hkl+VM0yY1c;b-){|XeyRo3!m>U5BiKlz{{zE?ZW9$8} zU#ANLvDm*xzo(VuIKKRxQ=eLtAd7ruP1_$X@MtTiazuQKGO0q_ur=MfBoa}DLCAV! ziR-^Z15gW#kjzKa{?zUOP;N%@RUxTsR%=<>3An$(X<5U&nWr=Rle!%u;M(iz?c|y9)8Bi7xh(+qW97O*9+~bQGpox?jwSeg! zeGcyg#`V0mKc3>{n&%1H+Egg@fmv^JO?KBqSpuheT7If(<`Gvt`Fyvs0(Go*p_)U_jetkEcX4Qot(lc-f@V_=$P3BtLWpGXF{2Zq+g@NL$H9<^ewr` z_7wERArYdt3?!XIz@ajOMTV1%Lu~%8NDe#abWJ)TWU_1x=ecWE7OmRD7fMvC+0>U+ zEY_>!h_4Y*z5BEVTEvmoW^pdR+;R0vdec#8cyhE~w}VauG+1saNC-&u#<0CeOB8?( z^UM&p2uKGfY=rHleM6{*OiXwL@)A#pu?;pf^hUc&^ev!lU8-j4uPHK$9DY#AzKg6P z_r<-h`)HX%|8lZa$PI;;7v}gKkdV|-fyFpJ?9d++WgPy#Zy}2Xs*EOztqa)?l#v%> zc6gNYmp?J{n-Q`wFlaRKzxdFV?H`0ib$%_Td|FEIPLYP__dx_f0ER=lL;bSeSMUYF znz!YGPThx7nPRYk->h)87;8WL-I--qmpC~rK4$kbJg36Se1X-j&NWl|aJ{Oed9#5< zPHko;(;4sh8Nr$2sd*fWN@7FFhgEBrKXce56adJ-jk~SIR7g#>M95Bry&fIVr{RmV zsIfMs>KP(tHCxX=s8X8RQD2LriPsvE+Q)5sfof9wrq)KUDTymBeGz3JkHBl=widI7 z1!^5zz!3_pXSHsr5ZzDFMP|NZWpmq{P%USSx`Jx4;e)buA90^KSm8(9!eR|AWL5it z#irbB1ecCH<(*%pmuA$)Y)PF%@Wh}TM#%x<79h0T1?zd91Z2c0{%*6jo`j~e+ze*{ zV}LK7zi;aOw4IaSEzTg4bAN`X^`IY_4ZCDjlcaZrdz<{nNQk{8ezA;d(|{hH=o)JQ zzblB~N)OBG8hf!TT_{XFGaTzP%)kw9Q1P!1?2-JfRPnykr#))&QH(pj&|l73BG(TtHE{ zEAhDU3;BbYc2t_MU*aDZl)QiLl1IFmubqF^VXhs;mD!~yPlh<4GTGc9OzpLGIpSb> zM7*5N@+qydIhO<3-|_3e>~$~-q&jZM!?qX4x<1?Dk?)D2FsKO$Ve z9JYMLu#OIK|GNU;&M~MX<<<53>yy1Io~{T+_gLxpp)=+9iq-cu5lYr=lhl7=jz?xi zF1jzK_WBWG2j!K*-4H?plO6W#=gM#rA+YNCD!DPwac@qbvETYs)`I+RSVUOEv-L{-5^jspkj z8D$YBWRN8R^R{fTU**rOb&9^kyw;EEJ)1did2g}G)nVqh{_BH9?q8Xg=(FG6?fKXb z#wOP!V0K*O(p+7iQa$#FtT$Oc*GFt`-cpp&GeSU`H_k2l)k zX9TVLZ&mlp(ewMHseB1vD9DS)`}kTI%sz$)E*ak?&kg=#cg^Izj}{2O=L{D&DG28NQ1xa zVus=*^yj)I@D0ro#J4`q7;ikun6zgfGJfF}l;YKfk>$B@qe?C=Y#QeGHRxh#K@rgL z4ttPXAT#Eaw=}OwWQx+crPrfwPsb$dPv{Z}*0x~V-u}|LTbRry9gB=@TX*=Gj2toT zD94V`ah^83zoFwkr=FzhMs_L4OQmxZl8uAGcm*xV;f!zsup%F@8_+;bKtqAI2K*=| zQGSSwdpHoW*hmLGzvHj7HRWyT%slr76Kgk!e`bg|vhc7olBO!HJhYDlEkU7A)`N3u z*w?VK-p37>>YB$_h#*SG1h&|Vv<*3hZr_3hG^UqcC|&CU`JOU434F|ih{TkUX2YVo za=70+vPd0_{0iogWaNiz5o$XSyx3fQrM5Y-DAd-8y=I(9J(gaBBRm0a^;ckQ!>Jf} z!h_ZX1i0M+`8&|47zY34@lS@4GsOL}@}CT265CD@6_c5;TBC2qgM)Y`5eJDUCkj_X$Jsx-LH`K?c1aBghoV4SR@Ces}R*GzX>_HyW z(9}>(+``KTfR95btVHg5j_pE-oiYT`C=sk;UPPkRz~uphou>V93~W%s<5FQoZr zLBWG&IsWGO41Fy(h})M0YvgXxsyM4t%%Z)0)qH)I8XSBm0|YyYQe>KK*&BW$foA`^ zOTceB4Zo#KQPtEQtIiC2B-VJ1z7`pbku<=#P+K!`8!Y9hz`*~c=fR@0OlxlMK{;#t zSmedmnwYO+wDx@s>#-SC=$u;csaVk8dkY4nVX+Z#+9EYV^eC(-WcwYO@}gm~%Ao;K z`*yxy{Jg&)tpetr^Yf+0h&6Q5_T5CD<2W}{vn6JZ!pH7VL5})QXLHH1PVjD_HTagW z;$ZmG7?D&)-{$Gwf8NzwLcqYx_C`((?KP`2Hh}@PXnldU-#6No@;-w37ub%Nn5|SP zj~_SqUG~3TMhIv8R?yHB44#HM^AtuC3=1v>tEU5H;=we$?1(n({2@`X7COu%O5$2N z_4z9f<}a^p&prfvvbCSK1`z5JUw!0PJ2&+H=`~-~pGhdnIPK6NFxWQz_tpO;b1nD% zE90eM2%G6cn&hmw`j5)B2qFnM=1}bn?Ss~)gN++n-r8Yti{69puFEKEzF0Be9&HQ? z3O`7mBfCL!8y@&FVBU2&cU8gP-tYftWv-%zQ{{)3J(wvBgNafit;5UZa0zLk@c`=Q zJfLdP^QUTo#5^2uH@FJ=nfiA=CPk*pY`%y@vbb~p{6_Iai0#QKeO8jx`M7L+;)h*a z?S(i$Oyptp%r=$dFMX%O{$=&+;5&lCQ(7w01uXJJ0mwx0lQLh7x+-V3+7Q0l-CSb% zcD^JQ|8g|u+nM>gb?+uY$3ExtDKMWJ}F25*s~ z8BU5`JaxMuP9KCv?~fXqTmpyO6NPw3NX#KI0BOe_!~Gl#;!E^WeYy?`)bJ=VI>^sB zOord-iY$-dN+3mcc2Zz|7{vd=qnhUW)toVd-^HwA%8f5(w&SNNQ}-_)0&8oybA|9D zcnSVG4<0k%tjkGrdSXt9H3knG&r_6@;ox(Y4|%zmnt8NaYiE@|YxAS}Cs4e-CuzPH zMs*V6?Ff~=;#aQeGoQTE)M7bWBzXp$&v9TV(V#4bg8)3XK(G&lPOGGV@umNaFdx^W zK5)x}#>A<+kEJ{+qjudvOt4*ebF`!ugSd;ZxNLo|$7oj~omQ=IdKiaU3+uI2Jjs;O zbd;wZ0~;&*7Whiw*)b>p01QXbR{?lsF(fccV20Ou7HLYq!ZE{2DLRIHEX&e0N?}Vk zXk|MdkZu$D?&S~bLxLh_?#Rn8h6dyaMqa>@3Ko z`5_4Rf?#J||J_+u_pl~vv59DK_a`w$(JR%1B2%gZa6Jb5`%b$L%8;bx6^F2yB5cT= z_(!Lk9tQaZr8?$)Xjrw6CebkG5$pr+3^42P7kU#&sQK^Pbkp9v=;@k;eIw2eDI4VF zQAA82=k&mF;$v~2l*vRQQlwwcXV}c3TOB^$lA%8v5WYI!RcPHMg^IQ)r%fT>7aY+^ zf$<#z*@QyCxPzJjts6<3!xsLZOfK?%bH>g`pEo$2a9?fUmIH-(pX_d~O0Bfwu!@l2 zOQ`BY?hm zVY@HBFv#&KB@lEsSt}S75zf3QMAInEG~Zv-{=nbXyR-{dvlI$*8vzAk|E1*H)w~?X zpt+jW3UtPO_IWQxIo#_zXS5jYG~I&S^8$kQW%A%pNVqRb1QAREzER;K|7Va!73 z$MP8}JZ^s%O|lL=Y<4h!vVK)Gy#hF>_MZrR%H(men!m^*Jhyg6FnYw>|7|^2U`TdB zVUe!=oxIey^8EN1RX2K@7@_VX3=JxMP!2R@P9O_ijS&|Fx)dx>nI z`x#o%UzKOY^W;D?8tyA$(gEh4f-g&9dt$D9wLzYGf~Kn2-HQn~0pz02j&$a=_Qmcj z0(eYWy75mO{PRUb`IWC0ptQ2IX@`8mm6H!okM2Kj>@5^e%7ou9C}*IskO}R+g&%H_ zDAN1hZi&qTrVmoS-qdlusW(wdS=ASL8%T>TRjC>MiM~jyhiRAP`_D8E9=j?wtcqQc zdnTKn8mk&de8=E>{Di{B0oxH$7cm14q$gTsVubu)%SBDZk&t@O@zVxV(t7Q)NaQ^U z#*HAWV#_a#G2+w>8=-qdKhb8>c5t^21}^P(v&`LWCW8NVvvDzoUq;QZYUv zAb3Hc%S_R%lTCMF=)ay<*>6sy2=qH(V<<9?kcCos@xy251TPiU^nEO;Xi|@LgdZPM zdk9(@i+WZ^uNb|P<<|`+AuG}FE^mwn6_>aZ@TwUu z;IhtsBQp$sdq5zR^IW+6Y3xok!fd)+0xOE-zQdsm%G}(vs^BH2d+M)uX!QA;%^8R( zD;)&%5<^1$8TEgvi&YwLQlYl845WIeCm-6Z!c5 zDKBm$(%%ROA$=4ea@(l9e#`b+UreN9GK}C!ZTy-=p;^A!N$8bbBH8*J*b4yWKdOQ! zlTzT4o;vHo=0U|o0$0mz7m|JhJ0Bfl@>iVd75lmN)nZfy%8$xb%+^`TF&wnV>-`MH z;SuLHsPEZtD&%bf@$ZbWaDKAEuM!(d@9JmbFyb=Yv#X=7Kj5VXxyv+=b%c{v9usb1 zKnh8>faX*DsW0+u$;(F+qMn?7Y@GD|P}f4|31KUiUdGrikC)pXyYnZ{LSwukt1~Hd z)2VMBvJ$O|x2uHq=Fq;u*)dZD1^c8%dLf{}2yZSVOUW;lXNWkBH`U>rE6Dy_ws>NE z+;DyG?R{;2KEflVU!K^ehRPd|Z&t5+iKB4eJ(PV}kLYkj;uW_VvZ9j$KWjNQGUc$# zLQB9)LrPi1a6NXfU9jen{)E+)#@~w&PVSwK79)v+bM)ae-e>~&^YX7IoSl|v1ZkHeS;z3wRm zwRKnbX&lfh^ne*(>goew+76JR@=3(0~>{L*7!{ko2giiYip zB{B!{3NkbZ1PALc?TVyP!|T((nM{q5EQF&eSbIX=D--fD;e95FI}xu3{G2FBUgg{1=PgnMBnE|Ao&P z3g?dfovYCMdj~fSv%Rrcs2ZBAl#|Z=Y9t#rX+pX6aKB`axzqy+Yf1UY-aE4v5ZdU6 ztH|f3TIaR&jG;WbC>V{UL&R2%gBYB1FtZbL0NUw0p||by7M@tzG~}n;S9{WazJ zLkOS>_a^eTYSxxD#xeiiL=j=nv|m%UBw2CF|M4O}t=|t~H>p}bF$9W7g4!b{L`#!mkj;i~h9JJ?cRn85A}E20`sP?*f&Mf9g7&v96!{=h=u$ zYc!GN@h{>-ysve!J`~eg-$w(4}wadyg3=S80g||K__Ps@jWPmhDNAb;cMo^!`;wch%`} z_w@<*-HK@CM6o~Mbg%Y&`y~18TYCPR##{z)mw?dUsRvY3wsLM^$mjJ*PL851@+pz! zkHQMktTno06^kM)D&hF5p6}nrehCz!u0MK9_cot{hVuBnVg0tsAlgEw*DkXoI#+^s z<82)>w2xi^weYG-@(>7&fBAga`k=NPeY$cbG?YWHs#cVasEmw)vKMjY*Uk0|;t+lh zryipmwpjgmDu3ZdccMwDEz>J*;qUxiBj+Z-6wTH};Si|la=}gIa^a?O5+iA+Kh|SD z6h}lko6x7fdb|5PvfF7Zv{CdSZnJBdUXy!&9QK9MQS(#1fPG|wKx#wW4E7JonVdfz z6l)Mf;j>>sV7rll3p6wip6wo6o2DS+QTJM*0YV-^o{4^y6#g&gdvAHV7_8)@w`uB1 zye9PUQJQmDRRsGre!AXGKBtgkmonz~+Fp;%E(ni92%u65IS(KLL@+HiaPb`fqF-tY z_Cbgm(Yd&}+kFt#SHb1xm(kZ+8l_8dZ`%wtXx4k?(dU~V&xfY&^GB?V?P`C*k7|l> z%~C{Q?gz5!Sly`5o*8;S0nlL^{ODQo&$tCB$-}2DyjWnlCP=N^EQm1mY9tTX`k5CC zMC)()?6gVVIzxdz{h0REa|M(SqcW-J=uA^HNqI(Eiu8%h+a8zGU!p{i+qm0ASx|C*WO*fCuiSbTUs>nMYCkOJ z=%cbU8VS-~&`vE{OBRB3G7rN42q1vMLX(?eEH}z?W3>JJM^bvCN0x262s0P7PHb5`{1Bt-TnegwLU$(Pqokgi> z))f54IjjD0fIPa^DP`Gj_k)0fy$w-gX7sYomw%@H`4}DP{PMGD@J$pgDy$GP-m@&yCU?TY2uYk}f3s z7z(3~lAVD-@B!AlmTcP|`d9c4g`>zUoXC9E(L+*KKM#NFYmQimw06%MWaFJG{|y2z zSw4i0%h%hELqVEN>y1=%h0**)v31{6!D>!{1Yf7&P?b|;}%d+4&}J^E+c%^Ow2RJW%bD-y+uvtq3883GvZ7Eg?xMQX#; z6@0Ka>@N3Ib!`+8fM4DQ=tynRRNt1Lu?3jI*9JZ8}14OkaFX* z51~MGz;}cfjLJe| z?9$y6f2|e<33p8*1HGe-tdP^3%wGNaS?SiS(n9b z$A_08%MmSys*-51-b665F>?&;Q^kl#GUz>`?Z0^-9^;!UA3&9)MC0sR&FgJQ#7-K^ zei`;<9V~czMQh*)o@kI~4oc4}O)Fw9Mj^1|mobf>_3f(E)KSklvL!Es=0 z^M?@&Z+nv~k!Z!cw}h%$A(XjFqDCSLEq{`Bsk2UWxmqv?_}o;3X)2$Qq<&FU$E`NO zi7u!j-=1Tgj_%IeRtYZenC?L?ezrK>DjSi3^YE1!VwmlqxfzU1KkSezUdM@?gRp}=d&4sU~;@!H9<0MQG^d-Haic-c9XIk zgVMK^mSU{h3F}gen5}l)+Q97s@!7xwWe0}a&ChU0UNh114N;~b6t~+* z_ivW^ZZ@t_LizptEBf-t#9by_0=_3fCe|HPr9~H5^HULqeqRJ0f=rC-o=z%6Ou-4> z*n^9@T`n}Q|fBWl8Z9a z@A9`o^DK|_p|uRH?&lt;mXD*XvlUdu=l`*Xdl zC1`Mxy_^77Q#dMg!nJ6K7~G4R5|9E)0(8hXz&hb3K!+u`0LsZS1UBmg=$!Q>`$^Z% z5Fu%Vr6kB4y9GoaG$`PZo&)vIBt_>x4T`~ZN9VGCVEs4NB!Xr;+!UgGnP|+`1&3FG zz8|rhHO;kT8Twptiz+*GT{NFO=w)EI%C8N0)}$@=f;@??pmNR&=BLNX`5gB@c>FJ{ z7sR{8-?zH`;Ob^!int)cuTo{_fj9@V^u&r?`J9P(ZW^C{J+Kz{Pp~VsFPk-xcXW zg1Ld1it&fw$o28O+Dea-3tQ1JpQiOKq%dU#Div~5?iSPE_k!n!A5x2N9K5m~axQ%E z*8GW5g7cJVkLWk>T|qUmW*JN+lm&F(P9^XLL_8T4jF8rUK>3kHW1^A=nIF|&D1-j4 zjw>PY7OK%8jG@JFamHP4_jTDwuf*Y~sm<(VvZfuE`}H}!F6w^^1u%G4D}di>UoXIW zgB9XKh`OHPn~2IQNo*S4v#HSWmCH|CpHS$*<5eV2%>L!3p*)6u9f+V{;nVd_bFlxJ zW)8JIXBGd?0n%FNENB4#qWQ=mUXT~39B?`*nR zfO91)GOEvXmPG^^zm)aiVE5MDT&cD;&S!gAI;x#jpRs(Or-mV7YT_eO)OL9J;%WVX z;^J>Wi#7ZV&gl?97{1)f%6OGF!#n>%BB9UOX;T`Z3d@X$5XRiYpqRK>A)#=-^dsI* zZawm6n}L^LF!?FckG3U7!o+xrWn4I?qZ3Sb!m$N>{Am)dSd;Ph-pG)7X?zc%>Q%-N z8>S%>x>FinC+X9UD9p4l%=$!obdA&(5dxWe&~FLc8$VKSn9QjU^Yio_zxKIOuHqa{ zfqP>F#@_+%4gX6(R+B&yoL}FFsFxY)wP0{ye=q4+K=Qn5B5OdgKPn-}LyG@~jD^m- zTq&zZOC44`Sgw)kBy3mss)ZfFd|M2)=Dm`TEH?sbrWDMa6o~aG01aL^eOT(|=g-0>E)lMa zXDs180d8GTQ>o7ZkOwZ=B$6=@A)mI6h#a*x1~XZyXf zHx4~%2sMSDwgs(AInBQZ;_FM$n8SLjD?d<3!L2f2)bPq>JltPbG}}I-t!)gWnY;kl z&513U%e`@Dd{Wiiq#gG~P}jK2-$%xY=4$5c*^{XLte^BBUqo7&EQ-EmI-Z{F{_+(9 zNB5M+^kJ|CK;i;0Qkiyb$UF04nY*kbk9&8!bw<-bha{05t4aw@hy-i$8u}6so)L>< zlL|}mPvPRZYmrI&MtMW~kA!IUS_nJ}pwI}hiqD6AK?O-7n4|*=b*Mk0x|8$a_E@(8 zUPU;o6=8<^MXi-q#MIe?a#ifk*w@2KNn0sW#}9nW5}5VIzKDsxcv8gU#a^**a!}_nl42jy`jju{#OCB?M$M9V*bBdd( zVw2mGU>20=^F7Nl@8syH%Yx0a=K}Ht+j&+2F%P{SBZTXiZIqzC{78Ebp)&OsMh+ZU z>zu;sAplrUMKC`Hl7*3$3_Q#|$Vrc$a%`4UXli}V;2Q|$U`@DhuN5!FYQJ4Tm^0hV zh^wTN{c&`~_gzWX?*u!>`0wbivdhjw1O!I`tbY9iPG_sZAw2n=H$?sb6*9=zZWye`oHE`qN21TCW(O07W&Q(8LXv!sNG9;cdmss#OC zT@R1SbBL1h>tcCqd7o)WPWo1OQV;dM8+Rq8k8A zdJaQ!IL?pm!Ei>QB!x6yW`)SSIR`OFPp0YbnsU9ioo6-o3U7b6bi!NxZUXn4@q0F_ ztE8pnE8b7mh~jjiBwM`Wu)CSSZ@x88{I)!9s21R1>X{)B@Nt^Bzt4~ml`wjW~djz3j%VfO!4N%Kp)SmA<>^0a_#e!)Ih9LDgZ^u+^X(pQTX zHw-zBx9dAgQ+Nuk^~u)-^N zze{66%rJ~oqcONfG2~Zs!`3b~nSC%@Z95nnyNY|BzPvNYpHHyrUe31uSrBW4%MiY= zfZ)p=poRdMGf%i(1bgEy)_5b9%54gTJ0~#L#@44PudZDof(O*jl!1tAVVLE{s!p~7 zMZdm;iZxW^SWktC&aE>D1QrT=V{8S20vNnU{`ox|iJgD(038wTRQG@zg#Ma)rva2z zP8UKXs5$#nJXv=F=Vo@jnvs_K@;63I>$bQI(+nt*Y?wCEXC~B_E9cRMdrH*E^%a3H z3kqo7LmJzsZaY956`1LB+!!sHsM;hei{rbtAH_+B8Y4S#wue8@9I>@7BPBV$ogJYN zx>Ly3WmY~$P58jfG9(*s{5NtA+kqk&cC)dU8HRNg!>6R3xT|L9V6W$1_@?F)dz%vS zuc0D}52{@dKB839U+dd)YTiwBL3K0c0s8ukLSeqLMF}LZ41_#Y8YgQI`hp*Va70%A=)%1v3Vh8<{5Vl zBBMgm8c(+@I+0J+kTHNVl@1qtrks0xf%&R1VOUN5SDlAxV ztV}<+VI$t?Zn(-2*l}ZAQ>4+ox_#~yjs z1wlKPy<9qqlAf}Tyk~*`Xx53uX9c0i=@*b8<5j&`g4+@hyMX-Kr zSvJI5KgRV!0EPPgEG^ROyO;8XNzG1LEuEOH8W6Kz@A3y<*PZ&ibBd*|P_i66>7n%U z-m9jTeC=%W_S4(Z{gn64Qia-xkNV7@{kHjFbHGEm`x$uKe45tVli|+A6g|mng)@OV z+O3yC=J(|LOFO3xIa)`X;O8=-zdh!hOqcLyJ;#`q>K+}u_&K}x>Uza8_AB9b{mBPk zTrXtM81C)?v(@7Plef_;JMO%fJQT;(CAKK*Q;X=0rC*wjLKZ<~T7(n5PmeXG1_tiP z>h{Tg1tF1bhA>n=6nR~2Z=rHuGQCL=Mdbnn7cg24>jh56+=&Q~R`B`vuDy03J%3lA z$kkTH-h``0mbJ(Bs8U-UdEqz3T1DzkS<5qvxNPZCUmb(HDkX7!4&rM+Xz}_>#G~u3D5a>>?n zm?C2%H)B&1PquX;0m%FOUvm-gzlpdFoJ40r{xlmZQ&&@^7Z!8c7!NWdmo4ii>i6y- zD?P1cP+7A3c=h&+|LW1}0r4l~<|M`GeP?Q(PD6C|Yc(Nl&l0P@AR~Z**nb}X@6Uw6 zU9ac&NB4_@4g*DGjXR2o>?*OD8^Jsy*K^o2bF2;2XcQPU9FRS3 z+YFyZ3)*r~C=9iye5u<$A_^&IDU5USEy)9=gth*PA;un?AU%r)yqbiM*xYTea}Oz3Z03#@-U% z8UK9k+N5kedHL;xVw@S@z^9ov2>Rz^`RuY;D}r-!dkG0@Y>9A>AkZGW2P?j1esu+4 zc$ugkuevmkX;KA8ixWM3-Vm1bGHLKa%Ps5*L2q(I7UiSO^AfuML)u@4Rk?j%!0-n4 zrn^D9J4GZUq)`+E6p&6SDQTp;yGt4gX`~xz1Oy3b1e9)&@Le1A{QmFre0;9!oa1%; zu=ahgd#<_0oO8@E%`mFcRACX#D|n=&)MUxHldVZ#JS^b&c8~y2a%2M|0saOhg;gC^ z`c1E8t`$|p+Dnp$mm2z`XGlGYceodoU#MjFiacS4GKs0?72Z2MXsRmKC|{1DzijeQ zqBbUXifBG6C(T%BF6lH+MEq(19N!R_erIUcWvX(;jYUH8ny%m4_P6?+uop|KAKjL zP>=u$|HG6)7~xez*eB>d**P;eKFmx(xIs@>sDBbgep4ZE?>@im)Hb&p>qFv9|C^1% z2wK$rg0X`HZCXR~75wa*^+n5dkN~m*w_9L4S}@`5ESax=c<+{Q-aG2%Ww)aQ#14K@ zfW5glk@}(e)9EYS5fRYk;EjE~u#-V=i&@nz786PDcv?O_2f-I#3In0C*%MWMAwv@vb|npmwwM>O6F-4GMQBUH;bF%mb(NwYMxFVNZ*QaF{IGY9<;s8rz(Mexs+Ejl%UQlLkVu3 z$$<&-*2u4et-my6krvrt*W)MDcXkZ*qTg7 zF^(H)$3ltO(gx5_u1*Ok^b0b;OixqcX1Y#S$WdN3d-X; zPh3_f-5cVkAHh0)Xp*W*HV&~*WP~IY=t66AJ|;eYw~)wzO9YSW3=4so-kh`2gBd8? z+THETjZG%y>>FxjOM(I@Z9&tI$bXPBWv~wjzGaFLtenI3PH*Q$-w3Nk=_xy1gz2W3 zF}Bek{<0y?*@M4q1mI6XkAs1&N+4`$epQhqeeGIv?(!B=6fRifFmaelw=dJCA79|D zB63BWA}i;;gc$K9Kp9yu6MAC1Q@uj(y1bvv$0Fo9K`Jajul^C54NCcZ5=f9FU{%?_ zfmLPwxeyTclMW)U9A1ZH(92|471+14gbPlqkoGm1ScU|(Z-lz7iL`g2>vB^#Z1{#8 zBgl*fw$K}VcWzHxpf!f**8yQW zJTSI&>@Kuq1SB8EuNlX|Zd@#saqen0C_17Fd2sKq`{WuAmmzFQunXUl8F?PC4cDgxS09I>cr0rC=y zEEcM{YF=SSA|C+9hA|&I4Gl^v3Uh=8CY$VmqlmGkwY3{0x7OK1Z=y+)d7s@#zS`e^ z5QP_GH|_qc_#!PAoeFw<$&zgtK@{0D+mQy9x_#y~?$qhD0Rd9_=-VplZ%Z@-gsxlo zLq^!GM`(l@Q5bkg!NOS}KJX#ai^PVMI*+n+K{Vat=ru+amsoKq*-gXCLC?<$@BBEA zFDFOHo94N*gVer*_Ei<+1Z9Yq`8&Qx2oNv;oeN9{@ce7)G>=t%Uwc3}_)&>)E^GF` zsz}(F7RE;No}-GXRK=tGyu(8GGCidw_|s(P*Y(pkG+#o0UZp5Q8vpo9gys<@=ZZPe&vX%A(~G2~azcVmENVQmftFn0MIjmG z4HTDl!hP9e%Dxf*6|^&XT=rdJ_D^(m?~=$j>!x?rYlLthA;d1IaQ>|q8Xv>N zng&=Vo{Nlv!7d~i&6s>2%(j5hxwYKIITgKnB2Ap)M>CVqjV#&qutOl|AhI`chv$=_ zj0r1Fys35ZsudfjiwVWznqPUc#)(?0){*X&ZM~GRtO6nhN#iYA^2Uxvy^TNVv+vs# z(k3bo$xB=KBGUbmKAI-4cvFKzW40Igz2z;_tINmGqwEblP;LraFyMO*8GKhAx+q2$ z!hyv=!R-UkLbacnBBFP2TYQB=)C>GjQ~arcv^b;Y46JLs7~?PB3ex(E`;$93RVDn?Lb#5GX`xb*asf82GbqSbB-iKYB>*WS*>k72$UbtzK1 z?2h7lL@3g}EC~0m_W(`zJzFhc*8C^9z!M+PZIK$RU`?iJ??Py{e=IGi+FyUBnuSJ( zGdJY_sU|v4{OTeQ?F0Fdb4WSsIb?wI9L&Cn zfV~=CPG|K>fIJe|FqDmYsUppXPpuY^fCCHaY}?7N6|Lpx<`OjtS)#r14$y3L633X6 zRXrLb7>;zn%7Q0kwPIkCaKU9zBE)Tm=hP*?iar3a9w;wEtp36JJ8yfQXaB1nO#grU z)&Jq$TL=&LyqYn$MtS@D0Iv)Dl8(bB=Wx(V!(YQE{ZMP2R=}tE|VnhEx_4`B=U;1BA z4F{FT?~&$d#}PE3WzLLA39Ix-VVRpT20};})1F!`qK71%3aafDe|g12;AQ2))2x1N zrxED%e1QU;CTu8Tj^aiNN!- zKa7Q+AgAgd44=FG_h7(82F*H0V{4oxjk`ym(p2-4%Ar*5kPi@UEa?*Wktt4`H+e{zg)Xf9ynetf3*W zl7E#v`0a7i<-AG!lz>vvvw%Rk2dw%L!{f3h;$CU;EzO0;?LrNT5zZ9I62whm zCBg!BAi{6K2Di8DRrnv=J?l*VNeTC0mOVV+yX)?EvuEPZnIm?&2&{BMeB2Dwm_R;>-X7rYg~D6hE%&6e>baS%CYqt% z#^+3yqc^xM^WH7wlByfHZ~Pt1d<^~G7`|C8~47*9p85DeFEDv988{D;qV7LhEtTbnzkwnW8@ zXkTIP_Cmr+>MO>S6(b}rbe(;K+@=G+WTQ`jPX|DrfftlI7B&OvHt@Rj>;}qTQj=ao zoJaX2R+tNSWAGp6wb4N`=;q%HmY<|8y4%sJ*PAR2kg^)11z-+_RNUP`gFn&xQS4r zdCREHlaRqHcK{)#wKQ-`_#r|%!KZ6HOR0sd{{3_o3t0pnbQgnWhUTa z%bObE$jP5u+=oU?AENQBg`YgqocVy5ejUq)h9j!mb9K}boH!FSZjDlm#&wZGGP9$AaEV$pU zM*mUUFClbvFV!o-1G<&A@8`8D zWA^f8JP{L=AH^R`UW+;ycD_mWKxDyl!yuSWdMk0}ryturQ08NUf0bKz7YnM4eb2+v zsx0kQZ71A^scWISV?aAD|LeULcn`4$nb0BwcdRcEH}FI7s>s$)87(J$`BRzI8Cv``^zPTKIX%2GR|I)b zg&xLczLyBM6I+|FH1q!rY=wCylwYmpL2n3pHJiuTpCY-K)juWO_si^auW(GT8d_Rm z3~9%Wew)%%DJ`hf*5@PjmTIWbkDRsRQHRHta0_^cmqeFPnLd!j-~TgU8NnM-i{U0x zvXH|eqQA4|QY>JViBDawC%#HiYZm~&Vz6l(_Y5;vE zIOvfDtFNDc64YPLDuQ3}#uR!`I_u3w|L5Sh7` znSF%?*oe$tvpB4DP0EyRzGv@}(S6H@wT^I*}OgI$X$Up|F0I5s-!8Yo$GMhSKu!V=`B>NuY?U!Ku?z8hnF z?6>z|GL(j0zr45C^oh%tlSdv652|EZ8h~0MC#NeDRD%X^a>HYa2lvI|hE>^H$aNH3 zkVes4$xForw^w3ao^(E0Q+?`ypU5L{mxpXD8EuU0xdky@JpHk5o98saJ=Hh*Da>fE@6gT5_Iy1-?4mzW z$*3!2iNjP7&+t_U0U|{AtZ(KXHZvhs^Y9vptnefUD!?Pe&oH63wX(kv;rs|_^DoWc zkblI8#0c%4UPU%SAajZqw~BqAr5WVD>2!5i%_g&)aM95E?nB){#B=|B&qlKsWn zGR#jmrkx{=za~04XsrRVB%GA|O&&Oy&9vKWVe&>vj_Xy%gM^p&Q4y{uEcsdGqCNSI zmQa?etX4=+?&x{vCLmN-SDg44Qtpv$3%+hmvn3W|@^og8iwnw{yOjojAQJ1Lf?Tpa z2yFl%BF+EZ*5t0o0!ct}o3!WebKn*BuJfSc0*P*n(~?~c+e35yrBhwn(>g)zZQ`1R=h%I+8%pO<4T#U zowBZlaqs~2Fe^J!lNWl7ClNb|A1iCeV8^lj^hrgv!5t-wuj$Re)M~Csa#soyKKb+h zsbOHGx-WSQ`o37fMj*u2H9n=T$NI|x;-f6KB*A#(D}l~l!eM5wC-V+pi9g|%c~toZc6hx*jr;AU{9O=~Su zH#}7&-<6P>Xu6wFsH3f7SBkV`Yo#Zlp@y@+>E3QPL(BzbnE}{`+p$# zV&N9Q|No`s5C8n#zBd4Ve|b9R3%6P3c~PkR3~zew-^MzqS5R zUJFN~N(zb)R^(%0AzU#A91h7xgrAIOQB77Q3i)@``LWg*nOZHMgM!`vD{p?Ydkc=C zm%A`R)NqhC4~ATWG)Uy%Zo}FK+;Sn|)Afm2al)`p=?N}dd>-)pxTqjzLAyeY5rP7_q0S^YE2b4P z8}c-32iIflW4l59aMz}v4-v)o%OBru*os{Pyz?#&7cg0lHiXl7&njBETRg9YUkv@0 zS3&HyxS8EJREGy)ic=s61LS}Q0Mvu&(qO9FA1;|DLg#)?Eo><;&yBTMTWoIPOiE8HEablk*>#1-Qr7c(vMXS+&!WURzFIVK;!r3`v*_j=-EkK#hx1g~3^Q_D8SsPunw>tFH$ip{;%@;+ zN!u!^yk9`<>5PmxProUi#{EZVy77v7`?#*>kGtLGULp|Bzho6)4G&~Pac#>?(HGWX zXP--O&ZQcs47tq$Ah4QX@CgA81s33r2I5@fAiw^)qh*eDT*45vN;l3p8Gqr9*@m0Q*Sw0jw;eKTnFVLC<8$B-SbD5#G_C z7aafEcD93p#s0mZ8!t)#ajx|G0HLHhirPC7q2u+wcI*eN_%}=xQ7az^o$OIGpT>a- z9^Ma-%XysvH$F44_~$dQ4c1_BIL4b(E`J+srt)x(U|Yc8j&1PkI?>~*9?g-dZ7n`# zX1>>BZYZ_Mp@$;zE5XqXGHJuL;tS^UM9=K($RKqybJWR=* zFA|bkKNAO_?+x~+vh#yI#zBCXqJa>|{M~J-1QbXN(e$~#Kp-aI`5%L<>J04bv7k-< z&mFb#BX@2KRJ%a0*P0Au)i}&DFXaQ~TANWE)EQqz3rb|*i5rMZ@9E5j7Cw4}*FD)|+{hX>Wyf239YLz*Nty&@Y?F20hR{LWN|I#{VJ3tEWFgf9q z2TMPj_Y0p{FJngZ_Z4#PiYIyqEYt%XH~B zygsD(?-#{e`_zI?a~zmqBlrPD{h7{eNb`VCsq=b)ft+$Z_{xsRDWl&IaPt|EoMf-g^3$>hf?j}JFi zf4m9mYha^e(8h2$?~3B7n(|=4Sgyuq&g-2z;`}WM^3c%{O39|ubd^(dn3Wax(eRf} z81evjXzLqExAGFrRrA^9zNTpA;|y(5b48Hy|26`rU3~>MGIj0B4Vn96e6V9@ETRLh zQG|A<`T*bAomdiW|Etk6y~4qB$^trqF|+x%1cUtiI0K|1kVQ{NZ%K78N_N!N=-r6y zR&tDdvLG-9Ein%0l1+6?+~x`>kv0TWtp@E=_QLd+1LphFJF6=`i&DP$HTanQtD$-L z5oS?9^cY%AU4P<1N;86D&BO%`i}S{17Ws{%jRq(J^C~1{Lg_RC`veCWP(uh&^Rjz( zAZk0D`yoN6ZN^YlV37@x<>e4Cz% zc=^Jz0CF%8tD!@h!GFMd{467U^3JdHF+Ju2^HU#fPWfABaa`@h?e9gpb<;+fdeK%c zo_<@9zXNNnt2iQT<_f(|_bTxFOyO>}wzt@GTN`MlU`&ISM$4>$^#tUv+^IRZ%YFnk zAo~P7uz(80RKV_sjGMidq&`{($3{D4;q_V_C{81|qjV7Ab7-L6m##7p?7wGBqD1}v zus4) zP-cEeNcUA2lrk_urmvtI?lrT(;^kN1%Fh3L$fS2~-U>@0$ds(1k7zORKRLw_VC0Zw zcH0OdT&2xhYGnEFo^bhlyszjEbcPnE@n@vfK5jj?GfKbV(`i(r0QezOkB4$SXB>yt zWx>yw{KOpYO8s&q=Gkn=fw4?66veanheMG22ZcORAIFtu@XwhQLOoUFr~ zz34qqa+>$Q9^b+5@b8ztUSf*ef0`<+t|OoXVI}UyME!N%jopF`Y|999;08@kfv5*} zQV4ory@kPygOMBc32)(hxyY_b9~!&M;NI7~Hm3X=xI?ywpa|%goVd5bJq= zW@6A0_-yP$ynamuus)5B?NVF%bwQa#h~Db|ziYvYDiIr+ZY+ZXJZ2lI#wloR=+%k8SH=W&W^C zsE1rUc9KSt7`-3>_$S~85DZ=+sNTCx&4aj}lg54GUrlocEWfJ{xexmP{zv;+cnmYb zy^SvLMxo#MVT3%Sx{k(~kI6VA?DhqE)gf5GVnZ%bw>1vAb2wH z-|_s|YaB-3H=M}i%@@^*z#E6wS5_w})w@ZS+&yfT!+mj&$CXmQIlepF=SH@&mNMFI zydHV;AtJX{;Qzig(7`kN1iTq&mjP%Bb?vHKpaibfdz(m(FzpY-)fx)4Hjpg!$u^%X zq!Lm!#Ueq`$_?;nYO$>hME+_0^=WF9-$h7bLap_u-z_tX%|yAyjVIV*H@pa76F^Y@ zX#uoV?0WYwf`B)QW?@s}+{+HD9C}o8Y%R_{F|qe(sIhb&?=+mecZrQaknferv8=k9Rm?L&dTkpCq7)HiGlBJiwI>uhSRO!Dms8}g61%IFU-S5 znfBp4Rz~($hdHW|eaCy4@%QD2xQs_4VfYKyUpG24T1w4Sz~m(`Pg*J+)O{e2TaX~) z;7)8m)5QKamS!YUy?HAA``!qoT3j^v_gbt zJZF3l?aqQ9`u9XB60Y7M9Vr%a`5Q5wHXcye93GJZM>FujQjQ`vWWezM`p$1!uh}rd^L&>jP#H- z5Nb#uRO0SBe6%OS?6uta?$P$uzNvK+OBYA+T~7uoAum}w73Rk)@y`@5H0}h=nK>+1 zx#pPOAg#~)Mx=c+%k_kX0~u~a=;~8&b}(-TeM5g{T;Ti@xkRWn{l47#m5|wijOXz? z_muW%Ew_@|n4v~^d2rZHS!Z1rfi*!;o8w|%`C zaPrRf&37hnyjqZ?M#dQ}l&nR}^EI8`%GJ%FyQ|a8#xN&lh6v@$44KtTiyE*Y)C6C7 z+C*fY$gOk5rtY*-*3f*8#WU%coaY2@?TfY&V3 zpoa-y&jCGR9~_0_(-dyV!C&mzP7pHilFVypj8toW=L)~-ahba)Cf!fYG#Sr(_Fp7) zhkvGzSTftz42q8uVRQyP)`BFa!?`KZ_eUZDZl^Jx?ud-8()&Z7*zo$w52 zkblabCaX6RQ|*R~yj^{Or{sK5(f%6QZ*>Y&SWQFq(bKABzH|ch@;hz)glMAAj z^ezk7>@nk@HU>T8*Gi!3HIB$=2Q3PP;LgGsIPS~`n~?n* z6f_F{-dNu-M-MzZYaXM#$Rj)ZLFHTHI|RG?2%)39sGe=|4uyx??^7<_SDs5%RpB(R zkbH?F3?yEErsEBe3GerA@0|ggUjepcg9(9bMC*@= zA(ju8HgitY-R(!1Mr1}r^xzj@cn-J#AR%J6xe1~UFg9EtGJxHKK`w*|2tx#rp}#rL zwK~doI1ggpVcy8As?AstBT1tOy7#p>yje!mx_S75l%fQ>vqGY4(^-dDa!?@NYfB{4 z#d}hR+fV(QC_wuhxW+^T=qQJb7qmN`RbXFiFFl9$)r*W`*}P1Z9$le}GFj!@R=q6D;C{5Z7gvNnb^jfQY;V38&{7TD{CmNJ1kp@_Z6n2!Nmr0K(ok`BlC z0gf3)&Q7CrI>rmF4e|z)Y1)2-6rorreeElSrxitJ8q^03rf#_5dpA5c{X`L-z!tRq!uhm?c|J zqt#IB>mueuP5U^87~IisQ>1JqMHcdcN$!^;3zu*Q%HzwBcfyWI3LEVg_4b3W=sKHu5rOOK{=-e$PklAcsPvV@J0dDKq8vChPPab*S1X;|yIr>6&pc-8 zk)E+!ZI_~!dsNXrk7u{fJK3Y;5(%q)af!1R#0MtQnU9>`-IK^W;V{q@IjAe8KViQy z&~&tndp+Z4K1~faz7v9qBMn6`fVQRrG_8(6<8Zm1!5ey$R6~tX>>|zTqFNC2l)N)v>TK@a{jK*&RDZu zF+bA#!@ua10r4VzxJnRN_poB)Fvm?9-Nff)-fU`sOfASMj(@NG^bz*=kP@W64V8c{ zA4B}J_}oumr$Bkv@^&<-J~*=RXCND4@%Kz|D)D!*OK)2|P_dq=HY;u3o12o0l&yI$ z5+W&odg0i|zCQFON`~*`Xh^_?u*jJvCf)g5(YM-w`RUcjXgK=qnevCSqA^}Tx5F4O zfUo82qd+aa-tPYF{9XR{V})bsvA<9nylfr-+r>x?wS%OHhRI>Z!A|Uv+!KQ zg~S(NWNeh?t>zxiIiA7-7r@tAw!nU%)?9XjVa#H8+b={uy-%+7K@-%ET1yIGzBD#i ztuV!8$dX{E6qg~?!U1t?Iy@HaxvV+eNCp=gb3w%2+C_W zDYv9-0Y8i%yBI#=0d!moGimC5XE6%|1!R0Lr!$+Gf@5lOtC{anB*dZ^qiQZj)zUo; zg&H;uPQ-dx2d#ux6Zym7>_&cQSTzhNg#Gp20(1~3AU$?bRbnFTV*U*8?`+>&SZ!%ngO~*PA)# zcI7oQOgwuqxJe6>htoEJ(2wE6L6pga%!HfSw^WWL>pbo{k1 z3FH`cA8M{H3!b6p@|UWrNR`b^C&3F;!;POGNs5W3l0IRa_J3}k$Kb{1k>-ocOx{Et zlu()R__(4miY}b|ul>3u!XbwySo;R7?fQ2gB(bAROX+vMcY4fh<{l#oV;>l72b(5S zy)ec0uw?w2!l}2FS!|jhRsHxNfN`ZTK7uhMzBLE=8CNblwdFZz6u$M@&n^J8&knvN zwMn!0@U7`aYSsqqvOVGO2pB_7bSmpaF&8jBVa%S6X6;D7g#JIS)a2< zV=j|QLS-UbF+un{Kh5l)xMjmzyzPT)FjrfMMV^-*)II({=&tNu!d206u)X~gea7n( zP@6M%5H?4Fs`vaE2&D?#PxDoZAw=!3>1oEla@lIQ%R>;ja^9&8MX*32$T~6@8aA@q z;(5eTnR$gfqi4;lB2*|FL2s1ZYbwFXSuc`8efq{Lf~4vVD37WfIJ!btn&GCm1Wd2I z19Rs9vi#Th486bErd1W4@lRzJ`jv}d_j$6$SL`WlHZ)~en8P;puu$$0?%%XP>;sfd z4cmO@6u6>3G>}UBG|NiYuPs=@jSuKEQHQ{S_ht9t<9a|Oyud!?7t~ed^~7XF-Y)d| zd|3ecrG}NgF-wG5&d8{LdnN%D>7egbo{_ncipj*YZ8WrVVOIPT7lHibi-&iGWo;2q zZBmdP&Y(hGfalG-?*BLc0l_46Ul|ug+*x@JGn^eue0|k$h51zj($TRvr_TXFtoTyH z^*bCTTq|nrN-ST?)JBAuqA-8Pw%3C5W<4qo;pk~oz!n-e1K*37KZyDq68m>6%;Fe6 zYaV%jR6SIp3l~rLmqX;>`KEUh=!Qk+H7|e&IE=(pxWBV%c|b9r|4MCW!iMZ zmMs5nBufm4U*H_tLSq|1F88!!@nE;%ADtvQGj( z%g>r;epj9y>mu1kzW-~LRti=7_(=T4v((``SvIzzfv(K8z{LRoY|CbiVGf$pooxv7 zpsT-qr~*7QLlPgBZ>-N0JZEi5AZ^%8dZQQdbZJI7?qp#UlhcMA@9D$m1NkO&p=T~r z>ILz_<5kKPiUml}Dg~1QXlOcoH5aT9y>~}r_!amgmeX+>It%HI;!Dw{Y0Tow5S<~% zHyopG|h% zsie);En*L%v0V0$+7E)a_JGnw8B|FEwh3t_7X=Eq?i%XoX>-qpLv(kiqsqSDb6Fq8 z(7Rp@a$y%W`ma-Z=rB5V~en-yOHi}tro9pi`6 zpNq~KMOXS*`Rr{1dh%j=%UF&!TJzk_(&=(^jGD`jN_`{V5L0*I z1QbB?(Z3I}Ar(pRY)FW?>5w^h7QISyTJpSpG43{>I% zpUs#yI*gTD+$!=8F$y-bPFK&OxGqbpe;pf0-81@jW+D*7@xB=qk~RI=nl+J&+lUzi zj`SdvD*cTy3EqP%1U~)rZ!l6s>hCFveyBkh8K!)S^n-d;Z z9j-=$c?Xe08Lijok?r`lj|xNS7C()vu}OSY-5!knG@V%iKSdzuy=Mi)91{!Rfn-eO zxel34>YWKNU4hrHSTO}A!4n_KzF#@ODHj27xC)Z7hav2J2~!=6#txFXhmid2uB zax$C0(fyT27amCV48eZjHo|4)-!+Mfflz@RgbHK-m_x^dzxSv93l);S%O++~$@qWM zFg7l?t6WJ~tUiPZZu#8}q4?%Fxan0gsDUp+@$e!+ZdOUtsj-$kXmRW&bGG{`&-~*r zsfPa{LO*B|W=;jawJ? z#Qr1Ck2J}lo6ja#Ml)BiilxMT>R(lijdzAT3r__896<2@s~c2t^M7@N%7JcBHt3oE zS2+0a_p_8PrG$29D8HdWODQ&RG&o@xqi5~;I@I`f+7QiS6Np3DzvWLcr(r(!`Qi<& zwQ$1CObHCM$Me!xU%JB?umG$a)TvO*L4teg;?FeWa^Z@)9t3{7su{7dUTV)?(+JIK zR5ZiR9j$>^>lZnK;csG2;X~Lj6q}JO~Q;I{;^a!T;R& zQ#+Uh2H)uq41VhG&enXDx})N)U0f+FirR@S;Xc}_rD|C7xjPS8j!D(0!A3}qt>mtM zv_wQSztBQ;eqhV=d06(aJKJNPv>N1R)qi$&-6KI+O8bAC=Mv{RdeOLeAe z&PTZ7w2ywa8O&mx)RIumcaihwWb?O#Xi$E9l{>QawTm~R|0rzZ4$1y254gR%Si`F^ z1#st4x9E`*UL5}Z($zqNl%Td($+={Cxid8IlBjRT>uCEub=udYOu_qG! zr?m`}Gtw6fl1^H=1&r@`jhZsEp_kj-jMVzgGeLHYox@dr*zu9b2@8~{TSIvhz|-xX z%79D&tZ6)eh&H!qBdE%Ho4j>Ie4w3W3Wp&97bCKUoT1UUh<`IetWda9M-|3qKCl4G zn)+RB0_nJG_*eml%wF{QpTgv8km_9ry{Qri&D&$P4_EIY4XTIyd?4s{Z?Tp}Uz%Tk z|Gnz^eS$oU8vQqZCd`9je#+fph8`;EvvhajDeis&Ag4evQp_Bx-X{VXn zv=azi$Uxw79HH3&q4@j7yIzv!2Md2ac^u3#J6)U^EqG2nnT%2E|1FucjsD(zI%S8d zjMpP${EtQEk{MI(RzyD0?R;*ZtvO1ou6+S+HGbHD2z__PmOI@t*#T4$UrMc<=3>{#~s++ z7v?T%<`=2wXd4W9HdtOPrJz=jEZ?hxoUZkCbI0TyHr_k(>^R@e^N)cZp8{C(mkSPC zdg9Ti^hlm%P3k}a>hQ3Fhm_CctGdadW9bc*CQ8%su)R5XXaGZ**a*_^;6l$d3XuMc zA=Z}5x|r0XavuOI0<)rt1>4-Mv;^jZ6TEKnd(NkMQ&2Kz-!ada@#9O)Gh6ceZRkv4 zCD5DH$L)3au7{~;9JB~RPxWZLrQCj77rK>1Yh*+tRwYF$=72GoKjFoL08n|8fUT&- z@?uSL2s@x&J^ZxuP%c?fyK3u_iZ&u3pEV-TqHgSgdy?+g7S;rXBF!?@XL|k{v{a99 zxi*gVN-=Utrr<{E4W-Qj3$CA;=YWo9u{Qzt$4g?b*n=E40vb>5F>GV$)Ndbp4ec`U z1?-q1>$vz2)+dIt8rdFSc<~VHye?1T6f@o>yB}7%6&wxkpMHG_R+|cjt8V`sxr3Cl z_W3=-yKnYEc6&4ZcgvhB*(W-Rlw|$mUwm)~lK-@+(m`v-AuN~nySyAXNH8+cVbDG_ zTH9<~BO5Nj5BX%y4GoNhpYF5qZ)I9dk_zqb%Ni-3t_4wZePrPFxVNjLfP<4cUrgxP zfVp&+YEJy86%AK6GV*14*Ifw@di?2@iNW(v!(s5#UCbMR1ns>oyIg4<%vN_#lsqtG z#zQhCR@t^MEM*SmFe{n=?AhS<^7*O&%H$D39$N+JtYwQU1w!7C#<7XfRIJjhPj@9z zDSWlCRX{*#^npLy&4c;JcE2O(<6tMQAi&3vmnVMO$J^k*;P7fkvI*)krEeYq>F zZ5OJOo@O$fl=}TDKVB}$;zWwSm`j5ezMA9#yaYT2&#{3#1&^qN)`emvA;lahS2aV+(uzbHoPg^~8tBh4t9_X$4wC-8I_ z8WJ?cfsp|>vj{Ai&%Q4)hh?Lj88(|*kcEkzHLYEWAe8o-#vA2`OqHiV!>^!PZSm!* z3{!dO3j+K2pmeV2L`(Yg4NFO*GmM2G)$naUVc8Ny=(->fDJx21WClkWS6g$Q3~j1G zyT_EN9h<>kW<5LXj$2p??Ocl9juP()y=v+hjyf_zg^jXsY5S9Jf=E_m{w(ooVTjO9 z-eo-Cfoiv*enj9b*F)i4MM$2cZbUs8=BNz#DchXtVpo7h#0fEO+=@C7U$u ztjA$+YZ>q8)zO_;(gLND$w{8tK-%mVY9eDS{xaN`hq9i$!T8oj&%Yzb0ssde5UeT; z4}#>uFN`2u17*j@f4v3iZ(2pB2MF>icL6CYpkYu~iLob?VSCXbfs zvCMtdd1Hv2jO|$%vz0j<^Imo=bhy zJKf-UqDs#=RbB@y4BWoY&%wKgmH}aWt_|B2L7F7)-v$T=6n)ACE71ikiknxGPT#po zg9RWnGGi)ViT9S(e;&cSW7amL!tyCnXLQ+e7nGeWXcG0|SNZQ@;5mA)^FM)?=N@;+ zYgcQ;wDgt_B(rQ_*zk5~3m1Fd)Z-%)o4t_Ywk+$1w)a~vHBpy(4<(-Jhm4^RG0S#& z0QV=q1GO_M6GAy?lH6A*Y<{u#VA&Cd?Pwx4)aR>_t!#Z!PmV}#t&)18cc00cg_U!e&;O{2} zi0v;X*e{heDxN0#&y!~jJ-|#sEnFmi-pnO>FL19HJ%vZn(L3v|RRyRUomwTO$4iceNVn*gpRZ<|C-$FDW@-mM_JUd;*oz%-Iu+GuRN|L?kuV2(zLVo zRallD0U8w#F3A;aIW+7HY|$AIxj+Fc>f&FK!+CAj??1)Uxfl0h5-~evBG~woY0wWz zXtgucZ002q-De==Zi&WDb`y@0a(w|F{)EnFZ(neZekl3WQeGJIG?bO3+ZodeNNfGe z?f)0K-2Wp*)OhhHa(S6BulI{elxCK?N5jv3EGt0(A2$zu9Pi_Nda7w$M#_>x*T-p{ ziJYusOLK+<)EbY2nTO)k9Y_VCNa32eK(G1#5xJCA{olyN8ALAW@EGYY z>AHz_Mh0Im;&6-m8c2ppWzEcME5DGHW2QgMer-M8Z|zWaWI#5--#PA>$y)C%+xeh| ze3vs=RBYTWMHaM${e3I4AZS%SoJw5)0Q~wnpi)O&)>@QTm z2T)op)ZXMCS{pEKR~uz4d=i#yR1>KkgRojv9T_7;+a}EQv0}~0BSx5TP$P(kRKb{e zup{S#5{Y>ndOqb|X_;9DnvZptNfidjsr~y9APXC40nUGSKKw#8AfCD_nY*>@owhfi zZ`8%%{vgjnuCFEh9FbZp}W?T%neiNHiA2B z$|Ua7RRsPT6GtxdnMZ6Qs)Rm^t6^RYX}%a+Twt2<#RA@#bDhx9@6lsj_-gl>!BoBU z%Wg*heKALkf;yjp@!SToyAVWd2et>5CtL5Np)K_y9W;O#RmfHO)?D+P_&jW~KAa7= z$h!000mLIFoW$rdBV${`8NQq-5D9~>-M}BtC4Gx{*s%sdzP`dJ=|WS_IV<@+A3MWV zs>b2QOG}lJECVt*TLLn6V~mcMEv&il)n1N))o#F;KH!Gk z6Y(;|mS1_6by{-Y73ZzJ_DCQcdX=QdUEKaA$C!gsQrs$>TB?L|?g38x(9_HJ!w!@` z?)YKN9b3xGkBWs0tII-6?P{T>k}|SB`NtQx`XB@Tz45JW7QX(N zu-`hdsM7mI!EhW!y#{)iqCY6`D%LgCKvA<+U($s(p>k7B?p>75b9Ty&1lpGc85v6? zQ}1HLK3xVT~`$4e4TMOAU26TKHGCp3YB9nj<_u#Pp$7iI<|o;5db{DxcQoe#jtt-&R`eJoL{^~u?FAHYZ%iG|8udvZ(pT9J7tJ-%4;`~Q*l z-r-okar^jvb6eRNA$#v^A!KKh5h7$ocD7{iEt`yp$d(zh_uhMN87U+4ciqzGd49+D z&*wNg`okaB`?|03x?baaou_EZGLEB)o=0|TWl4-Fph<;IRCoyzU6CmiaAsE zY;Tua$jj;+&1UjYn77XhLSUd*yNT*$wYX7FAJ z?R|$bSfczGo=_dj%Qs$vHB|vtlPp2LGqgib8Tg_(2#}v^d6!8>>BmQZW%GzE_{#rw zW&L?N4}mZiKtK|f@@_( z5ua_vv%MVH%wqx>EnyOc?50`YPkjq_WZpLRMGlb`%;BtDoV$d+Wf{f?X()I>)AFV% z#RM3@Z3sB zG0NPGrt{h`{30|qJ4Rq=bz_gU1abLO8S=M$YBJhIo-uX15S`C5@fRLrj@dM!WKke`$}3d_<}+h; z+^zELbX}eQdc8LIlbk1fbJfkm5mq564Muy{z{JBYj0R*iKo?5Wcg1Xo$L(Ze8DsbH z++$K7FY8mR9g(DT6bM4U+TRbo18!>#J@k`24UPoqmrK5yUfXL-$v{)#!sjw+kv$9q z!F6PV-MnD3AZ5M55Axujg9*U(O;D)(xcu#TXDqYoDeWkOLUH*w3d=F(!_{~{mK;Wf z?`n?ic`X4=eNqE>Eqk@icdPNZQ>uTJw7wfU3GYa)hgooft6Lox>~tWKG}Ko^ z`k1Sw28GPIaY6@qB+zwI_v^6UnHlrkZy4O$g!xVTr0c z)lc29sCYxSD9$P+JJ9bav76DYgGC*N!ua&*a3JwwwKqkY51!w2is|d~y@vxr-NzMA ziV36o4XNM29On9Y-g6QUJaj`_5|zQtQA75+Lc}99&3q*>S0_wU`17v#f_WDu7!f=W z7^YxZ3$m#n00FCXv~#-(I{vB4NEN@xJX?RO8AH|%2P)NH%NF)_xd9tYh+(q9C5X*^ zA(!TLmKyb2>^vE}+_VFged;7HYZC;?)An|$)WknB}$ z>GVoQ{?q!C^63-VQpWy#!B-)%iRs|3BG6*R-K4a)k6W?83?D;tV@I&Qn7zP2U@Q;} zE3dTpmY)>)BQ&Cx3Umr1Ci1+VZER3mfi6xZjtO+RqaxROOt`9@yjB?@a;E7rcK3 zvP;-<2XcVLfPS+EWst`N2WM$wuatNvziX0c4N(p5D@+?GQGUQ7tjtP~LeVqgC?LU_ zu!3o^$8;W#Y{{?a2&&8YebYnWK`@5>J*9DHpb*j!1e^`AM~@MA{>!VLJ7v833 zy^=1Cwera~>7jj?g$SS&_~*s`7fyI%fG4Ha#s?l>aB3AQgZ? zpim4rZz>Q_zy;w%T>|*hZ8$-4dzPBQrr4BJwq0XhqkfAYsFf6w75u68;0bLh8AegP z_We0}%hCJnjK6jybM}s>cjliLG5XPetfC6hJ(;O@60 zBob?5x$9ubKTHD;C%kmv#M#wV8zb6gZUYQF^{w0 z&RRdUPjAP=?*)HS+LVj%y6ybx={I9UqVe=m2+c07GUK@18lVBqepRg>-}zQO5;_W_ z$vwnw?6q!XA>qffz67QO^(YaMDjzlZq?HPua3A(JeJaReIqq9&mGip!?tQM=;7ZdP zm3Q|@EZ&kwm(y(X6B9{`a{Uy7A;O%g@Z#53i(k7n@amt*gjbDOxJDQV z5DWn8x;kprz<^-hZq~$aC!^Okq0;@<{`;g$@eDr*0_7eUx*(2O5mHvtXR=d%3bqi1m zXU&bS@c5;_Z^b|xSIpJX@j6hFZFxL)7Tw*4f&1o8vNRcwaWKjc*1E}}<==mcD@vch zW-p(@r*|M@P3f<3^>w!3&wF`ohwppck-i>F)`1wOZwYm$C+aHWvvb`|2gr=E{Ivz& z92h;k!!;#KOi-otVYxrsITr4jTj9~s9LS!9gKKodLo)O83k$8zL|<@oiPb&slF|~4 z+0W0QsJm>?4gX3PLWpWW|ly%Bj--m*?cxYg(oCA3XLw6Uo zGpUHD850M?M*>%kTn-tJ%E>;X&`0=v;@m|`+lw@WQjOiEa=fM^W2;$nMsJ{`5&i}s^yhwkov{dScf4UfeXBbNyT7_F(fzQ_^Jd|mf&3%1WPE&r7u?&X zTq0*zPq;DEXOKhL$hn7OwS9nnx%W`Y2a?~keFN-8#cr6X=+S(Hc~|yJi6ma^tI)r*uE$=*p}lK6}5g6cK

    $=IJ30B;gpK*CtB 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 NmiUTfY9HUo3jk(b>k0q> literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d new file mode 100644 index 0000000..0d2f3cc --- /dev/null +++ b/poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d @@ -0,0 +1 @@ +{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3} \ No newline at end of file diff --git a/poa-network/single-peer/node1/password.txt b/poa-network/single-peer/node1/password.txt new file mode 100644 index 0000000..4b93364 --- /dev/null +++ b/poa-network/single-peer/node1/password.txt @@ -0,0 +1 @@ +password1 diff --git a/test/helpers/merkle.js b/test/helpers/merkle.js index be2ded3..d80e3bb 100644 --- a/test/helpers/merkle.js +++ b/test/helpers/merkle.js @@ -81,6 +81,11 @@ const createMerkle = (items) => { const pathMerkle = (leaf,tree) => { const leafHash = merkleHash(leaf) let idx = tree[0].findIndex(h => h.equals(leafHash)) + // console.log(leafHash) + // let idx = tree[0].findIndex(h => { + // console.log(Object.keys(h)); + // h.equals(leafHash) + // }) //console.log(tree.map(l => l.map(b=>(b||'0x0').toString(16)))) const result = tree diff --git a/test/merkle.js b/test/merkle.js index adc2a0a..adf913c 100644 --- a/test/merkle.js +++ b/test/merkle.js @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0+ const Web3Utils = require('web3-utils'); -const BN = require('bignumber.js') +// const BN = require('bignumber.js') const merkle = require('./helpers/merkle.js') contract('Merkle.js', () => { diff --git a/test/validation.js b/test/validation.js index 8441022..d57d648 100644 --- a/test/validation.js +++ b/test/validation.js @@ -29,20 +29,53 @@ function bytesToHex(bytes) { return hex.join(""); } -contract('validation.js', (accounts) => { + +// Takes a header and private key returning the signed data +// Needs extraData just to be sure of the final byte +signHeader = (headerHash, privateKey, extraData) => { + const sig = Util.ecsign(headerHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = Util.pubToAddress(pubKey); + + const newSigBytes = Buffer.concat([sig.r, sig.s]); + let newSig; + + const bytes = hexToBytes(extraData) + const finalByte = bytes.splice(bytes.length-1) + if (finalByte.toString('hex')=="0") { + newSig = newSigBytes.toString('hex') + '00'; + } + if (finalByte.toString('hex')=="1") { + newSig = newSigBytes.toString('hex') + '01'; + } + + return newSig; +} + + + + +contract('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); const blockNum = 1; + // Hash of the genesis block + const genHash = "0xfddbd5fe1a53989f2730c8f5cfd36eed28a8bf0837d6e95f9aa1e5fc01d157d9"; + + // Find the validator of block 1 as it is not known a priori const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; - const genHash = "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28"; it('Test: GetValidators()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = validators[1]; + const signer = validators[0]; const validatorsReceipt = await validation.GetValidators(); assert.equal(validators[0], validatorsReceipt[0]) @@ -52,10 +85,10 @@ contract('validation.js', (accounts) => { it('Test: Authentic Submission Happy Path - ValidateBlock()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = validators[1]; + const signer = validators[0]; // Get a single block - const block = web3.eth.getBlock(1); + const block = web3.eth.getBlock(blockNum); // Decompose the values in the block to hash const parentHash = block.parentHash; @@ -139,10 +172,10 @@ contract('validation.js', (accounts) => { it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = validators[1]; + const signer = validators[0]; // Get a single block - const block = web3.eth.getBlock(1); + const block = web3.eth.getBlock(blockNum); // Decompose the values in the block to hash const parentHash = block.parentHash; @@ -190,27 +223,17 @@ contract('validation.js', (accounts) => { const encodedHeader = '0x' + rlp.encode(header).toString('hex'); const headerHash = Util.sha3(encodedHeader); - const privateKey = Buffer.from('d18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083', 'hex') - - const sig = Util.ecsign(headerHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); - const addrBuf = Util.pubToAddress(pubKey); + // However we cannot be sure which validator is s + // const privateKey = Buffer.from('d18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083', 'hex') + const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig; - if (sig.v==28) - newSig = newSigBytes.toString('hex') + '00'; - else (sig.v==27) - newSig = newSigBytes.toString('hex') + '01'; + let signature = await signHeader(headerHash, privateKey, extraData); // Append signature to the end of extraData - const sigBytes = hexToBytes(newSig.toString('hex')); + const sigBytes = hexToBytes(signature.toString('hex')); const newExtraDataBytes = extraBytesShort.concat(sigBytes); const newExtraData = '0x' + bytesToHex(newExtraDataBytes); + assert.equal(extraDataSignature, '0x'+signature.toString('hex')) const newBlockHeader = [ parentHash, @@ -251,7 +274,7 @@ contract('validation.js', (accounts) => { const signer = validators[1]; // Get a single block - const block = web3.eth.getBlock(1); + const block = web3.eth.getBlock(blockNum); // Decompose the values in the block to hash const parentHash = block.parentHash; @@ -278,11 +301,13 @@ contract('validation.js', (accounts) => { // Make some changes to the block const newTxHash = Web3Utils.sha3("Test Data"); + // console.log(txHash, newTxHash); const header = [ parentHash, sha3Uncles, coinbase, root, + // txHash, newTxHash, receiptHash, logsBloom, @@ -310,12 +335,14 @@ contract('validation.js', (accounts) => { const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); const addrBuf = Util.pubToAddress(pubKey); - const vPseudo = new Buffer(0); const newSigBytes = Buffer.concat([sig.r, sig.s]); let newSig; - if (sig.v==28) + + const bytes = hexToBytes(extraData); + const finalByte = bytes.splice(bytes.length-1); + if (finalByte.toString('hex')=="00") newSig = newSigBytes.toString('hex') + '00'; - else (sig.v==27) + else (finalByte.toString('hex')=="01") newSig = newSigBytes.toString('hex') + '01'; // Append signature to the end of extraData @@ -328,6 +355,7 @@ contract('validation.js', (accounts) => { sha3Uncles, coinbase, root, + // txHash, newTxHash, receiptHash, logsBloom, @@ -351,7 +379,9 @@ contract('validation.js', (accounts) => { const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; + assert.equal(recoveredBlockHash, blockHeaderHash); assert.equal(recoveredSignature, signer); + }) it('Test: Authentic Block Unkown Validator Submission - ValidateBlock()', async () => { @@ -360,7 +390,7 @@ contract('validation.js', (accounts) => { const signer = validators[1]; // Get a single block - const block = web3.eth.getBlock(1); + const block = web3.eth.getBlock(blockNum); // Decompose the values in the block to hash const parentHash = block.parentHash; @@ -420,9 +450,15 @@ contract('validation.js', (accounts) => { const addrBuf = Util.pubToAddress(pubKey); const addr = Util.bufferToHex(addrBuf); - const vPseudo = new Buffer(0); const newSigBytes = Buffer.concat([sig.r, sig.s]); - const newSig = newSigBytes.toString('hex') + '00'; + let newSig; + + const bytes = hexToBytes(extraData) + const finalByte = bytes.splice(bytes.length-1) + if (finalByte.toString('hex')=="00") + newSig = newSigBytes.toString('hex') + '00'; + else (finalByte.toString('hex')=="01") + newSig = newSigBytes.toString('hex') + '01'; // Append signature to the end of extraData const sigBytes = hexToBytes(newSig.toString('hex')); From cc2255e6863c51034cac863bb9879fce7b6c6518 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 13 Jul 2018 14:54:22 +0100 Subject: [PATCH 058/203] Added Roots proof and associated tests. --- contracts/Ion.sol | 67 ++++++++++++++++--- contracts/PatriciaTrie.sol | 4 +- contracts/RLP.sol | 18 +++--- test/ion.js | 128 +++++++++++-------------------------- tooling/encoder.py | 47 +++++++++++++- 5 files changed, 151 insertions(+), 113 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 54156e8..2771025 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -31,7 +31,7 @@ contract Ion { chainId = _id; } - enum ProofType { TX, RECEIPT } + enum ProofType { TX, RECEIPT, ROOTS } event VerifiedProof(bytes32 chainId, bytes32 blockHash, uint proofType); /* ======================================================================================================================== @@ -126,9 +126,10 @@ contract Ion { * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove * param: _path (bytes) Byte array of the path to the node to be proved * - * emits: VerifiedTxProof(chainId, blockHash) + * emits: VerifiedTxProof(chainId, blockHash, proofType) * chainId: (bytes32) hash of the chain verifying proof against * blockHash: (bytes32) hash of the block verifying proof against + * proofType: (uint) enum of proof type * * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution * of this function to only allow if the chain the proof is for is registered to this contract and if the block that @@ -141,10 +142,10 @@ contract Ion { bytes _parentNodes, bytes _path ) - onlyRegisteredChains(_id) - onlyExistingBlocks(_id, _blockHash) - public - returns (bool) + onlyRegisteredChains(_id) + onlyExistingBlocks(_id, _blockHash) + public + returns (bool) { BlockHeader storage blockHeader = m_blockheaders[_blockHash]; assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.txRootHash) ); @@ -161,9 +162,10 @@ contract Ion { * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove * param: _path (bytes) Byte array of the path to the node to be proved * - * emits: VerifiedTxProof(chainId, blockHash) + * emits: VerifiedTxProof(chainId, blockHash, proofType) * chainId: (bytes32) hash of the chain verifying proof against * blockHash: (bytes32) hash of the block verifying proof against + * proofType: (uint) enum of proof type * * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution * of this function to only allow if the chain the proof is for is registered to this contract and if the block that @@ -175,6 +177,40 @@ contract Ion { bytes _value, bytes _parentNodes, bytes _path + ) + onlyRegisteredChains(_id) + onlyExistingBlocks(_id, _blockHash) + public + returns (bool) + { + BlockHeader storage blockHeader = m_blockheaders[_blockHash]; + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.receiptRootHash) ); + + emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); + return true; + } + + /* + * CheckRootsProof + * param: _id (bytes32) Unique id of chain submitting block from + * param: _blockHash (bytes32) Block hash of block being submitted + * param: _txNodes (bytes) RLP-encoded relevant nodes of the Tx trie + * param: _receiptNodes (bytes) RLP-encoded relevant nodes of the Receipt trie + * + * emits: VerifiedTxProof(chainId, blockHash, proofType) + * chainId: (bytes32) hash of the chain verifying proof against + * blockHash: (bytes32) hash of the block verifying proof against + * proofType: (uint) enum of proof type + * + * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution + * of this function to only allow if the chain the proof is for is registered to this contract and if the block that + * the proof is for has been submitted. + */ + function CheckRootsProof( + bytes32 _id, + bytes32 _blockHash, + bytes _txNodes, + bytes _receiptNodes ) onlyRegisteredChains(_id) onlyExistingBlocks(_id, _blockHash) @@ -182,13 +218,14 @@ contract Ion { returns (bool) { BlockHeader storage blockHeader = m_blockheaders[_blockHash]; - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.receiptRootHash) ); - emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); + assert( blockHeader.txRootHash == getRootNodeHash(_txNodes) ); + assert( blockHeader.receiptRootHash == getRootNodeHash(_receiptNodes) ); + + emit VerifiedProof(_id, _blockHash, uint(ProofType.ROOTS)); return true; } - function addBlockHashToChain(bytes32 _chainId, bytes32 _hash) internal { bytes32[] storage blockHashes = m_blockhashes[_chainId]; @@ -210,6 +247,16 @@ contract Ion { ======================================================================================================================== */ + + function getRootNodeHash(bytes _rlpNodes) private view returns (bytes32) { + RLP.RLPItem memory nodes = RLP.toRLPItem(_rlpNodes); + RLP.RLPItem[] memory nodeList = RLP.toList(nodes); + + bytes memory b_nodeRoot = RLP.toBytes(nodeList[0]); + + return keccak256(b_nodeRoot); + } + function bytesToBytes32(bytes b, uint offset) private pure returns (bytes32) { bytes32 out; diff --git a/contracts/PatriciaTrie.sol b/contracts/PatriciaTrie.sol index 73cdb6c..65b35a2 100644 --- a/contracts/PatriciaTrie.sol +++ b/contracts/PatriciaTrie.sol @@ -4,7 +4,7 @@ import "./RLP.sol"; library PatriciaTrie { - function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) returns (bool) { + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) public returns (bool) { RLP.RLPItem memory nodes = RLP.toRLPItem(_parentNodes); RLP.RLPItem[] memory parentNodes = RLP.toList(nodes); @@ -65,7 +65,7 @@ library PatriciaTrie { } } - function toNibbleArray(bytes b, bool hexPrefixed) private returns (bytes) { + function toNibbleArray(bytes b, bool hexPrefixed) private pure returns (bytes) { bytes memory nibbleArray = new bytes(255); uint8 nibblesFound = 0; diff --git a/contracts/RLP.sol b/contracts/RLP.sol index 42ba1cf..3aa7796 100644 --- a/contracts/RLP.sol +++ b/contracts/RLP.sol @@ -167,7 +167,7 @@ library RLP { /// @dev Return the RLP encoded bytes. /// @param self The RLPItem. /// @return The bytes. - function toBytes(RLPItem memory self) internal constant returns (bytes memory bts) { + function toBytes(RLPItem memory self) internal returns (bytes memory bts) { uint len = self._unsafe_length; if (len == 0) return; @@ -179,7 +179,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toData(RLPItem memory self) internal constant returns (bytes memory bts) { + function toData(RLPItem memory self) internal returns (bytes memory bts) { if(!isData(self)) revert(); uint rStartPos; @@ -193,7 +193,7 @@ library RLP { /// Warning: This is inefficient, as it requires that the list is read twice. /// @param self The RLP item. /// @return Array of RLPItems. - function toList(RLPItem memory self) internal constant returns (RLPItem[] memory list) { + function toList(RLPItem memory self) internal pure returns (RLPItem[] memory list) { if(!isList(self)) revert(); uint numItems = items(self); @@ -210,7 +210,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toAscii(RLPItem memory self) internal constant returns (string memory str) { + function toAscii(RLPItem memory self) internal returns (string memory str) { if(!isData(self)) revert(); uint rStartPos; @@ -225,7 +225,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toUint(RLPItem memory self) internal constant returns (uint data) { + function toUint(RLPItem memory self) internal pure returns (uint data) { if(!isData(self)) revert(); uint rStartPos; @@ -242,7 +242,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toBool(RLPItem memory self) internal constant returns (bool data) { + function toBool(RLPItem memory self) internal pure returns (bool data) { if(!isData(self)) revert(); uint rStartPos; @@ -263,7 +263,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toByte(RLPItem memory self) internal constant returns (byte data) { + function toByte(RLPItem memory self) internal pure returns (byte data) { if(!isData(self)) revert(); uint rStartPos; @@ -298,7 +298,7 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toAddress(RLPItem memory self) internal constant returns (address data) { + function toAddress(RLPItem memory self) internal pure returns (address data) { if(!isData(self)) revert(); uint rStartPos; @@ -358,7 +358,7 @@ library RLP { } // Get start position and length of the data. - function _decode(RLPItem memory self) private constant returns (uint memPtr, uint len) { + function _decode(RLPItem memory self) private pure returns (uint memPtr, uint len) { if(!isData(self)) revert(); uint b0; diff --git a/test/ion.js b/test/ion.js index 49bfc79..1eec0fd 100644 --- a/test/ion.js +++ b/test/ion.js @@ -58,43 +58,6 @@ const TEST_TX_NODES = "0xf9011df851a0f2c8598d0469e213e269219f0f631bf983434442623 const TEST_RECEIPT_VALUE = "0xf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" const TEST_RECEIPT_NODES = "0xf901d8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" -//{ difficulty: 2, -// extraData: '0xd88301080b846765746888676f312e31302e32856c696e757800000000000000a317eac1407c2095a544b7574618e307f4a3308489c9570a87424fd8057714b20701902291849b8586a1d5044282a638017429bfcd36cd01d145515ce3fac5b201', -// gasLimit: 447846308142, -// gasUsed: 1395032, -// hash: '0x53e7275992ff72155dbacfde26881872d7b322afe47b104c7e96079761100a55', -// logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', -// miner: '0x0000000000000000000000000000000000000000', -// mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', -// nonce: '0x0000000000000000', -// number: 15108, -// parentHash: '0x07844784b5ed519502da2708ecbc1a3f918bae7b3daba06bd55e08f3dcaa42c9', -// receiptsRoot: '0x6fc7cc2a8c59c0e2c84fe806d652e636d1a513b9c3cefbe0b53920c5787a1e2c', -// sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', -// size: 5758, -// stateRoot: '0x732b314700d866f88c612c8ae3cc74c91f2e873b66ae13eb8cb5f54780441d14', -// timestamp: 1531404477, -// totalDifficulty: 30217, -// transactions: -// [ '0xb8aece2b5060358b4eb788a64e240bd29fa82c6edd277b4b7d58c9a8b6b57959' ], -// transactionsRoot: '0xf79d0f0f21b250c65ce2817fde4f2d4bf2edb23de4b1f06550a8f2fa8e34aa4e', -// uncles: [] } -//EP Root hash = 0xf79d0f0f21b250c65ce2817fde4f2d4bf2edb23de4b1f06550a8f2fa8e34aa4e -//PATH = 0x80 -//RLP ENCODED NODE = 0xf9141d822080b91417f91414820c5f85174876e800836691b78080b913bd608060405234801561001057600080fd5b5060405160208061139d8339810160405251600055611369806100346000396000f30060806040526004361061007f5763ffffffff60e060020a600035041663550325b581146100845780635a0235e4146100ae5780636b4f9b9d14610110578063927a32e3146101605780639a8a0592146101965780639e43d86b146101ab578063affd8be9146101c3578063bec205b9146102b3578063fecc37c31461038f575b600080fd5b34801561009057600080fd5b5061009c6004356103aa565b60408051918252519081900360200190f35b3480156100ba57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261010e9482359460248035953695946064949201919081908401838280828437509497506103c99650505050505050565b005b34801561011c57600080fd5b5061012860043561056e565b6040518082606080838360005b8381101561014d578181015183820152602001610135565b5050505090500191505060405180910390f35b34801561016c57600080fd5b506101786004356105b5565b60408051938452602084019290925282820152519081900360600190f35b3480156101a257600080fd5b5061009c6105d6565b3480156101b757600080fd5b5061010e6004356105dc565b3480156101cf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061071b9650505050505050565b604080519115158252519081900360200190f35b3480156102bf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610a9a9650505050505050565b34801561039b57600080fd5b5061009c600435602435610deb565b60018054829081106103b857fe5b600091825260209091200154905081565b60606000808581805b60015481101561040e5760018054829081106103ea57fe5b600091825260209091200154831415610406576001915061040e565b6001016103d2565b811515610465576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61047661047188610e1b565b610e6e565b9550866040518082805190602001908083835b602083106104a85780518252601f199092019160209182019101610489565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209750505088861490506104e357600080fd5b6000888152600360205260408120875190955061051f9161051891899190811061050957fe5b90602001906020020151610f23565b6001610f77565b8455855161053890610518908890600490811061050957fe5b6001850155855161055490610518908890600590811061050957fe5b60028501556105638989611005565b505050505050505050565b6105766112e6565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b6000805482141561065d576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106e657600180548391908390811061067c57fe5b60009182526020909120015414156106de576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b600101610661565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b60015481101561075e57600180548290811061073a57fe5b600091825260209091200154831415610756576001915061075e565b600101610722565b8115156107b5576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b81548110156108045781818154811015156107e057fe5b6000918252602090912001548414156107fc5760019250610804565b6001016107c9565b82151561085b576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600101546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108ff5781810151838201526020016108e7565b50505050905090810190601f16801561092c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561095f578181015183820152602001610947565b50505050905090810190601f16801561098c5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156109bf5781810151838201526020016109a7565b50505050905090810190601f1680156109ec5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610a0e57600080fd5b505af4158015610a22573d6000803e3d6000fd5b505050506040513d6020811015610a3857600080fd5b50511515610a4257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f60005b60408051938452602084019290925282820152519081900360600190a15060019e9d5050505050505050505050505050565b6000808681805b600154811015610add576001805482908110610ab957fe5b600091825260209091200154831415610ad55760019150610add565b600101610aa1565b811515610b34576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b8154811015610b83578181815481101515610b5f57fe5b600091825260209091200154841415610b7b5760019250610b83565b600101610b48565b821515610bda576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600201546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610c7e578181015183820152602001610c66565b50505050905090810190601f168015610cab5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610cde578181015183820152602001610cc6565b50505050905090810190601f168015610d0b5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610d3e578181015183820152602001610d26565b50505050905090810190601f168015610d6b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610d8d57600080fd5b505af4158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b50511515610dc157fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f6001610a68565b600260205281600052604060002081815481101515610e0657fe5b90600052602060002001600091509150505481565b610e23611305565b81516000811515610e495760408051808201909152600080825260208201529250610e67565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e7a61131c565b6000610e8585611065565b1515610e9057600080fd5b610e998561108f565b925082604051908082528060200260200182016040528015610ed557816020015b610ec2611305565b815260200190600190039081610eba5790505b509350610ee1856110ff565b91505b610eed82611138565b15610f1b57610efb82611157565b8482815181101515610f0957fe5b60209081029091010152600101610ee4565b505050919050565b6020810151606090801515610f37576105af565b806040519080825280601f01601f191660200182016040528015610f65578160200160208202803883390190505b5091506105af83600001518383611199565b600080805b6020811015610ffd578060080285828601815181101515610f9957fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610f7c565b509392505050565b6000828152600260205260408120905b815481101561104d578154839083908390811061102e57fe5b600091825260209091200154141561104557600080fd5b600101611015565b50805460018101825560009182526020909120015550565b60008082602001516000141561107e57600091506105af565b5050515160c060009190911a101590565b6000806000806000806110a187611065565b15156110b057600095506110f5565b8651805160001a955093506110c4876111d9565b840192506001876020015185010391505b8183116110f1576110e583611259565b909201916001016110d5565b8095505b5050505050919050565b61110761131c565b600061111283611065565b151561111d57600080fd5b611126836111d9565b83519383529092016020820152919050565b6000611142611305565b50508051602080820151915192015191011190565b61115f611305565b60008061116b84611138565b1561007f578360200151915061118082611259565b8284526020808501829052838201908601529050610e67565b60006020601f83010484602085015b8284146111c6576020840282810151908201526001909301926111a8565b6000865160200187015250505050505050565b60008060008360200151600014156111f45760009250610e67565b50508151805160001a9060808210156112105760009250610e67565b60b882108061122b575060c0821015801561122b575060f882105b156112395760019250610e67565b60c082101561124e5760b51982019250610e67565b5060f5190192915050565b8051600090811a608081101561127257600191506105af565b60b881101561128757607e19810191506105af565b60c08110156112b057600183015160b76020839003016101000a9004810160b5190191506105af565b60f88110156112c55760be19810191506105af565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280611330611305565b81526020016000815250905600a165627a7a7230582024e7bd39ca02a13e7b30d3f8eabcff1f54aa2b2794c25da896d910015790ad590029ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075820bf9a0cf066fe78ea2e58000322d541b37763dc8d5daad8b301e63d0d2e5bdc3f2fe6ca048f44173b406c4ebd09b4f52174d00e6019820ea92f1caa5dd49d2f5652671ad -//HASHED NODE = 0xf79d0f0f21b250c65ce2817fde4f2d4bf2edb23de4b1f06550a8f2fa8e34aa4e -//EXTENSION NODE WITH PATHPTR = 2 -//EP TX VALUE = 0xf91414820c5f85174876e800836691b78080b913bd608060405234801561001057600080fd5b5060405160208061139d8339810160405251600055611369806100346000396000f30060806040526004361061007f5763ffffffff60e060020a600035041663550325b581146100845780635a0235e4146100ae5780636b4f9b9d14610110578063927a32e3146101605780639a8a0592146101965780639e43d86b146101ab578063affd8be9146101c3578063bec205b9146102b3578063fecc37c31461038f575b600080fd5b34801561009057600080fd5b5061009c6004356103aa565b60408051918252519081900360200190f35b3480156100ba57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261010e9482359460248035953695946064949201919081908401838280828437509497506103c99650505050505050565b005b34801561011c57600080fd5b5061012860043561056e565b6040518082606080838360005b8381101561014d578181015183820152602001610135565b5050505090500191505060405180910390f35b34801561016c57600080fd5b506101786004356105b5565b60408051938452602084019290925282820152519081900360600190f35b3480156101a257600080fd5b5061009c6105d6565b3480156101b757600080fd5b5061010e6004356105dc565b3480156101cf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061071b9650505050505050565b604080519115158252519081900360200190f35b3480156102bf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610a9a9650505050505050565b34801561039b57600080fd5b5061009c600435602435610deb565b60018054829081106103b857fe5b600091825260209091200154905081565b60606000808581805b60015481101561040e5760018054829081106103ea57fe5b600091825260209091200154831415610406576001915061040e565b6001016103d2565b811515610465576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61047661047188610e1b565b610e6e565b9550866040518082805190602001908083835b602083106104a85780518252601f199092019160209182019101610489565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209750505088861490506104e357600080fd5b6000888152600360205260408120875190955061051f9161051891899190811061050957fe5b90602001906020020151610f23565b6001610f77565b8455855161053890610518908890600490811061050957fe5b6001850155855161055490610518908890600590811061050957fe5b60028501556105638989611005565b505050505050505050565b6105766112e6565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b6000805482141561065d576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106e657600180548391908390811061067c57fe5b60009182526020909120015414156106de576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b600101610661565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b60015481101561075e57600180548290811061073a57fe5b600091825260209091200154831415610756576001915061075e565b600101610722565b8115156107b5576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b81548110156108045781818154811015156107e057fe5b6000918252602090912001548414156107fc5760019250610804565b6001016107c9565b82151561085b576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600101546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108ff5781810151838201526020016108e7565b50505050905090810190601f16801561092c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561095f578181015183820152602001610947565b50505050905090810190601f16801561098c5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156109bf5781810151838201526020016109a7565b50505050905090810190601f1680156109ec5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610a0e57600080fd5b505af4158015610a22573d6000803e3d6000fd5b505050506040513d6020811015610a3857600080fd5b50511515610a4257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f60005b60408051938452602084019290925282820152519081900360600190a15060019e9d5050505050505050505050505050565b6000808681805b600154811015610add576001805482908110610ab957fe5b600091825260209091200154831415610ad55760019150610add565b600101610aa1565b811515610b34576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b8154811015610b83578181815481101515610b5f57fe5b600091825260209091200154841415610b7b5760019250610b83565b600101610b48565b821515610bda576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600201546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610c7e578181015183820152602001610c66565b50505050905090810190601f168015610cab5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610cde578181015183820152602001610cc6565b50505050905090810190601f168015610d0b5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610d3e578181015183820152602001610d26565b50505050905090810190601f168015610d6b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610d8d57600080fd5b505af4158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b50511515610dc157fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f6001610a68565b600260205281600052604060002081815481101515610e0657fe5b90600052602060002001600091509150505481565b610e23611305565b81516000811515610e495760408051808201909152600080825260208201529250610e67565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e7a61131c565b6000610e8585611065565b1515610e9057600080fd5b610e998561108f565b925082604051908082528060200260200182016040528015610ed557816020015b610ec2611305565b815260200190600190039081610eba5790505b509350610ee1856110ff565b91505b610eed82611138565b15610f1b57610efb82611157565b8482815181101515610f0957fe5b60209081029091010152600101610ee4565b505050919050565b6020810151606090801515610f37576105af565b806040519080825280601f01601f191660200182016040528015610f65578160200160208202803883390190505b5091506105af83600001518383611199565b600080805b6020811015610ffd578060080285828601815181101515610f9957fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610f7c565b509392505050565b6000828152600260205260408120905b815481101561104d578154839083908390811061102e57fe5b600091825260209091200154141561104557600080fd5b600101611015565b50805460018101825560009182526020909120015550565b60008082602001516000141561107e57600091506105af565b5050515160c060009190911a101590565b6000806000806000806110a187611065565b15156110b057600095506110f5565b8651805160001a955093506110c4876111d9565b840192506001876020015185010391505b8183116110f1576110e583611259565b909201916001016110d5565b8095505b5050505050919050565b61110761131c565b600061111283611065565b151561111d57600080fd5b611126836111d9565b83519383529092016020820152919050565b6000611142611305565b50508051602080820151915192015191011190565b61115f611305565b60008061116b84611138565b1561007f578360200151915061118082611259565b8284526020808501829052838201908601529050610e67565b60006020601f83010484602085015b8284146111c6576020840282810151908201526001909301926111a8565b6000865160200187015250505050505050565b60008060008360200151600014156111f45760009250610e67565b50508151805160001a9060808210156112105760009250610e67565b60b882108061122b575060c0821015801561122b575060f882105b156112395760019250610e67565b60c082101561124e5760b51982019250610e67565b5060f5190192915050565b8051600090811a608081101561127257600191506105af565b60b881101561128757607e19810191506105af565b60c08110156112b057600183015160b76020839003016101000a9004810160b5190191506105af565b60f88110156112c55760be19810191506105af565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280611330611305565b81526020016000815250905600a165627a7a7230582024e7bd39ca02a13e7b30d3f8eabcff1f54aa2b2794c25da896d910015790ad590029ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075820bf9a0cf066fe78ea2e58000322d541b37763dc8d5daad8b301e63d0d2e5bdc3f2fe6ca048f44173b406c4ebd09b4f52174d00e6019820ea92f1caa5dd49d2f5652671ad -//EP TX PATH = 0x80 -//EP TX PARENT NODES = 0xf91420f9141d822080b91417f91414820c5f85174876e800836691b78080b913bd608060405234801561001057600080fd5b5060405160208061139d8339810160405251600055611369806100346000396000f30060806040526004361061007f5763ffffffff60e060020a600035041663550325b581146100845780635a0235e4146100ae5780636b4f9b9d14610110578063927a32e3146101605780639a8a0592146101965780639e43d86b146101ab578063affd8be9146101c3578063bec205b9146102b3578063fecc37c31461038f575b600080fd5b34801561009057600080fd5b5061009c6004356103aa565b60408051918252519081900360200190f35b3480156100ba57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261010e9482359460248035953695946064949201919081908401838280828437509497506103c99650505050505050565b005b34801561011c57600080fd5b5061012860043561056e565b6040518082606080838360005b8381101561014d578181015183820152602001610135565b5050505090500191505060405180910390f35b34801561016c57600080fd5b506101786004356105b5565b60408051938452602084019290925282820152519081900360600190f35b3480156101a257600080fd5b5061009c6105d6565b3480156101b757600080fd5b5061010e6004356105dc565b3480156101cf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061071b9650505050505050565b604080519115158252519081900360200190f35b3480156102bf57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261029f94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610a9a9650505050505050565b34801561039b57600080fd5b5061009c600435602435610deb565b60018054829081106103b857fe5b600091825260209091200154905081565b60606000808581805b60015481101561040e5760018054829081106103ea57fe5b600091825260209091200154831415610406576001915061040e565b6001016103d2565b811515610465576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61047661047188610e1b565b610e6e565b9550866040518082805190602001908083835b602083106104a85780518252601f199092019160209182019101610489565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209750505088861490506104e357600080fd5b6000888152600360205260408120875190955061051f9161051891899190811061050957fe5b90602001906020020151610f23565b6001610f77565b8455855161053890610518908890600490811061050957fe5b6001850155855161055490610518908890600590811061050957fe5b60028501556105638989611005565b505050505050505050565b6105766112e6565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b6000805482141561065d576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106e657600180548391908390811061067c57fe5b60009182526020909120015414156106de576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b600101610661565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b60015481101561075e57600180548290811061073a57fe5b600091825260209091200154831415610756576001915061075e565b600101610722565b8115156107b5576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b81548110156108045781818154811015156107e057fe5b6000918252602090912001548414156107fc5760019250610804565b6001016107c9565b82151561085b576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600101546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108ff5781810151838201526020016108e7565b50505050905090810190601f16801561092c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561095f578181015183820152602001610947565b50505050905090810190601f16801561098c5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156109bf5781810151838201526020016109a7565b50505050905090810190601f1680156109ec5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610a0e57600080fd5b505af4158015610a22573d6000803e3d6000fd5b505050506040513d6020811015610a3857600080fd5b50511515610a4257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f60005b60408051938452602084019290925282820152519081900360600190a15060019e9d5050505050505050505050505050565b6000808681805b600154811015610add576001805482908110610ab957fe5b600091825260209091200154831415610ad55760019150610add565b600101610aa1565b811515610b34576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a81526002602052604081208b918b91815b8154811015610b83578181815481101515610b5f57fe5b600091825260209091200154841415610b7b5760019250610b83565b600101610b48565b821515610bda576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f6000191660001916815260200190815260200160002098507338800a01ecf096d73c62878ac8e183bfe92cd82d634f7142ad8e8e8e8d600201546040518563ffffffff1660e060020a028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610c7e578181015183820152602001610c66565b50505050905090810190601f168015610cab5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610cde578181015183820152602001610cc6565b50505050905090810190601f168015610d0b5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610d3e578181015183820152602001610d26565b50505050905090810190601f168015610d6b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610d8d57600080fd5b505af4158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b50511515610dc157fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468f8f6001610a68565b600260205281600052604060002081815481101515610e0657fe5b90600052602060002001600091509150505481565b610e23611305565b81516000811515610e495760408051808201909152600080825260208201529250610e67565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e7a61131c565b6000610e8585611065565b1515610e9057600080fd5b610e998561108f565b925082604051908082528060200260200182016040528015610ed557816020015b610ec2611305565b815260200190600190039081610eba5790505b509350610ee1856110ff565b91505b610eed82611138565b15610f1b57610efb82611157565b8482815181101515610f0957fe5b60209081029091010152600101610ee4565b505050919050565b6020810151606090801515610f37576105af565b806040519080825280601f01601f191660200182016040528015610f65578160200160208202803883390190505b5091506105af83600001518383611199565b600080805b6020811015610ffd578060080285828601815181101515610f9957fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610f7c565b509392505050565b6000828152600260205260408120905b815481101561104d578154839083908390811061102e57fe5b600091825260209091200154141561104557600080fd5b600101611015565b50805460018101825560009182526020909120015550565b60008082602001516000141561107e57600091506105af565b5050515160c060009190911a101590565b6000806000806000806110a187611065565b15156110b057600095506110f5565b8651805160001a955093506110c4876111d9565b840192506001876020015185010391505b8183116110f1576110e583611259565b909201916001016110d5565b8095505b5050505050919050565b61110761131c565b600061111283611065565b151561111d57600080fd5b611126836111d9565b83519383529092016020820152919050565b6000611142611305565b50508051602080820151915192015191011190565b61115f611305565b60008061116b84611138565b1561007f578360200151915061118082611259565b8284526020808501829052838201908601529050610e67565b60006020601f83010484602085015b8284146111c6576020840282810151908201526001909301926111a8565b6000865160200187015250505050505050565b60008060008360200151600014156111f45760009250610e67565b50508151805160001a9060808210156112105760009250610e67565b60b882108061122b575060c0821015801561122b575060f882105b156112395760019250610e67565b60c082101561124e5760b51982019250610e67565b5060f5190192915050565b8051600090811a608081101561127257600191506105af565b60b881101561128757607e19810191506105af565b60c08110156112b057600183015160b76020839003016101000a9004810160b5190191506105af565b60f88110156112c55760be19810191506105af565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280611330611305565b81526020016000815250905600a165627a7a7230582024e7bd39ca02a13e7b30d3f8eabcff1f54aa2b2794c25da896d910015790ad590029ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075820bf9a0cf066fe78ea2e58000322d541b37763dc8d5daad8b301e63d0d2e5bdc3f2fe6ca048f44173b406c4ebd09b4f52174d00e6019820ea92f1caa5dd49d2f5652671ad -//PATH = 0x80 -//RLP ENCODED NODE = 0xf90112822080b9010cf901090183154958b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0 -//HASHED NODE = 0x6fc7cc2a8c59c0e2c84fe806d652e636d1a513b9c3cefbe0b53920c5787a1e2c -//EXTENSION NODE WITH PATHPTR = 2 -//EP RECEIPT VALUE = 0xf901090183154958b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0 -//EP RECEIPT PATH = 0x80 -//EP RECEIPT PARENT NODES = 0xf90115f90112822080b9010cf901090183154958b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0 - contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); @@ -168,30 +131,6 @@ contract('Ion.js', (accounts) => { await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); }) -// it('Check Infura Proofs', async () => { -// -// var eP = new EP(new Web3.providers.HttpProvider("https://gmainnet.infura.io")); -// -// -// var txValue; -// var txPath; -// var txParentNodes; -// await eP.getTransactionProof("0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893").then( (proof) => { -// verified = EP.transaction(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); -// assert(verified); -// -// txValue = rlp.encode(proof.value); -// txPath = rlp.encode(proof.path); -// txParentNodes = rlp.encode(proof.parentNodes); -// }) -// -// -// console.log("EP TX VALUE = 0x" + txValue.toString('hex')); -// console.log("EP TX PATH = 0x" + txPath.toString('hex')); -// console.log("EP TX PARENT NODES = 0x" + txParentNodes.toString('hex')); -// -// }) - it('Fail Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); @@ -209,32 +148,6 @@ contract('Ion.js', (accounts) => { await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, "0xff").should.be.rejected; }) -// it('Check EP Receipt Proofs', async () => { -// -// var eP = new EP(new Web3.providers.HttpProvider("https://gmainnet.infura.io")); -// -// await eP.getReceiptTrieRoot("0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893").then( (root) => { -// console.log("EP Root hash = 0x" + root.toString('hex')) -// }) -// -// var txValue; -// var txPath; -// var txParentNodes; -// await eP.getReceiptProof("0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893").then( (proof) => { -// verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); -// assert(verified); -// -// txValue = rlp.encode(proof.value); -// txPath = proof.path; -// txParentNodes = rlp.encode(proof.parentNodes); -// }) -// -// console.log("EP RECEIPT VALUE = 0x" + txValue.toString('hex')); -// console.log("EP RECEIPT PATH = 0x" + txPath.toString('hex')); -// console.log("EP RECEIPT PARENT NODES = 0x" + txParentNodes.toString('hex')); -// -// }) - it('Check Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); @@ -245,15 +158,50 @@ contract('Ion.js', (accounts) => { await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH); }) - it('Fail Receipt Proof', () => { + it('Fail Receipt Proof', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await ion.CheckReceiptProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; + // Fail with wrong block hash + await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; + + // Fail with wrong path + await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, "0xff").should.be.rejected; }) - it('Check Roots Proof', () => { + it('Check Roots Proof', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); }) - it('Fail Roots Proof', () => { + it('Fail Roots Proof', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID); + + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await ion.CheckRootsProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected + + // Fail with wrong block hash + await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; + + // Fail with wrong tx nodes + await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_NODES).should.be.rejected; + // Fail with wrong receipt nodes + await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; }) }) diff --git a/tooling/encoder.py b/tooling/encoder.py index 926136a..d9c9711 100644 --- a/tooling/encoder.py +++ b/tooling/encoder.py @@ -2,6 +2,7 @@ from .ethrpc import EthJsonRpc from ethereum.utils import sha3 from .utils import require +import click class Block(object): def __init__(self, block_json): @@ -52,7 +53,11 @@ def hexstring_to_bytes(hex): return int(hex, 16) class RLPEncoder(object): - def __init__(self, host, port, tls=False): + def __init__(self, host, port): + if port == 443: + tls = True + else: + tls = False self.rpc = EthJsonRpc(host, port, tls) def get_block_by_number(self, n): @@ -83,4 +88,42 @@ def hash_block_header(self, block): hash = sha3(encoded).hex() require('0x'+hash == block['hash'], "Block hash and hashed header do not match:\n{} expected\n{} acquired".format(block['hash'], '0x'+hash)) - return hash \ No newline at end of file + return hash + + + +@click.command(help="Returns an RLP encoded block in hexadecimal format.") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.argument('number', nargs=1, type=int) +def get_encoded_block(rpc_host, rpc_port, number): + rlp_encoder = RLPEncoder(rpc_host, rpc_port) + block = rlp_encoder.get_block(number) + click.echo('0x'+rlp_encoder.encode_block(block).hex()) + +@click.command(help="Returns block hash in hexadecimal format.") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.argument('number', nargs=1, type=int) +def get_block_hash(rpc_host, rpc_port, number): + rlp_encoder = RLPEncoder(rpc_host, rpc_port) + block = rlp_encoder.get_block(number) + click.echo('0x'+rlp_encoder.hash_block_header(block)) + + +@click.command(help="Returns a list of transaction hashes from a specified block") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.argument('number', nargs=1, type=int) +def get_block_transactions(rpc_host, rpc_port, number): + rlp_encoder = RLPEncoder(rpc_host, rpc_port) + block = rlp_encoder.get_block(number) + click.echo(rlp_encoder.get_transactions(block)) + +commands = click.Group('commands') +commands.add_command(get_encoded_block, "encodeblock") +commands.add_command(get_block_hash, "blockhash") +commands.add_command(get_block_transactions, "gettx") + +if __name__ == "__main__": + commands.main() \ No newline at end of file From 4de672761cf274029f18f49124f930270ae51984 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 13 Jul 2018 17:40:07 +0100 Subject: [PATCH 059/203] Added gas consumption logging to relevant tests --- test/ion.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/ion.js b/test/ion.js index 1eec0fd..ca2b5a4 100644 --- a/test/ion.js +++ b/test/ion.js @@ -88,7 +88,9 @@ contract('Ion.js', (accounts) => { await ion.RegisterChain(TESTCHAINID); // Submit block should succeed - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) + let tx = await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) + + console.log("Gas used to submit block header = " + tx.receipt.gasUsed.toString() + " gas"); let blockHash = await ion.m_blockhashes(TESTCHAINID, 0); let header = await ion.getBlockHeader.call(blockHash); @@ -128,7 +130,9 @@ contract('Ion.js', (accounts) => { await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); - await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); + let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); + + console.log("Gas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); }) it('Fail Tx Proof', async () => { @@ -155,7 +159,9 @@ contract('Ion.js', (accounts) => { await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); - await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH); + let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH); + + console.log("Gas used to submit check receipt proof = " + tx.receipt.gasUsed.toString() + " gas"); }) it('Fail Receipt Proof', async () => { @@ -182,7 +188,9 @@ contract('Ion.js', (accounts) => { await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); - await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); + let tx = await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); + + console.log("Gas used to submit check roots proof = " + tx.receipt.gasUsed.toString() + " gas"); }) it('Fail Roots Proof', async () => { From 3968ea3ad778793e207ce18685cac2c8da9fda8f Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 17 Jul 2018 15:26:34 +0100 Subject: [PATCH 060/203] Ion test works with live testrpc --- abi/ECVerify.abi | 1 + abi/ECVerify.bin | 1 + abi/Ion.abi | 1 + abi/Ion.bin | 1 + abi/PatriciaTrie.abi | 1 + abi/PatriciaTrie.bin | 1 + abi/RLP.abi | 1 + abi/RLP.bin | 1 + abi/SolUtils.abi | 1 + abi/SolUtils.bin | 1 + abi/Validation.abi | 1 + abi/Validation.bin | 1 + ion-cli/contracts/ion.go | 555 ++++++++++++++++++++++++++++++++++ ion-cli/contracts/ion_test.go | 49 +++ 14 files changed, 616 insertions(+) create mode 100644 abi/ECVerify.abi create mode 100644 abi/ECVerify.bin create mode 100644 abi/Ion.abi create mode 100644 abi/Ion.bin create mode 100644 abi/PatriciaTrie.abi create mode 100644 abi/PatriciaTrie.bin create mode 100644 abi/RLP.abi create mode 100644 abi/RLP.bin create mode 100644 abi/SolUtils.abi create mode 100644 abi/SolUtils.bin create mode 100644 abi/Validation.abi create mode 100644 abi/Validation.bin create mode 100644 ion-cli/contracts/ion.go create mode 100644 ion-cli/contracts/ion_test.go diff --git a/abi/ECVerify.abi b/abi/ECVerify.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/abi/ECVerify.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/abi/ECVerify.bin b/abi/ECVerify.bin new file mode 100644 index 0000000..65f0298 --- /dev/null +++ b/abi/ECVerify.bin @@ -0,0 +1 @@ +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a723058209b042e675a498ff3065c231b18babe7c1eda6630c62a5b46cf1b1e2d2f16a9590029 \ No newline at end of file diff --git a/abi/Ion.abi b/abi/Ion.abi new file mode 100644 index 0000000..a70cf5d --- /dev/null +++ b/abi/Ion.abi @@ -0,0 +1 @@ +[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"chains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CheckReceiptProof","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_blockHash","type":"bytes32"}],"name":"getBlockHeader","outputs":[{"name":"","type":"bytes32[3]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"CheckRootsProof","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"VerifiedTxProof","type":"event"}] \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin new file mode 100644 index 0000000..ce7bd09 --- /dev/null +++ b/abi/Ion.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50604051602080611487833981018060405281019080805190602001909291905050508060008160001916905550506114398061004e6000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063550325b5146100a957806359349832146100f25780635a0235e4146101095780636b4f9b9d1461018e578063927a32e3146101fb5780639a8a0592146102665780639e43d86b14610299578063affd8be9146102ca578063e318df54146103f3578063fecc37c31461040a575b600080fd5b3480156100b557600080fd5b506100d460048036038101908080359060200190929190505050610461565b60405180826000191660001916815260200191505060405180910390f35b3480156100fe57600080fd5b50610107610484565b005b34801561011557600080fd5b5061018c60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610486565b005b34801561019a57600080fd5b506101bd60048036038101908080356000191690602001909291905050506106be565b6040518082600360200280838360005b838110156101e85780820151818401526020810190506101cd565b5050505090500191505060405180910390f35b34801561020757600080fd5b5061022a600480360381019080803560001916906020019092919050505061072d565b60405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b34801561027257600080fd5b5061027b610757565b60405180826000191660001916815260200191505060405180910390f35b3480156102a557600080fd5b506102c8600480360381019080803560001916906020019092919050505061075d565b005b3480156102d657600080fd5b506103d960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108f4565b604051808215151515815260200191505060405180910390f35b3480156103ff57600080fd5b50610408610d83565b005b34801561041657600080fd5b50610443600480360381019080803560001916906020019092919080359060200190929190505050610d85565b60405180826000191660001916815260200191505060405180910390f35b60018181548110151561047057fe5b906000526020600020016000915090505481565b565b60606000808560008060009150600090505b6001805490508110156104e4576001818154811015156104b457fe5b906000526020600020015460001916836000191614156104d757600191506104e4565b8080600101915050610498565b811515610559576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61056a61056588610db5565b610e10565b9550866040518082805190602001908083835b6020831015156105a2578051825260208201915060208101905060208303925061057d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209450876000191685600019161415156105e757600080fd5b600360008960001916600019168152602001908152602001600020935061062f61062887600081518110151561061957fe5b90602001906020020151610ecd565b6001610f32565b84600001816000191690555061066661065f87600481518110151561065057fe5b90602001906020020151610ecd565b6001610f32565b84600101816000191690555061069d61069687600581518110151561068757fe5b90602001906020020151610ecd565b6001610f32565b8460020181600019169055506106b38989611010565b505050505050505050565b6106c6611395565b6000600360008460001916600019168152602001908152602001600020905060606040519081016040528082600001546000191660001916815260200182600101546000191660001916815260200182600201546000191660001916815250915050919050565b60036020528060005260406000206000915090508060000154908060010154908060020154905083565b60005481565b6000805460001916826000191614151515610806576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600090505b6001805490508110156108be57816000191660018281548110151561082c57fe5b906000526020600020015460001916141515156108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b808060010191505061080b565b60018290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055505050565b6000808660008060009150600090505b6001805490508110156109505760018181548110151561092057fe5b906000526020600020015460001916836000191614156109435760019150610950565b8080600101915050610904565b8115156109c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8989600060606000809250600260008660001916600019168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610a3957602002820191906000526020600020905b81546000191681526020019060010190808311610a21575b50505050509150600090505b8151811015610a8b578181815181101515610a5c57fe5b906020019060200201516000191684600019161415610a7e5760019250610a8b565b8080600101915050610a45565b821515610b00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600360008f60001916600019168152602001908152602001600020985073__./contracts/libraries/PatriciaTrie.s__634f7142ad8e8e8e8d600101546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610bc0578082015181840152602081019050610ba5565b50505050905090810190601f168015610bed5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610c26578082015181840152602081019050610c0b565b50505050905090810190601f168015610c535780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610c8c578082015181840152602081019050610c71565b50505050905090810190601f168015610cb95780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610cdb57600080fd5b505af4158015610cef573d6000803e3d6000fd5b505050506040513d6020811015610d0557600080fd5b81019080805190602001909291905050501515610d1e57fe5b7f202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a18f8f60405180836000191660001916815260200182600019166000191681526020019250505060405180910390a16001995050505050505050505095945050505050565b565b600260205281600052604060002081815481101515610da057fe5b90600052602060002001600091509150505481565b610dbd6113b8565b600080835191506000821415610deb5760408051908101604052806000815260200160008152509250610e09565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e1c6113d2565b6000610e27856110b4565b1515610e3257600080fd5b610e3b856110e6565b925082604051908082528060200260200182016040528015610e7757816020015b610e646113f3565b815260200190600190039081610e5c5790505b509350610e8385611160565b91505b610e8f826111a8565b15610ec557610e9d826111d2565b8482815181101515610eab57fe5b906020019060200201819052508080600101915050610e86565b505050919050565b60606000826020015190506000811415610ee657610f2c565b806040519080825280601f01601f191660200182016040528015610f195781602001602082028038833980820191505090505b509150610f2b8360000151838361122e565b5b50919050565b60008060008090505b6020811015611005576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610f7c57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610f3b565b819250505092915050565b6000806002600085600019166000191681526020019081526020016000209150600090505b818054905081101561107d578260001916828281548110151561105457fe5b9060005260206000200154600019161415151561107057600080fd5b8080600101915050611035565b8183908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555050505050565b6000806000836020015114156110cd57600091506110e0565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806110f8876110b4565b15156111075760009550611156565b86600001519350835160001a945061111e8761126f565b840192506001876020015185010391505b818311151561115257611141836112fb565b83019250808060010191505061112f565b8095505b5050505050919050565b6111686113d2565b6000611173836110b4565b151561117e57600080fd5b6111878361126f565b83600001510190508282600001819052508082602001818152505050919050565b60006111b26113b8565b826000015190508060200151816000015101836020015110915050919050565b6111da6113b8565b6000806111e6846111a8565b1561122257836020015191506111fb826112fb565b90508183600001818152505080836020018181525050808201846020018181525050611227565b600080fd5b5050919050565b60006020601f83010484602085015b82841461125c576020840280830151818301526001850194505061123d565b6000865160200187015250505050505050565b6000806000808460200151141561128957600092506112f4565b83600001519050805160001a915060808210156112a957600092506112f4565b60b88210806112c5575060c082101580156112c4575060f882105b5b156112d357600192506112f4565b60c08210156112ea57600160b783030192506112f4565b600160f783030192505b5050919050565b600080825160001a90506080811015611317576001915061138f565b60b881101561132e5760016080820301915061138e565b60c08110156113585760b78103806020036101000a6001850151048082016001019350505061138d565b60f881101561136f57600160c0820301915061138c565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b606060405190810160405280600390602082028038833980820191505090505090565b604080519081016040528060008152602001600081525090565b6060604051908101604052806113e66113f3565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582092fe2217ce4fc7e2c1df216da8d39cd9ccf25c15d607088915e2dede2778065d0029 \ No newline at end of file diff --git a/abi/PatriciaTrie.abi b/abi/PatriciaTrie.abi new file mode 100644 index 0000000..faa17e8 --- /dev/null +++ b/abi/PatriciaTrie.abi @@ -0,0 +1 @@ +[{"constant":true,"inputs":[{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"},{"name":"_root","type":"bytes32"}],"name":"verifyProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/abi/PatriciaTrie.bin b/abi/PatriciaTrie.bin new file mode 100644 index 0000000..6e3af0a --- /dev/null +++ b/abi/PatriciaTrie.bin @@ -0,0 +1 @@ +611278610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634f7142ad1461005d575b600080fd5b610151600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803560001916906020019092919050505061016b565b604051808215151515815260200191505060405180910390f35b60006101756111d5565b606060006060806000606060008060608061018f8f61060f565b9a5061019a8b61066a565b99508c9850600095506101ae8e6000610727565b9450600093505b89518410156105fb576101de8a858151811015156101cf57fe5b90602001906020020151610ad7565b9750876040518082805190602001908083835b60208310151561021657805182526020820191506020810190506020830392506101f1565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916896000191614151561025c5760009b506105fc565b61027c8a8581518110151561026d57fe5b9060200190602002015161066a565b9650601187511415610446578451861415610397578f6040518082805190602001908083835b6020831015156102c757805182526020820191506020810190506020830392506102a2565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661031988601081518110151561030a57fe5b90602001906020020151610ad7565b6040518082805190602001908083835b60208310151561034e5780518252602082019150602081019050602083039250610329565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141561038e5760019b506105fc565b60009b506105fc565b84868151811015156103a557fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250610439878461ffff1681518110151561042a57fe5b90602001906020020151610b3c565b98506001860195506105ee565b6002875114156105e45761047187600081518110151561046257fe5b90602001906020020151610b51565b915061047e826001610727565b51860195508451861415610592578f6040518082805190602001908083835b6020831015156104c2578051825260208201915060208101905060208303925061049d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661051488600181518110151561050557fe5b90602001906020020151610b51565b6040518082805190602001908083835b6020831015156105495780518252602082019150602081019050602083039250610524565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614156105895760019b506105fc565b60009b506105fc565b600061059f836001610727565b5114156105af5760009b506105fc565b6105d08760018151811015156105c157fe5b90602001906020020151610b51565b90506105dd816000610bc3565b98506105ed565b60009b506105fc565b5b83806001019450506101b5565b5b5050505050505050505050949350505050565b6106176111d5565b6000808351915060008214156106455760408051908101604052806000815260200160008152509250610663565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006106766111ef565b600061068185610ca1565b151561068c57600080fd5b61069585610cd3565b9250826040519080825280602002602001820160405280156106d157816020015b6106be611210565b8152602001906001900390816106b65790505b5093506106dd85610d4d565b91505b6106e982610d95565b1561071f576106f782610dbf565b848281518110151561070557fe5b9060200190602002018190525080806001019150506106e0565b505050919050565b60608060008061073561122a565b6060600060ff6040519080825280601f01601f19166020018201604052801561076d5781602001602082028038833980820191505090505b50955060009450600093505b88518410156109db576107e3898581518110151561079357fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002610e1b565b92508780156107f25750600084145b1561091a5760017f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561082a57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108b4575060037f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561088b57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b15610915578260016002811015156108c857fe5b6020020151868660ff168151811015156108de57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001850194505b6109ce565b82600060028110151561092957fe5b6020020151868660ff1681518110151561093f57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535082600160028110151561097e57fe5b6020020151866001870160ff1681518110151561099757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506002850194505b8380600101945050610779565b8460ff166040519080825280601f01601f191660200182016040528015610a115781602001602082028038833980820191505090505b509150600090505b8460ff16811015610ac8578581815181101515610a3257fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028282815181101515610a8b57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050610a19565b81965050505050505092915050565b60606000826020015190506000811415610af057610b36565b806040519080825280601f01601f191660200182016040528015610b235781602001602082028038833980820191505090505b509150610b3583600001518383610f01565b5b50919050565b6000610b4782610f42565b6001029050919050565b6060600080610b5f84610f99565b1515610b6a57600080fd5b610b7384610fca565b8092508193505050806040519080825280601f01601f191660200182016040528015610bae5781602001602082028038833980820191505090505b509250610bbc828483610f01565b5050919050565b60008060008090505b6020811015610c96576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610c0d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610bcc565b819250505092915050565b600080600083602001511415610cba5760009150610ccd565b8260000151905060c0815160001a101591505b50919050565b600080600080600080610ce587610ca1565b1515610cf45760009550610d43565b86600001519350835160001a9450610d0b8761104b565b840192506001876020015185010391505b8183111515610d3f57610d2e836110d7565b830192508080600101915050610d1c565b8095505b5050505050919050565b610d556111ef565b6000610d6083610ca1565b1515610d6b57600080fd5b610d748361104b565b83600001510190508282600001819052508082602001818152505050919050565b6000610d9f6111d5565b826000015190508060200151816000015101836020015110915050919050565b610dc76111d5565b600080610dd384610d95565b15610e0f5783602001519150610de8826110d7565b90508183600001818152505080836020018181525050808201846020018181525050610e14565b600080fd5b5050919050565b610e2361122a565b600080610e31846004611171565b9150600f7f010000000000000000000000000000000000000000000000000000000000000002841690506040805190810160405280837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525092505050919050565b60006020601f83010484602085015b828414610f2f5760208402808301518183015260018501945050610f10565b6000865160200187015250505050505050565b6000806000610f5084610f99565b1515610f5b57600080fd5b610f6484610fca565b80925081935050506020811180610f7b5750600081145b15610f8557600080fd5b806020036101000a82510492505050919050565b600080600083602001511415610fb25760009150610fc4565b8260000151905060c0815160001a1091505b50919050565b6000806000806000610fdb86610f99565b1515610fe657600080fd5b85600001519150815160001a925060808310156110095781945060019350611043565b60b88310156110275760018660200151039350600182019450611042565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b6000806000808460200151141561106557600092506110d0565b83600001519050805160001a9150608082101561108557600092506110d0565b60b88210806110a1575060c082101580156110a0575060f882105b5b156110af57600192506110d0565b60c08210156110c657600160b783030192506110d0565b600160f783030192505b5050919050565b600080825160001a905060808110156110f3576001915061116b565b60b881101561110a5760016080820301915061116a565b60c08110156111345760b78103806020036101000a60018501510480820160010193505050611169565b60f881101561114b57600160c08203019150611168565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008160020a60ff16837f0100000000000000000000000000000000000000000000000000000000000000900460ff168115156111aa57fe5b047f010000000000000000000000000000000000000000000000000000000000000002905092915050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611203611210565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a7230582052aab7d1b534145ff43213168b77a7d3fc197b4648313c3c59c0b3f6cdee0bc00029 \ No newline at end of file diff --git a/abi/RLP.abi b/abi/RLP.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/abi/RLP.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/abi/RLP.bin b/abi/RLP.bin new file mode 100644 index 0000000..bdc910d --- /dev/null +++ b/abi/RLP.bin @@ -0,0 +1 @@ +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820ce6cdb517493eee375e351c5f859db8319a6325d15ad79211273ad6e375c0d6c0029 \ No newline at end of file diff --git a/abi/SolUtils.abi b/abi/SolUtils.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/abi/SolUtils.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/abi/SolUtils.bin b/abi/SolUtils.bin new file mode 100644 index 0000000..6a48b5e --- /dev/null +++ b/abi/SolUtils.bin @@ -0,0 +1 @@ +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a7230582076e5542a798eb77cf57188cde0bca45312e3955489de3675f7d6df18930bf9b20029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi new file mode 100644 index 0000000..41ce549 --- /dev/null +++ b/abi/Validation.abi @@ -0,0 +1 @@ +[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"validators","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"blockNumber","type":"uint256"}],"name":"GetBlock","outputs":[{"name":"_blockHash","type":"bytes32"},{"name":"_prevBlockHash","type":"bytes32"},{"name":"_blockHeight","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"m_blockheaders","outputs":[{"name":"blockHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genesisHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes"}],"name":"broadcastHash2","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin new file mode 100644 index 0000000..84a4712 --- /dev/null +++ b/abi/Validation.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50604051610ca4380380610ca483398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816003816000191690555081600460008081526020019081526020016000206000018160001916905550505050610adf806101c56000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806335aa2e441461007d57806340ce4b6c146100ea5780639db7d9f714610149578063aae933e41461017c578063c4cf3ed614610271578063d405af3d146102c9575b600080fd5b34801561008957600080fd5b506100a860048036038101908080359060200190929190505050610335565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100f657600080fd5b5061011560048036038101908080359060200190929190505050610373565b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390f35b34801561015557600080fd5b5061015e6103b6565b60405180826000191660001916815260200191505060405180910390f35b34801561018857600080fd5b5061026f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506103c0565b005b34801561027d57600080fd5b5061029c60048036038101908080359060200190929190505050610857565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b3480156102d557600080fd5b506102de61087b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610321578082015181840152602081019050610306565b505050509050019250505060405180910390f35b60018181548110151561034457fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000600460008581526020019081526020016000206000015492506004600085815260200190815260200160002060010154915060025490509193909250565b6000600354905090565b600080600060608060608060606000806103db8d6004610909565b9950600354600019168a6000191614151561045e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b8c5198508c6040518082805190602001908083835b6020831015156104985780518252602082019150602081019050602083039250610473565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561053c5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105735781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156105aa5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156105e15781602001602082028038833980820191505090505b5093506105f0878e600061091d565b600260218801600260208f016004610bb8fa50610611868e608c8c0361091d565b600160208701600160208e016004610bb8fa50610632848e602a8c0361091d565b61063d87878661093f565b9250826040518082805190602001908083835b6020831015156106755780518252602082019150602081019050602083039250610650565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506106b2858e606b8c0361091d565b6106bc82866109eb565b905060011515600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515610786576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b87600381600019169055506002600081548092919060010191905055508760046000600254815260200190815260200160002060000181600019169055508960046000600254815260200190815260200160002060010181600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050505050505050505050565b60046020528060005260406000206000915090508060000154908060010154905082565b606060018054806020026020016040519081016040528092919081815260200182805480156108ff57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116108b5575b5050505050905090565b600060208201915081830151905092915050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109a65781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a0157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a2c57601b810190505b601b8160ff161480610a415750601c8160ff16145b1515610a4c57600080fd5b610a5886828585610a63565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610aa657600080fd5b80925050509493505050505600a165627a7a72305820cf83fdc91c1477a7ff4a9251338903b37b04c10ccb8538af298dd16fece5a0ba0029 \ No newline at end of file diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go new file mode 100644 index 0000000..bcadb9b --- /dev/null +++ b/ion-cli/contracts/ion.go @@ -0,0 +1,555 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contract + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// IonABI is the input ABI used to generate the binding from. +const IonABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"chains\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"CheckReceiptProof\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_rlpBlockHeader\",\"type\":\"bytes\"}],\"name\":\"SubmitBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockHash\",\"type\":\"bytes32\"}],\"name\":\"getBlockHeader\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[3]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"txRootHash\",\"type\":\"bytes32\"},{\"name\":\"receiptRootHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"}],\"name\":\"RegisterChain\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"}],\"name\":\"CheckTxProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"CheckRootsProof\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"m_blockhashes\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"chainId\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"VerifiedTxProof\",\"type\":\"event\"}]" + +// IonBin is the compiled bytecode used for deploying new contracts. +const IonBin = `608060405234801561001057600080fd5b50604051602080611487833981018060405281019080805190602001909291905050508060008160001916905550506114398061004e6000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063550325b5146100a957806359349832146100f25780635a0235e4146101095780636b4f9b9d1461018e578063927a32e3146101fb5780639a8a0592146102665780639e43d86b14610299578063affd8be9146102ca578063e318df54146103f3578063fecc37c31461040a575b600080fd5b3480156100b557600080fd5b506100d460048036038101908080359060200190929190505050610461565b60405180826000191660001916815260200191505060405180910390f35b3480156100fe57600080fd5b50610107610484565b005b34801561011557600080fd5b5061018c60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610486565b005b34801561019a57600080fd5b506101bd60048036038101908080356000191690602001909291905050506106be565b6040518082600360200280838360005b838110156101e85780820151818401526020810190506101cd565b5050505090500191505060405180910390f35b34801561020757600080fd5b5061022a600480360381019080803560001916906020019092919050505061072d565b60405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b34801561027257600080fd5b5061027b610757565b60405180826000191660001916815260200191505060405180910390f35b3480156102a557600080fd5b506102c8600480360381019080803560001916906020019092919050505061075d565b005b3480156102d657600080fd5b506103d960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108f4565b604051808215151515815260200191505060405180910390f35b3480156103ff57600080fd5b50610408610d83565b005b34801561041657600080fd5b50610443600480360381019080803560001916906020019092919080359060200190929190505050610d85565b60405180826000191660001916815260200191505060405180910390f35b60018181548110151561047057fe5b906000526020600020016000915090505481565b565b60606000808560008060009150600090505b6001805490508110156104e4576001818154811015156104b457fe5b906000526020600020015460001916836000191614156104d757600191506104e4565b8080600101915050610498565b811515610559576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61056a61056588610db5565b610e10565b9550866040518082805190602001908083835b6020831015156105a2578051825260208201915060208101905060208303925061057d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209450876000191685600019161415156105e757600080fd5b600360008960001916600019168152602001908152602001600020935061062f61062887600081518110151561061957fe5b90602001906020020151610ecd565b6001610f32565b84600001816000191690555061066661065f87600481518110151561065057fe5b90602001906020020151610ecd565b6001610f32565b84600101816000191690555061069d61069687600581518110151561068757fe5b90602001906020020151610ecd565b6001610f32565b8460020181600019169055506106b38989611010565b505050505050505050565b6106c6611395565b6000600360008460001916600019168152602001908152602001600020905060606040519081016040528082600001546000191660001916815260200182600101546000191660001916815260200182600201546000191660001916815250915050919050565b60036020528060005260406000206000915090508060000154908060010154908060020154905083565b60005481565b6000805460001916826000191614151515610806576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600090505b6001805490508110156108be57816000191660018281548110151561082c57fe5b906000526020600020015460001916141515156108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b808060010191505061080b565b60018290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055505050565b6000808660008060009150600090505b6001805490508110156109505760018181548110151561092057fe5b906000526020600020015460001916836000191614156109435760019150610950565b8080600101915050610904565b8115156109c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8989600060606000809250600260008660001916600019168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610a3957602002820191906000526020600020905b81546000191681526020019060010190808311610a21575b50505050509150600090505b8151811015610a8b578181815181101515610a5c57fe5b906020019060200201516000191684600019161415610a7e5760019250610a8b565b8080600101915050610a45565b821515610b00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600360008f60001916600019168152602001908152602001600020985073__./contracts/libraries/PatriciaTrie.s__634f7142ad8e8e8e8d600101546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610bc0578082015181840152602081019050610ba5565b50505050905090810190601f168015610bed5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610c26578082015181840152602081019050610c0b565b50505050905090810190601f168015610c535780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610c8c578082015181840152602081019050610c71565b50505050905090810190601f168015610cb95780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610cdb57600080fd5b505af4158015610cef573d6000803e3d6000fd5b505050506040513d6020811015610d0557600080fd5b81019080805190602001909291905050501515610d1e57fe5b7f202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a18f8f60405180836000191660001916815260200182600019166000191681526020019250505060405180910390a16001995050505050505050505095945050505050565b565b600260205281600052604060002081815481101515610da057fe5b90600052602060002001600091509150505481565b610dbd6113b8565b600080835191506000821415610deb5760408051908101604052806000815260200160008152509250610e09565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e1c6113d2565b6000610e27856110b4565b1515610e3257600080fd5b610e3b856110e6565b925082604051908082528060200260200182016040528015610e7757816020015b610e646113f3565b815260200190600190039081610e5c5790505b509350610e8385611160565b91505b610e8f826111a8565b15610ec557610e9d826111d2565b8482815181101515610eab57fe5b906020019060200201819052508080600101915050610e86565b505050919050565b60606000826020015190506000811415610ee657610f2c565b806040519080825280601f01601f191660200182016040528015610f195781602001602082028038833980820191505090505b509150610f2b8360000151838361122e565b5b50919050565b60008060008090505b6020811015611005576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610f7c57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610f3b565b819250505092915050565b6000806002600085600019166000191681526020019081526020016000209150600090505b818054905081101561107d578260001916828281548110151561105457fe5b9060005260206000200154600019161415151561107057600080fd5b8080600101915050611035565b8183908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555050505050565b6000806000836020015114156110cd57600091506110e0565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806110f8876110b4565b15156111075760009550611156565b86600001519350835160001a945061111e8761126f565b840192506001876020015185010391505b818311151561115257611141836112fb565b83019250808060010191505061112f565b8095505b5050505050919050565b6111686113d2565b6000611173836110b4565b151561117e57600080fd5b6111878361126f565b83600001510190508282600001819052508082602001818152505050919050565b60006111b26113b8565b826000015190508060200151816000015101836020015110915050919050565b6111da6113b8565b6000806111e6846111a8565b1561122257836020015191506111fb826112fb565b90508183600001818152505080836020018181525050808201846020018181525050611227565b600080fd5b5050919050565b60006020601f83010484602085015b82841461125c576020840280830151818301526001850194505061123d565b6000865160200187015250505050505050565b6000806000808460200151141561128957600092506112f4565b83600001519050805160001a915060808210156112a957600092506112f4565b60b88210806112c5575060c082101580156112c4575060f882105b5b156112d357600192506112f4565b60c08210156112ea57600160b783030192506112f4565b600160f783030192505b5050919050565b600080825160001a90506080811015611317576001915061138f565b60b881101561132e5760016080820301915061138e565b60c08110156113585760b78103806020036101000a6001850151048082016001019350505061138d565b60f881101561136f57600160c0820301915061138c565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b606060405190810160405280600390602082028038833980820191505090505090565b604080519081016040528060008152602001600081525090565b6060604051908101604052806113e66113f3565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582092fe2217ce4fc7e2c1df216da8d39cd9ccf25c15d607088915e2dede2778065d0029` + +// DeployIon deploys a new Ethereum contract, binding an instance of Ion to it. +func DeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte) (common.Address, *types.Transaction, *Ion, error) { + parsed, err := abi.JSON(strings.NewReader(IonABI)) + if err != nil { + return common.Address{}, nil, nil, err + } + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(IonBin), backend, _id) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil +} + +// Ion is an auto generated Go binding around an Ethereum contract. +type Ion struct { + IonCaller // Read-only binding to the contract + IonTransactor // Write-only binding to the contract + IonFilterer // Log filterer for contract events +} + +// IonCaller is an auto generated read-only Go binding around an Ethereum contract. +type IonCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IonTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IonTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IonFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IonFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IonSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IonSession struct { + Contract *Ion // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IonCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IonCallerSession struct { + Contract *IonCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IonTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IonTransactorSession struct { + Contract *IonTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IonRaw is an auto generated low-level Go binding around an Ethereum contract. +type IonRaw struct { + Contract *Ion // Generic contract binding to access the raw methods on +} + +// IonCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IonCallerRaw struct { + Contract *IonCaller // Generic read-only contract binding to access the raw methods on +} + +// IonTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IonTransactorRaw struct { + Contract *IonTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIon creates a new instance of Ion, bound to a specific deployed contract. +func NewIon(address common.Address, backend bind.ContractBackend) (*Ion, error) { + contract, err := bindIon(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil +} + +// NewIonCaller creates a new read-only instance of Ion, bound to a specific deployed contract. +func NewIonCaller(address common.Address, caller bind.ContractCaller) (*IonCaller, error) { + contract, err := bindIon(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IonCaller{contract: contract}, nil +} + +// NewIonTransactor creates a new write-only instance of Ion, bound to a specific deployed contract. +func NewIonTransactor(address common.Address, transactor bind.ContractTransactor) (*IonTransactor, error) { + contract, err := bindIon(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IonTransactor{contract: contract}, nil +} + +// NewIonFilterer creates a new log filterer instance of Ion, bound to a specific deployed contract. +func NewIonFilterer(address common.Address, filterer bind.ContractFilterer) (*IonFilterer, error) { + contract, err := bindIon(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IonFilterer{contract: contract}, nil +} + +// bindIon binds a generic wrapper to an already deployed contract. +func bindIon(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(IonABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ion *IonRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Ion.Contract.IonCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ion *IonRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ion.Contract.IonTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ion *IonRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ion.Contract.IonTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ion *IonCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Ion.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ion *IonTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ion.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ion *IonTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ion.Contract.contract.Transact(opts, method, params...) +} + +// CheckReceiptProof is a free data retrieval call binding the contract method 0x59349832. +// +// Solidity: function CheckReceiptProof() constant returns() +func (_Ion *IonCaller) CheckReceiptProof(opts *bind.CallOpts) error { + var () + out := &[]interface{}{} + err := _Ion.contract.Call(opts, out, "CheckReceiptProof") + return err +} + +// CheckReceiptProof is a free data retrieval call binding the contract method 0x59349832. +// +// Solidity: function CheckReceiptProof() constant returns() +func (_Ion *IonSession) CheckReceiptProof() error { + return _Ion.Contract.CheckReceiptProof(&_Ion.CallOpts) +} + +// CheckReceiptProof is a free data retrieval call binding the contract method 0x59349832. +// +// Solidity: function CheckReceiptProof() constant returns() +func (_Ion *IonCallerSession) CheckReceiptProof() error { + return _Ion.Contract.CheckReceiptProof(&_Ion.CallOpts) +} + +// CheckRootsProof is a free data retrieval call binding the contract method 0xe318df54. +// +// Solidity: function CheckRootsProof() constant returns() +func (_Ion *IonCaller) CheckRootsProof(opts *bind.CallOpts) error { + var () + out := &[]interface{}{} + err := _Ion.contract.Call(opts, out, "CheckRootsProof") + return err +} + +// CheckRootsProof is a free data retrieval call binding the contract method 0xe318df54. +// +// Solidity: function CheckRootsProof() constant returns() +func (_Ion *IonSession) CheckRootsProof() error { + return _Ion.Contract.CheckRootsProof(&_Ion.CallOpts) +} + +// CheckRootsProof is a free data retrieval call binding the contract method 0xe318df54. +// +// Solidity: function CheckRootsProof() constant returns() +func (_Ion *IonCallerSession) CheckRootsProof() error { + return _Ion.Contract.CheckRootsProof(&_Ion.CallOpts) +} + +// ChainId is a free data retrieval call binding the contract method 0x9a8a0592. +// +// Solidity: function chainId() constant returns(bytes32) +func (_Ion *IonCaller) ChainId(opts *bind.CallOpts) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "chainId") + return *ret0, err +} + +// ChainId is a free data retrieval call binding the contract method 0x9a8a0592. +// +// Solidity: function chainId() constant returns(bytes32) +func (_Ion *IonSession) ChainId() ([32]byte, error) { + return _Ion.Contract.ChainId(&_Ion.CallOpts) +} + +// ChainId is a free data retrieval call binding the contract method 0x9a8a0592. +// +// Solidity: function chainId() constant returns(bytes32) +func (_Ion *IonCallerSession) ChainId() ([32]byte, error) { + return _Ion.Contract.ChainId(&_Ion.CallOpts) +} + +// Chains is a free data retrieval call binding the contract method 0x550325b5. +// +// Solidity: function chains( uint256) constant returns(bytes32) +func (_Ion *IonCaller) Chains(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "chains", arg0) + return *ret0, err +} + +// Chains is a free data retrieval call binding the contract method 0x550325b5. +// +// Solidity: function chains( uint256) constant returns(bytes32) +func (_Ion *IonSession) Chains(arg0 *big.Int) ([32]byte, error) { + return _Ion.Contract.Chains(&_Ion.CallOpts, arg0) +} + +// Chains is a free data retrieval call binding the contract method 0x550325b5. +// +// Solidity: function chains( uint256) constant returns(bytes32) +func (_Ion *IonCallerSession) Chains(arg0 *big.Int) ([32]byte, error) { + return _Ion.Contract.Chains(&_Ion.CallOpts, arg0) +} + +// GetBlockHeader is a free data retrieval call binding the contract method 0x6b4f9b9d. +// +// Solidity: function getBlockHeader(_blockHash bytes32) constant returns(bytes32[3]) +func (_Ion *IonCaller) GetBlockHeader(opts *bind.CallOpts, _blockHash [32]byte) ([3][32]byte, error) { + var ( + ret0 = new([3][32]byte) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "getBlockHeader", _blockHash) + return *ret0, err +} + +// GetBlockHeader is a free data retrieval call binding the contract method 0x6b4f9b9d. +// +// Solidity: function getBlockHeader(_blockHash bytes32) constant returns(bytes32[3]) +func (_Ion *IonSession) GetBlockHeader(_blockHash [32]byte) ([3][32]byte, error) { + return _Ion.Contract.GetBlockHeader(&_Ion.CallOpts, _blockHash) +} + +// GetBlockHeader is a free data retrieval call binding the contract method 0x6b4f9b9d. +// +// Solidity: function getBlockHeader(_blockHash bytes32) constant returns(bytes32[3]) +func (_Ion *IonCallerSession) GetBlockHeader(_blockHash [32]byte) ([3][32]byte, error) { + return _Ion.Contract.GetBlockHeader(&_Ion.CallOpts, _blockHash) +} + +// MBlockhashes is a free data retrieval call binding the contract method 0xfecc37c3. +// +// Solidity: function m_blockhashes( bytes32, uint256) constant returns(bytes32) +func (_Ion *IonCaller) MBlockhashes(opts *bind.CallOpts, arg0 [32]byte, arg1 *big.Int) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "m_blockhashes", arg0, arg1) + return *ret0, err +} + +// MBlockhashes is a free data retrieval call binding the contract method 0xfecc37c3. +// +// Solidity: function m_blockhashes( bytes32, uint256) constant returns(bytes32) +func (_Ion *IonSession) MBlockhashes(arg0 [32]byte, arg1 *big.Int) ([32]byte, error) { + return _Ion.Contract.MBlockhashes(&_Ion.CallOpts, arg0, arg1) +} + +// MBlockhashes is a free data retrieval call binding the contract method 0xfecc37c3. +// +// Solidity: function m_blockhashes( bytes32, uint256) constant returns(bytes32) +func (_Ion *IonCallerSession) MBlockhashes(arg0 [32]byte, arg1 *big.Int) ([32]byte, error) { + return _Ion.Contract.MBlockhashes(&_Ion.CallOpts, arg0, arg1) +} + +// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// +// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) +func (_Ion *IonCaller) MBlockheaders(opts *bind.CallOpts, arg0 [32]byte) (struct { + PrevBlockHash [32]byte + TxRootHash [32]byte + ReceiptRootHash [32]byte +}, error) { + ret := new(struct { + PrevBlockHash [32]byte + TxRootHash [32]byte + ReceiptRootHash [32]byte + }) + out := ret + err := _Ion.contract.Call(opts, out, "m_blockheaders", arg0) + return *ret, err +} + +// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// +// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) +func (_Ion *IonSession) MBlockheaders(arg0 [32]byte) (struct { + PrevBlockHash [32]byte + TxRootHash [32]byte + ReceiptRootHash [32]byte +}, error) { + return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0) +} + +// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// +// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) +func (_Ion *IonCallerSession) MBlockheaders(arg0 [32]byte) (struct { + PrevBlockHash [32]byte + TxRootHash [32]byte + ReceiptRootHash [32]byte +}, error) { + return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0) +} + +// CheckTxProof is a paid mutator transaction binding the contract method 0xaffd8be9. +// +// Solidity: function CheckTxProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) +func (_Ion *IonTransactor) CheckTxProof(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { + return _Ion.contract.Transact(opts, "CheckTxProof", _id, _blockHash, _value, _parentNodes, _path) +} + +// CheckTxProof is a paid mutator transaction binding the contract method 0xaffd8be9. +// +// Solidity: function CheckTxProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) +func (_Ion *IonSession) CheckTxProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { + return _Ion.Contract.CheckTxProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) +} + +// CheckTxProof is a paid mutator transaction binding the contract method 0xaffd8be9. +// +// Solidity: function CheckTxProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) +func (_Ion *IonTransactorSession) CheckTxProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { + return _Ion.Contract.CheckTxProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) +} + +// RegisterChain is a paid mutator transaction binding the contract method 0x9e43d86b. +// +// Solidity: function RegisterChain(_id bytes32) returns() +func (_Ion *IonTransactor) RegisterChain(opts *bind.TransactOpts, _id [32]byte) (*types.Transaction, error) { + return _Ion.contract.Transact(opts, "RegisterChain", _id) +} + +// RegisterChain is a paid mutator transaction binding the contract method 0x9e43d86b. +// +// Solidity: function RegisterChain(_id bytes32) returns() +func (_Ion *IonSession) RegisterChain(_id [32]byte) (*types.Transaction, error) { + return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id) +} + +// RegisterChain is a paid mutator transaction binding the contract method 0x9e43d86b. +// +// Solidity: function RegisterChain(_id bytes32) returns() +func (_Ion *IonTransactorSession) RegisterChain(_id [32]byte) (*types.Transaction, error) { + return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id) +} + +// SubmitBlock is a paid mutator transaction binding the contract method 0x5a0235e4. +// +// Solidity: function SubmitBlock(_id bytes32, _blockHash bytes32, _rlpBlockHeader bytes) returns() +func (_Ion *IonTransactor) SubmitBlock(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _rlpBlockHeader []byte) (*types.Transaction, error) { + return _Ion.contract.Transact(opts, "SubmitBlock", _id, _blockHash, _rlpBlockHeader) +} + +// SubmitBlock is a paid mutator transaction binding the contract method 0x5a0235e4. +// +// Solidity: function SubmitBlock(_id bytes32, _blockHash bytes32, _rlpBlockHeader bytes) returns() +func (_Ion *IonSession) SubmitBlock(_id [32]byte, _blockHash [32]byte, _rlpBlockHeader []byte) (*types.Transaction, error) { + return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _blockHash, _rlpBlockHeader) +} + +// SubmitBlock is a paid mutator transaction binding the contract method 0x5a0235e4. +// +// Solidity: function SubmitBlock(_id bytes32, _blockHash bytes32, _rlpBlockHeader bytes) returns() +func (_Ion *IonTransactorSession) SubmitBlock(_id [32]byte, _blockHash [32]byte, _rlpBlockHeader []byte) (*types.Transaction, error) { + return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _blockHash, _rlpBlockHeader) +} + +// IonVerifiedTxProofIterator is returned from FilterVerifiedTxProof and is used to iterate over the raw logs and unpacked data for VerifiedTxProof events raised by the Ion contract. +type IonVerifiedTxProofIterator struct { + Event *IonVerifiedTxProof // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IonVerifiedTxProofIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IonVerifiedTxProof) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IonVerifiedTxProof) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IonVerifiedTxProofIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IonVerifiedTxProofIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IonVerifiedTxProof represents a VerifiedTxProof event raised by the Ion contract. +type IonVerifiedTxProof struct { + ChainId [32]byte + BlockHash [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterVerifiedTxProof is a free log retrieval operation binding the contract event 0x202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a1. +// +// Solidity: event VerifiedTxProof(chainId bytes32, blockHash bytes32) +func (_Ion *IonFilterer) FilterVerifiedTxProof(opts *bind.FilterOpts) (*IonVerifiedTxProofIterator, error) { + + logs, sub, err := _Ion.contract.FilterLogs(opts, "VerifiedTxProof") + if err != nil { + return nil, err + } + return &IonVerifiedTxProofIterator{contract: _Ion.contract, event: "VerifiedTxProof", logs: logs, sub: sub}, nil +} + +// WatchVerifiedTxProof is a free log subscription operation binding the contract event 0x202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a1. +// +// Solidity: event VerifiedTxProof(chainId bytes32, blockHash bytes32) +func (_Ion *IonFilterer) WatchVerifiedTxProof(opts *bind.WatchOpts, sink chan<- *IonVerifiedTxProof) (event.Subscription, error) { + + logs, sub, err := _Ion.contract.WatchLogs(opts, "VerifiedTxProof") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IonVerifiedTxProof) + if err := _Ion.contract.UnpackLog(event, "VerifiedTxProof", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} diff --git a/ion-cli/contracts/ion_test.go b/ion-cli/contracts/ion_test.go new file mode 100644 index 0000000..46511bf --- /dev/null +++ b/ion-cli/contracts/ion_test.go @@ -0,0 +1,49 @@ +package contract + +import ( + "encoding/hex" + "fmt" + "log" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/assert" +) + +var CLIENT = "http://127.0.0.1:8501" + +var DEPLOYEDCHAINID = "ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" +var TESTCHAINID = "22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" + +var TESTBLOCK = []byte(`{'difficulty': 2,'extraData': '0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00', 'gasLimit': 5635559972940396, 'gasUsed': 273138, 'hash': '0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4', 'logsBloom': '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 'miner':'0x0000000000000000000000000000000000000000','mixHash': '0x0000000000000000000000000000000000000000000000000000000000000000','nonce':'0x0000000000000000','number': 5446,'parentHash': '0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284','receiptsRoot': '0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1','sha3Uncles':'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347','size': 2027,'stateRoot':'0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967','timestamp': 1531327572,'totalDifficulty': 10893,'transactions': [ '0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3','0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5','0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8','0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6','0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8','0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1','0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446','0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462','0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e','0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314','0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d','0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede','0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc'],'transactionsRoot': '0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35','uncles': []}`) + +var KEY = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` + +// Test ion contract gets deployed correctly +func Test_IonDeployment(t *testing.T) { + // Create an IPC based RPC connection to a remote node + conn, err := ethclient.Dial("http://127.0.0.1:8501") + if err != nil { + log.Fatalf("Failed to connect to the Ethereum client: %v", err) + } + + ionAddr := common.HexToAddress("0xc290566df007e57a09e31ffe9a6d6627ab536ce2") + + ion, err := NewIon(ionAddr, conn) + if err != nil { + log.Fatalf("Failed to instantiate Ion contract: %v", err) + } + chainId, err := ion.ChainId(nil) + if err != nil { + log.Fatalf("Failed to retrieve chainId: %v", err) + } + deployedChainId, err := hex.DecodeString(DEPLOYEDCHAINID) + if err != nil { + log.Fatalf("Failed to retrieve chainId: %v", err) + } + + // Transform into string + CHAINID := fmt.Sprintf("%x", chainId) + assert.Equal(t, DEPLOYEDCHAINID, CHAINID) +} From 81464efe92df3abfd2e166a5ca8b31d015aa0e51 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 17 Jul 2018 16:01:15 +0100 Subject: [PATCH 061/203] Improved the deployment of contracts on single node --- contracts/Ion.sol | 6 +++- contracts/Validation.sol | 24 +++++++------- ion-cli/config/config_test.go | 2 +- ion-cli/contracts/validation.go | 48 +++++++++++++++++++++------- ion-cli/contracts/validation_test.go | 46 ++++++++++++++++++++++---- package.json | 14 ++++---- test/validation.js | 2 +- 7 files changed, 103 insertions(+), 39 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index e000836..14e6c79 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -1,3 +1,5 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; import "./libraries/RLP.sol"; @@ -135,7 +137,7 @@ contract Ion { */ function CheckTxProof(bytes32 _id, bytes32 _blockHash, bytes _value, bytes _parentNodes, bytes _path) onlyRegisteredChains(_id) onlyExistingBlocks(_id, _blockHash) public returns (bool) { BlockHeader storage blockHeader = m_blockheaders[_blockHash]; - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.txRootHash) ); + assert(PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.txRootHash)); emit VerifiedTxProof(_id, _blockHash); return true; } @@ -161,6 +163,7 @@ contract Ion { return [header.prevBlockHash, header.txRootHash, header.receiptRootHash]; } + /* ======================================================================================================================== @@ -176,5 +179,6 @@ contract Ion { } return out; } + } diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 004cfc0..e86b3b4 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -3,11 +3,12 @@ pragma solidity ^0.4.23; import "./libraries/ECVerify.sol"; +import "./libraries/RLP.sol"; import "./libraries/SolidityUtils.sol"; contract Validation { - address Owner; - address[] validators; + address owner; + address[] public validators; uint256 blockHeight; bytes32 blockHash; @@ -30,7 +31,7 @@ contract Validation { * @param _genesisHash genesis block hash */ constructor (address[] _validators, bytes32 genesisHash) public { - Owner = msg.sender; + owner = msg.sender; for (uint i = 0; i < _validators.length; i++) { validators.push(_validators[i]); m_validators[_validators[i]] = true; @@ -70,13 +71,14 @@ contract Validation { * @param prefixHeader the new prefix for the signed hash header * @param prefixExtraData the new prefix for the extraData field */ - function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public { + function ValidateBlock(bytes _header, bytes prefixHeader, bytes prefixExtraData) public { // Check the parent hash is the same as the previous block submitted - bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header, 4); + bytes32 _parentBlockHash = SolUtils.BytesToBytes32(_header, 4); + require(_parentBlockHash==blockHash, "Not child of previous block!"); - uint256 length = header.length; - bytes32 _blockHash = keccak256(header); + uint256 length = _header.length; + bytes32 _blockHash = keccak256(_header); emit broadcastHash(_blockHash); @@ -86,25 +88,25 @@ contract Validation { bytes memory headerEnd = new bytes(42); // Extract the start of the header and replace the length - SolUtils.BytesToBytes(headerStart, header, 0); + SolUtils.BytesToBytes(headerStart, _header, 0); assembly { let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) } // Extract the real extra data and create the signed hash - SolUtils.BytesToBytes(extraData, header, length-140); + SolUtils.BytesToBytes(extraData, _header, length-140); assembly { let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) } // Extract the end of the header - SolUtils.BytesToBytes(headerEnd, header, length-42); + SolUtils.BytesToBytes(headerEnd, _header, length-42); bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); bytes32 hashData = keccak256(newHeader); // Extract the signature of the hash create above - SolUtils.BytesToBytes(extraDataSig, header, length-107); + SolUtils.BytesToBytes(extraDataSig, _header, length-107); address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); require(m_validators[sig_addr]==true, "Signer not a validator!"); diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 52d125f..92eeff5 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -22,7 +22,7 @@ func Test_Read_ValidSetupJson(t *testing.T) { } func Test_Read_ValidKeystore(t *testing.T) { - path := findPath() + "../../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + path := findPath() + "../../poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" contents := config.ReadString(path) const val = "{\"address\":\"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa\",\"cipherparams\":{\"iv\":\"4aa66b789ee2d98cf77272a72eeeaa50\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e\"},\"mac\":\"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3\"},\"id\":\"a3cc1eae-3e36-4659-b759-6cf416216e72\",\"version\":3}" diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index e34a43a..2d9b10e 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -16,10 +16,10 @@ import ( ) // ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GetBlock\",\"outputs\":[{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"_blockHeight\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genesisHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHash2\",\"type\":\"event\"}]" +const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"validators\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GetBlock\",\"outputs\":[{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"_blockHeight\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genesisHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHash2\",\"type\":\"event\"}]" // ValidationBin is the compiled bytecode used for deploying new contracts. -const ValidationBin = `608060405234801561001057600080fd5b50604051610e8f380380610e8f83398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b8160028160001916905550505050610ce9806101a66000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334174e6c1461007d578063927a32e31461010d5780639db7d9f71461015a578063aae933e41461018d578063d405af3d14610282578063ebeafd77146102ee575b600080fd5b34801561008957600080fd5b506100926103e3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100d25780820151818401526020810190506100b7565b50505050905090810190601f1680156100ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011957600080fd5b5061013c6004803603810190808035600019169060200190929190505050610485565b60405180826000191660001916815260200191505060405180910390f35b34801561016657600080fd5b5061016f6104a3565b60405180826000191660001916815260200191505060405180910390f35b34801561019957600080fd5b50610280600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ad565b005b34801561028e57600080fd5b5061029761079f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102da5780820151818401526020810190506102bf565b505050509050019250505060405180910390f35b3480156102fa57600080fd5b506103e1600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061082d565b005b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561047b5780601f106104505761010080835404028352916020019161047b565b820191906000526020600020905b81548152906001019060200180831161045e57829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000154905081565b6000600254905090565b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156104f557805182526020820191506020810190506020830392506104d0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156105995781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105d05781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156106075781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561063e5781602001602082028038833980820191505090505b50935061064f878d60008a516109e9565b600260218801600260208e016004610bb8fa50610672868d608c8c0389516109e9565b600160208701600160208d016004610bb8fa50610695848d602a8c0387516109e9565b6106a0878786610aa4565b9250826040518082805190602001908083835b6020831015156106d857805182526020820191506020810190506020830392506106b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150610717858d606b8c0388516109e9565b6107218286610b50565b905087600281600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561082357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116107d9575b5050505050905090565b60008060608060608088519550886040518082805190602001908083835b602083101515610870578051825260208201915060208101905060208303925061084b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020945088600390805190602001906108b5929190610c18565b5084600281600019169055507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018560405180826000191660001916815260200191505060405180910390a1608d86036040519080825280601f01601f1916602001820160405280156109365781602001602082028038833980820191505090505b509350601f6040519080825280601f01601f19166020018201604052801561096d5781602001602082028038833980820191505090505b50925060416040519080825280601f01601f1916602001820160405280156109a45781602001602082028038833980820191505090505b509150602a6040519080825280601f01601f1916602001820160405280156109db5781602001602082028038833980820191505090505b509050505050505050505050565b60008090505b81811015610a9d5783818401815181101515610a0757fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028582815181101515610a6057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506109ef565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f191660200182016040528015610b0b5781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610b6657600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610b9157601b810190505b601b8160ff161480610ba65750601c8160ff16145b1515610bb157600080fd5b610bbd86828585610bc8565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610c0b57600080fd5b8092505050949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c5957805160ff1916838001178555610c87565b82800160010185558215610c87579182015b82811115610c86578251825591602001919060010190610c6b565b5b509050610c949190610c98565b5090565b610cba91905b80821115610cb6576000816000905550600101610c9e565b5090565b905600a165627a7a7230582009a70c54afc4fb7f922da0ee026dacb18eb44755eb2bc1e8b12424c23f2239b90029` +const ValidationBin = `608060405234801561001057600080fd5b50604051610ca4380380610ca483398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816003816000191690555081600460008081526020019081526020016000206000018160001916905550505050610adf806101c56000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806335aa2e441461007d57806340ce4b6c146100ea5780639db7d9f714610149578063aae933e41461017c578063c4cf3ed614610271578063d405af3d146102c9575b600080fd5b34801561008957600080fd5b506100a860048036038101908080359060200190929190505050610335565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100f657600080fd5b5061011560048036038101908080359060200190929190505050610373565b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390f35b34801561015557600080fd5b5061015e6103b6565b60405180826000191660001916815260200191505060405180910390f35b34801561018857600080fd5b5061026f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506103c0565b005b34801561027d57600080fd5b5061029c60048036038101908080359060200190929190505050610857565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b3480156102d557600080fd5b506102de61087b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610321578082015181840152602081019050610306565b505050509050019250505060405180910390f35b60018181548110151561034457fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000600460008581526020019081526020016000206000015492506004600085815260200190815260200160002060010154915060025490509193909250565b6000600354905090565b600080600060608060608060606000806103db8d6004610909565b9950600354600019168a6000191614151561045e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b8c5198508c6040518082805190602001908083835b6020831015156104985780518252602082019150602081019050602083039250610473565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561053c5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105735781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156105aa5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156105e15781602001602082028038833980820191505090505b5093506105f0878e600061091d565b600260218801600260208f016004610bb8fa50610611868e608c8c0361091d565b600160208701600160208e016004610bb8fa50610632848e602a8c0361091d565b61063d87878661093f565b9250826040518082805190602001908083835b6020831015156106755780518252602082019150602081019050602083039250610650565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506106b2858e606b8c0361091d565b6106bc82866109eb565b905060011515600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515610786576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b87600381600019169055506002600081548092919060010191905055508760046000600254815260200190815260200160002060000181600019169055508960046000600254815260200190815260200160002060010181600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050505050505050505050565b60046020528060005260406000206000915090508060000154908060010154905082565b606060018054806020026020016040519081016040528092919081815260200182805480156108ff57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116108b5575b5050505050905090565b600060208201915081830151905092915050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109a65781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a0157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a2c57601b810190505b601b8160ff161480610a415750601c8160ff16145b1515610a4c57600080fd5b610a5886828585610a63565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610aa657600080fd5b80925050509493505050505600a165627a7a72305820cf83fdc91c1477a7ff4a9251338903b37b04c10ccb8538af298dd16fece5a0ba0029` // DeployValidation deploys a new Ethereum contract, binding an instance of Validation to it. func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address, genesisHash [32]byte) (common.Address, *types.Transaction, *Validation, error) { @@ -304,25 +304,51 @@ func (_Validation *ValidationCallerSession) MBlockheaders(arg0 *big.Int) (struct return _Validation.Contract.MBlockheaders(&_Validation.CallOpts, arg0) } +// Validators is a free data retrieval call binding the contract method 0x35aa2e44. +// +// Solidity: function validators( uint256) constant returns(address) +func (_Validation *ValidationCaller) Validators(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { + var ( + ret0 = new(common.Address) + ) + out := ret0 + err := _Validation.contract.Call(opts, out, "validators", arg0) + return *ret0, err +} + +// Validators is a free data retrieval call binding the contract method 0x35aa2e44. +// +// Solidity: function validators( uint256) constant returns(address) +func (_Validation *ValidationSession) Validators(arg0 *big.Int) (common.Address, error) { + return _Validation.Contract.Validators(&_Validation.CallOpts, arg0) +} + +// Validators is a free data retrieval call binding the contract method 0x35aa2e44. +// +// Solidity: function validators( uint256) constant returns(address) +func (_Validation *ValidationCallerSession) Validators(arg0 *big.Int) (common.Address, error) { + return _Validation.Contract.Validators(&_Validation.CallOpts, arg0) +} + // ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. // -// Solidity: function ValidateBlock(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactor) ValidateBlock(opts *bind.TransactOpts, header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.contract.Transact(opts, "ValidateBlock", header, prefixHeader, prefixExtraData) +// Solidity: function ValidateBlock(_header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactor) ValidateBlock(opts *bind.TransactOpts, _header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.contract.Transact(opts, "ValidateBlock", _header, prefixHeader, prefixExtraData) } // ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. // -// Solidity: function ValidateBlock(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationSession) ValidateBlock(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +// Solidity: function ValidateBlock(_header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationSession) ValidateBlock(_header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, _header, prefixHeader, prefixExtraData) } // ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. // -// Solidity: function ValidateBlock(header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactorSession) ValidateBlock(header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, header, prefixHeader, prefixExtraData) +// Solidity: function ValidateBlock(_header bytes, prefixHeader bytes, prefixExtraData bytes) returns() +func (_Validation *ValidationTransactorSession) ValidateBlock(_header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { + return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, _header, prefixHeader, prefixExtraData) } // ValidationBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Validation contract. diff --git a/ion-cli/contracts/validation_test.go b/ion-cli/contracts/validation_test.go index acb89b0..33c7b8d 100644 --- a/ion-cli/contracts/validation_test.go +++ b/ion-cli/contracts/validation_test.go @@ -1,6 +1,7 @@ package contract import ( + "log" "math/big" "testing" @@ -17,12 +18,12 @@ var val1 = common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") var val2 = common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") var initValidators = []common.Address{val1, val2} -var genesisString = "c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28" +var GENESISHASH = "c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28" -// Test inbox contract gets deployed correctly +// Test validation contract gets deployed correctly func Test_DeployValidation(t *testing.T) { - //Setup simulated block chain + // Setup simulated block chain key, _ := crypto.GenerateKey() auth := bind.NewKeyedTransactor(key) alloc := make(core.GenesisAlloc) @@ -30,7 +31,7 @@ func Test_DeployValidation(t *testing.T) { blockchain := backends.NewSimulatedBackend(alloc) genesisHash := [32]byte{} - copy(genesisHash[:], []byte(genesisString)) + copy(genesisHash[:], []byte(GENESISHASH)) // Deploy contract address, _, _, err := DeployValidation( @@ -43,7 +44,7 @@ func Test_DeployValidation(t *testing.T) { blockchain.Commit() if err != nil { - t.Fatalf("Failed to deploy the Inbox contract: %v", err) + t.Fatalf("Failed to deploy the Validation contract: %v", err) } if len(address.Bytes()) == 0 { @@ -63,7 +64,7 @@ func TestGetValidators(t *testing.T) { blockchain := backends.NewSimulatedBackend(alloc) genesisHash := [32]byte{} - copy(genesisHash[:], []byte(genesisString)) + copy(genesisHash[:], []byte(GENESISHASH)) // Deploy contract _, _, contract, _ := DeployValidation( @@ -92,7 +93,7 @@ func Test_LatestBlock(t *testing.T) { blockchain := backends.NewSimulatedBackend(alloc) genesisHash := [32]byte{} - copy(genesisHash[:], []byte(genesisString)) + copy(genesisHash[:], []byte(GENESISHASH)) // Deploy contract _, _, contract, _ := DeployValidation( @@ -107,3 +108,34 @@ func Test_LatestBlock(t *testing.T) { latestBlock, _ := contract.LatestBlock(&bind.CallOpts{}) assert.Equal(t, latestBlock, genesisHash) } + +// Test that the Validators is updated upon deployment +func Test_Validators(t *testing.T) { + + //Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} + blockchain := backends.NewSimulatedBackend(alloc) + + genesisHash := [32]byte{} + copy(genesisHash[:], []byte(GENESISHASH)) + + // Deploy contract + _, _, contract, _ := DeployValidation( + auth, + blockchain, + initValidators, + genesisHash, + ) + // commit all pending transactions + blockchain.Commit() + + idx := big.NewInt(0) + validator, err := contract.Validators(&bind.CallOpts{}, idx) + if err != nil { + log.Fatalf("Failed to deploy new token contract: %v", err) + } + assert.Equal(t, initValidators[0], validator) +} diff --git a/package.json b/package.json index d6001d6..a70e349 100644 --- a/package.json +++ b/package.json @@ -36,15 +36,15 @@ "web3-utils": "^1.0.0-beta.33" }, "scripts": { - "testrpc": "ganache-cli --gasLimit 0xFFFFFFF --gasPrice 0 --network-id 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", - "testrpca": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", - "testrpcb": "ganache-cli --port 8546 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 5678 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", - "deploy": "truffle deploy", - "deploya": "truffle deploy --network testrpca", - "deployb": "truffle deploy --network testrpcb", + "deploy": "truffle deploy --network development", + "depclique": "truffle deploy --network clique", "test": "truffle test --network clique", "coverage": "solidity-coverage", - "lint": "solhint contracts/**/*.sol" + "lint": "solhint contracts/**/*.sol", + "genbin": "solc --overwrite --bin ./contracts/* -o abi", + "genabi": "solc --overwrite --abi ./contracts/* -o abi", + "abigen": "abigen --bin=abi/Validation.bin --abi=abi/Validation.abi --pkg=validation --out=validation.go" } } diff --git a/test/validation.js b/test/validation.js index d57d648..35c3749 100644 --- a/test/validation.js +++ b/test/validation.js @@ -59,7 +59,7 @@ signHeader = (headerHash, privateKey, extraData) => { -contract('Validation.js', (accounts) => { +contract.only('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From 6e8b6fd945d55ce3f33834d37d7a2b14cee5d8b4 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 17 Jul 2018 17:54:13 +0100 Subject: [PATCH 062/203] Removed some accidentally added files --- poa-network/multi-peer/node1/geth/LOCK | 0 .../node1/geth/chaindata/000002.ldb | Bin 988 -> 0 bytes .../multi-peer/node1/geth/chaindata/CURRENT | 1 - .../multi-peer/node1/geth/chaindata/LOCK | 0 .../multi-peer/node1/geth/chaindata/LOG | 18 - .../node1/geth/chaindata/MANIFEST-000004 | Bin 215 -> 0 bytes .../node1/geth/lightchaindata/000002.ldb | Bin 988 -> 0 bytes .../node1/geth/lightchaindata/000005.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000008.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000011.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000014.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000017.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000020.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000023.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000026.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000029.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000032.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000035.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000038.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000041.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000044.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000047.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000050.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000053.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000056.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000059.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000062.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000065.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000068.ldb | Bin 988 -> 0 bytes .../node1/geth/lightchaindata/CURRENT | 1 - .../multi-peer/node1/geth/lightchaindata/LOCK | 0 .../multi-peer/node1/geth/lightchaindata/LOG | 244 ----------- .../node1/geth/lightchaindata/MANIFEST-000067 | Bin 2746 -> 0 bytes poa-network/multi-peer/node1/geth/nodekey | 1 - .../multi-peer/node1/geth/nodes/000086.ldb | Bin 352635 -> 0 bytes .../multi-peer/node1/geth/nodes/CURRENT | 1 - poa-network/multi-peer/node1/geth/nodes/LOCK | 0 poa-network/multi-peer/node1/geth/nodes/LOG | 333 --------------- .../node1/geth/nodes/MANIFEST-000085 | Bin 862 -> 0 bytes .../multi-peer/node1/geth/transactions.rlp | Bin 31607 -> 0 bytes poa-network/multi-peer/node2/geth/LOCK | 0 .../multi-peer/node2/geth/chaindata/CURRENT | 1 - .../multi-peer/node2/geth/chaindata/LOCK | 0 .../multi-peer/node2/geth/chaindata/LOG | 6 - .../node2/geth/chaindata/MANIFEST-000000 | Bin 54 -> 0 bytes .../node2/geth/lightchaindata/000002.ldb | Bin 987 -> 0 bytes .../node2/geth/lightchaindata/000005.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000008.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000011.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000014.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000017.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000020.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000023.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000026.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000029.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000032.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000035.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000038.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000041.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000044.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000047.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000050.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000053.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000056.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000059.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000062.ldb | Bin 356 -> 0 bytes .../node2/geth/lightchaindata/000065.ldb | Bin 987 -> 0 bytes .../node2/geth/lightchaindata/CURRENT | 1 - .../multi-peer/node2/geth/lightchaindata/LOCK | 0 .../multi-peer/node2/geth/lightchaindata/LOG | 233 ----------- .../node2/geth/lightchaindata/MANIFEST-000064 | Bin 2627 -> 0 bytes poa-network/multi-peer/node2/geth/nodekey | 1 - .../multi-peer/node2/geth/nodes/000078.ldb | Bin 225108 -> 0 bytes .../multi-peer/node2/geth/nodes/CURRENT | 1 - poa-network/multi-peer/node2/geth/nodes/LOCK | 0 poa-network/multi-peer/node2/geth/nodes/LOG | 299 -------------- .../node2/geth/nodes/MANIFEST-000077 | Bin 852 -> 0 bytes .../multi-peer/node2/geth/transactions.rlp | 0 poa-network/single-peer/node1/geth/LOCK | 0 .../node1/geth/chaindata/000002.ldb | Bin 794 -> 0 bytes .../single-peer/node1/geth/chaindata/CURRENT | 1 - .../single-peer/node1/geth/chaindata/LOCK | 0 .../single-peer/node1/geth/chaindata/LOG | 16 - .../node1/geth/chaindata/MANIFEST-000004 | Bin 217 -> 0 bytes .../node1/geth/lightchaindata/000002.ldb | Bin 987 -> 0 bytes .../node1/geth/lightchaindata/000005.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000008.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000011.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000014.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000017.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000020.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000023.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000026.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000029.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000032.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000035.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000038.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000041.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000044.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000047.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000050.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000053.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/000056.ldb | Bin 356 -> 0 bytes .../node1/geth/lightchaindata/CURRENT | 1 - .../node1/geth/lightchaindata/LOCK | 0 .../single-peer/node1/geth/lightchaindata/LOG | 267 ------------ .../node1/geth/lightchaindata/MANIFEST-000070 | Bin 2270 -> 0 bytes poa-network/single-peer/node1/geth/nodekey | 1 - .../single-peer/node1/geth/nodes/000098.ldb | Bin 1327685 -> 0 bytes .../single-peer/node1/geth/nodes/CURRENT | 1 - poa-network/single-peer/node1/geth/nodes/LOCK | 0 poa-network/single-peer/node1/geth/nodes/LOG | 379 ------------------ .../node1/geth/nodes/MANIFEST-000097 | Bin 862 -> 0 bytes .../single-peer/node1/geth/transactions.rlp | Bin 637035 -> 0 bytes 114 files changed, 1807 deletions(-) delete mode 100644 poa-network/multi-peer/node1/geth/LOCK delete mode 100644 poa-network/multi-peer/node1/geth/chaindata/000002.ldb delete mode 100644 poa-network/multi-peer/node1/geth/chaindata/CURRENT delete mode 100644 poa-network/multi-peer/node1/geth/chaindata/LOCK delete mode 100644 poa-network/multi-peer/node1/geth/chaindata/LOG delete mode 100644 poa-network/multi-peer/node1/geth/chaindata/MANIFEST-000004 delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000002.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000005.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000008.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000011.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000014.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000017.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000020.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000023.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000026.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000029.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000032.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000035.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000038.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000041.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000044.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000047.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000050.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000053.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000056.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000059.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000062.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000065.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/000068.ldb delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/CURRENT delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/LOCK delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/LOG delete mode 100644 poa-network/multi-peer/node1/geth/lightchaindata/MANIFEST-000067 delete mode 100644 poa-network/multi-peer/node1/geth/nodekey delete mode 100644 poa-network/multi-peer/node1/geth/nodes/000086.ldb delete mode 100644 poa-network/multi-peer/node1/geth/nodes/CURRENT delete mode 100644 poa-network/multi-peer/node1/geth/nodes/LOCK delete mode 100644 poa-network/multi-peer/node1/geth/nodes/LOG delete mode 100644 poa-network/multi-peer/node1/geth/nodes/MANIFEST-000085 delete mode 100755 poa-network/multi-peer/node1/geth/transactions.rlp delete mode 100644 poa-network/multi-peer/node2/geth/LOCK delete mode 100644 poa-network/multi-peer/node2/geth/chaindata/CURRENT delete mode 100644 poa-network/multi-peer/node2/geth/chaindata/LOCK delete mode 100644 poa-network/multi-peer/node2/geth/chaindata/LOG delete mode 100644 poa-network/multi-peer/node2/geth/chaindata/MANIFEST-000000 delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000002.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000005.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000008.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000011.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000014.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000017.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000020.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000023.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000026.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000029.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000032.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000035.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000038.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000041.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000044.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000047.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000050.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000053.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000056.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000059.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000062.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/000065.ldb delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/CURRENT delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/LOCK delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/LOG delete mode 100644 poa-network/multi-peer/node2/geth/lightchaindata/MANIFEST-000064 delete mode 100644 poa-network/multi-peer/node2/geth/nodekey delete mode 100644 poa-network/multi-peer/node2/geth/nodes/000078.ldb delete mode 100644 poa-network/multi-peer/node2/geth/nodes/CURRENT delete mode 100644 poa-network/multi-peer/node2/geth/nodes/LOCK delete mode 100644 poa-network/multi-peer/node2/geth/nodes/LOG delete mode 100644 poa-network/multi-peer/node2/geth/nodes/MANIFEST-000077 delete mode 100755 poa-network/multi-peer/node2/geth/transactions.rlp delete mode 100644 poa-network/single-peer/node1/geth/LOCK delete mode 100644 poa-network/single-peer/node1/geth/chaindata/000002.ldb delete mode 100644 poa-network/single-peer/node1/geth/chaindata/CURRENT delete mode 100644 poa-network/single-peer/node1/geth/chaindata/LOCK delete mode 100644 poa-network/single-peer/node1/geth/chaindata/LOG delete mode 100644 poa-network/single-peer/node1/geth/chaindata/MANIFEST-000004 delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000002.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000005.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000008.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000011.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000014.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000017.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000020.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000023.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000026.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000029.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000032.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000035.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000038.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000041.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000044.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000047.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000050.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000053.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/000056.ldb delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/CURRENT delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/LOCK delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/LOG delete mode 100644 poa-network/single-peer/node1/geth/lightchaindata/MANIFEST-000070 delete mode 100644 poa-network/single-peer/node1/geth/nodekey delete mode 100644 poa-network/single-peer/node1/geth/nodes/000098.ldb delete mode 100644 poa-network/single-peer/node1/geth/nodes/CURRENT delete mode 100644 poa-network/single-peer/node1/geth/nodes/LOCK delete mode 100644 poa-network/single-peer/node1/geth/nodes/LOG delete mode 100644 poa-network/single-peer/node1/geth/nodes/MANIFEST-000097 delete mode 100755 poa-network/single-peer/node1/geth/transactions.rlp diff --git a/poa-network/multi-peer/node1/geth/LOCK b/poa-network/multi-peer/node1/geth/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/poa-network/multi-peer/node1/geth/chaindata/000002.ldb b/poa-network/multi-peer/node1/geth/chaindata/000002.ldb deleted file mode 100644 index 9306c979453e2b1d499d9f78ca63b25137a5fda6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 988 zcmeC={}9Tc(amT%XJS*&_TtxhZAWHA9eb=RZMnAPkGAK-z|Q?28)UN{FtRX!!H>=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsYv@=3rCln<)0UEwmj~b#I4WqmM;D#35?8~4g$cmY_X$k6$8VL ze?DyUeArktg6mc@voNyqZes~tQ1_65p@ET+VL@FmJEN*e0~mnv05DP+7{A=FULM_0 zkr7!K#CfcvJL$o+r+@MU*g*2aK+MfxGRwkEzk)%LIW04%B(+E{C$%g!CnZVGsT9c1 z%mXIT{9HFyX^lN>G9XQ0Lo+uX`YA5Lz{z}v@joY{2E%r+d0;6Qqb&WqZ2A+~#Xzd@ NgYe%C-72N-w*kGpN%8;y diff --git a/poa-network/multi-peer/node1/geth/chaindata/CURRENT b/poa-network/multi-peer/node1/geth/chaindata/CURRENT deleted file mode 100644 index cacca75..0000000 --- a/poa-network/multi-peer/node1/geth/chaindata/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000004 diff --git a/poa-network/multi-peer/node1/geth/chaindata/LOCK b/poa-network/multi-peer/node1/geth/chaindata/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/poa-network/multi-peer/node1/geth/chaindata/LOG b/poa-network/multi-peer/node1/geth/chaindata/LOG deleted file mode 100644 index b60b280..0000000 --- a/poa-network/multi-peer/node1/geth/chaindata/LOG +++ /dev/null @@ -1,18 +0,0 @@ -=============== Jul 13, 2018 (BST) =============== -13:56:18.180795 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:56:18.242233 db@open opening -13:56:18.242787 version@stat F·[] S·0B[] Sc·[] -13:56:18.256947 db@janitor F·2 G·0 -13:56:18.256978 db@open done T·14.717208ms -=============== Jul 13, 2018 (BST) =============== -13:56:18.332475 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:56:18.332632 version@stat F·[] S·0B[] Sc·[] -13:56:18.332654 db@open opening -13:56:18.332701 journal@recovery F·1 -13:56:18.335364 journal@recovery recovering @1 -13:56:18.343305 memdb@flush created L0@2 N·14 S·988B "9\x9c\x91..\x1dj\xe0,v4":"\xdb7C..b\xf5\xdc,v5" -13:56:18.345866 version@stat F·[1] S·988B[988B] Sc·[0.25] -13:56:18.361872 db@janitor F·3 G·0 -13:56:18.361936 db@open done T·29.262546ms -13:56:20.660995 db@close closing -13:56:20.661091 db@close done T·95.091µs diff --git a/poa-network/multi-peer/node1/geth/chaindata/MANIFEST-000004 b/poa-network/multi-peer/node1/geth/chaindata/MANIFEST-000004 deleted file mode 100644 index ebb5815c1a8d3d07176af1adcccc61c8983e9474..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215 zcmaDb>0;0Y21Z7yoYb<^oRlOzr^=Gl^338?=ltA)#G=HK{30f1W>yw{b_S+9>>8GH zCN}kKFMgfZc4S7>vB$d7mTO!7XnQ^k?A-scK{o3FBMSo=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsYv@=3rCln<)0UEwmj~b#I4WqmM;D#35?8~4g$cmY_X$k6$8VL ze?DyUeArktg6mc@voNyqZes~tQ1_65p@ET+VL@FmJEN*e0~mnv05DP+7{A=FULM_0 zkr7!K#CfcvJL$o+r+@MU*g*2aK+MfxGRwkEzk)%LIW04%B(+E{C$%g!CnZVGsT9c1 z%mXIT{9HFyX^lN>G9XQ0Lo+uX`YA5Lz{z}v@joY{2E%r+d0;6Qqb&WqZ2A+~#Xzd@ NgYe%C-72N-w*kGpN%8;y diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000005.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000005.ldb deleted file mode 100644 index c480fadcbb16ef1d519c30d62f4bb8b6d6608498..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=&~ggKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0QHestpET3 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000008.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000008.ldb deleted file mode 100644 index d2b26a1513df62490165abb9178df47524827180..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(5igKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7araSq}muu(H6 uxR{8GFmN)bG5+Ud)L=LX5{1|jQh)Z?Q%3!nOkyA*{2=^yL$^w)`)vRx>RJN; diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000011.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000011.ldb deleted file mode 100644 index df591285ec4a5126c6edcfcaadbe0d6cdbf90ba3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(2hgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(8jgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c40gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0Gb3^x&QzG diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000020.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000020.ldb deleted file mode 100644 index 0f885d9e99a6ddfd068f3d58435204b29fb142a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cA2gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c71gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cD3gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qiLgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm8l$aRU zK%$&L%*|leYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qoNgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qlMgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmH7Hgo`4N=yuF zAW=>r=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r05HB;{Qv*} diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000038.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000038.ldb deleted file mode 100644 index a05ec3826f2c34a6199189d16cc0a8392e95cf55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qrOgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*08mI;GXMYp diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000041.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000041.ldb deleted file mode 100644 index c8f05dd77cbe3eac74780b6ebaab315d0e462feb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANm$gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm?x!EOeQgq5PlH;yP;d9)crO9n~Yko diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000044.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000044.ldb deleted file mode 100644 index 627147b4d7b2f480a6a51150b612a39211a8ccf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANs&gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANp%gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANv(gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0AdtcNB{r; diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000053.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000053.ldb deleted file mode 100644 index 32548614e07c2dcfdabd893cf97d080abd9721d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HL=gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0A*QPO8@`> diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000056.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000056.ldb deleted file mode 100644 index 3c07eed7394d4b6511ac7fd9c724fdf5e2425875..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HR?gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HO>gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HU@gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*09BbYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV6gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*07G9|3jhEB diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/000068.ldb b/poa-network/multi-peer/node1/geth/lightchaindata/000068.ldb deleted file mode 100644 index f48d4b29e87d26a984acaf0bf636776b9e8b3e37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 988 zcmeC={}9Tc(amT%XJS*&_TtxhZAWHA9eb=RZMnAPkGAK-z|Q?28)UN{FtRX!!H>=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yasx8Sr-sa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsYv@=3rCln<)0UEwmj~b#I4WqmM;D#35?8~4g$cmY_X$k6$8VL ze?DyUeArktg6mc@voNyqZes~tQ1_65p@ET+VL@FmJEN*e0~mnv05DP+7&DbGHbys8 zWJDGQaUSdFPI@ry>7P6SHjun95OXt_%(8IPuV7GQPRq_T4N8J3`i5i(2a+Fii L1·0 S·2KiB Q·23 -=============== Jul 12, 2018 (BST) =============== -14:39:49.043595 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:39:49.043714 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] -14:39:49.043726 db@open opening -14:39:49.043774 journal@recovery F·1 -14:39:49.044218 journal@recovery recovering @15 -14:39:49.051759 memdb@flush created L0@17 N·1 S·356B "eth..\x0e/(,v24":"eth..\x0e/(,v24" -14:39:49.051955 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] -14:39:49.074956 db@janitor F·8 G·0 -14:39:49.074982 db@open done T·31.248066ms -14:39:49.075058 table@compaction L0·6 -> L1·0 S·2KiB Q·25 -=============== Jul 12, 2018 (BST) =============== -15:37:17.901222 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:37:17.901345 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] -15:37:17.901358 db@open opening -15:37:17.901422 journal@recovery F·1 -15:37:17.901807 journal@recovery recovering @18 -15:37:17.910921 memdb@flush created L0@20 N·1 S·356B "eth..\x0e/(,v26":"eth..\x0e/(,v26" -15:37:17.911100 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] -15:37:17.925999 db@janitor F·9 G·0 -15:37:17.926024 db@open done T·24.657115ms -15:37:17.927614 table@compaction L0·7 -> L1·0 S·3KiB Q·28 -=============== Jul 12, 2018 (BST) =============== -15:48:30.010524 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:48:30.010703 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] -15:48:30.010717 db@open opening -15:48:30.010770 journal@recovery F·1 -15:48:30.018151 journal@recovery recovering @21 -15:48:30.031309 memdb@flush created L0@23 N·1 S·356B "eth..\x0e/(,v28":"eth..\x0e/(,v28" -15:48:30.031687 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] -15:48:30.059073 db@janitor F·10 G·0 -15:48:30.059100 db@open done T·48.376085ms -15:48:30.060310 table@compaction L0·8 -> L1·0 S·3KiB Q·29 -=============== Jul 12, 2018 (BST) =============== -16:05:26.776033 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:05:26.776165 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] -16:05:26.776176 db@open opening -16:05:26.776224 journal@recovery F·1 -16:05:26.776677 journal@recovery recovering @24 -16:05:26.785455 memdb@flush created L0@26 N·1 S·356B "eth..\x0e/(,v30":"eth..\x0e/(,v30" -16:05:26.785678 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] -16:05:26.809759 db@janitor F·11 G·0 -16:05:26.809855 table@compaction L0·9 -> L1·0 S·3KiB Q·31 -16:05:26.810715 db@open done T·33.614932ms -=============== Jul 12, 2018 (BST) =============== -16:23:47.424425 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:23:47.424527 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] -16:23:47.424540 db@open opening -16:23:47.424591 journal@recovery F·1 -16:23:47.425123 journal@recovery recovering @27 -16:23:47.439219 memdb@flush created L0@29 N·1 S·356B "eth..\x0e/(,v32":"eth..\x0e/(,v32" -16:23:47.439454 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] -16:23:47.467206 db@janitor F·12 G·0 -16:23:47.467230 db@open done T·42.681537ms -16:23:47.467849 table@compaction L0·10 -> L1·0 S·4KiB Q·33 -=============== Jul 12, 2018 (BST) =============== -16:40:10.371686 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:40:10.371817 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] -16:40:10.371830 db@open opening -16:40:10.371907 journal@recovery F·1 -16:40:10.373766 journal@recovery recovering @30 -16:40:10.389761 memdb@flush created L0@32 N·1 S·356B "eth..\x0e/(,v34":"eth..\x0e/(,v34" -16:40:10.389933 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] -16:40:10.418773 db@janitor F·13 G·0 -16:40:10.418797 db@open done T·46.959609ms -16:40:10.418858 table@compaction L0·11 -> L1·0 S·4KiB Q·35 -=============== Jul 12, 2018 (BST) =============== -16:57:38.090757 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:57:38.090908 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] -16:57:38.090921 db@open opening -16:57:38.091001 journal@recovery F·1 -16:57:38.092562 journal@recovery recovering @33 -16:57:38.106295 memdb@flush created L0@35 N·1 S·356B "eth..\x0e/(,v36":"eth..\x0e/(,v36" -16:57:38.106774 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] -16:57:38.131109 db@janitor F·14 G·0 -16:57:38.131133 db@open done T·40.204748ms -16:57:38.131179 table@compaction L0·12 -> L1·0 S·4KiB Q·37 -=============== Jul 13, 2018 (BST) =============== -11:03:46.000460 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:03:46.000607 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] -11:03:46.000618 db@open opening -11:03:46.000698 journal@recovery F·1 -11:03:46.001141 journal@recovery recovering @36 -11:03:46.008992 memdb@flush created L0@38 N·1 S·356B "eth..\x0e/(,v38":"eth..\x0e/(,v38" -11:03:46.009166 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] -11:03:46.023882 db@janitor F·15 G·0 -11:03:46.023908 db@open done T·23.28332ms -11:03:46.024537 table@compaction L0·13 -> L1·0 S·5KiB Q·39 -=============== Jul 13, 2018 (BST) =============== -11:20:09.899511 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:20:09.899673 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] -11:20:09.899691 db@open opening -11:20:09.899783 journal@recovery F·1 -11:20:09.900184 journal@recovery recovering @39 -11:20:09.912744 memdb@flush created L0@41 N·1 S·356B "eth..\x0e/(,v40":"eth..\x0e/(,v40" -11:20:09.912997 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] -11:20:09.941221 db@janitor F·16 G·0 -11:20:09.941251 db@open done T·41.550282ms -11:20:09.941342 table@compaction L0·14 -> L1·0 S·5KiB Q·41 -=============== Jul 13, 2018 (BST) =============== -11:22:02.901675 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:22:02.901852 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] -11:22:02.901876 db@open opening -11:22:02.901980 journal@recovery F·1 -11:22:02.902709 journal@recovery recovering @42 -11:22:02.918141 memdb@flush created L0@44 N·1 S·356B "eth..\x0e/(,v42":"eth..\x0e/(,v42" -11:22:02.918398 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] -11:22:02.946853 db@janitor F·17 G·0 -11:22:02.946899 db@open done T·45.011878ms -11:22:02.947647 table@compaction L0·15 -> L1·0 S·5KiB Q·43 -=============== Jul 13, 2018 (BST) =============== -11:28:34.344769 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:28:34.344929 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] -11:28:34.344947 db@open opening -11:28:34.345034 journal@recovery F·1 -11:28:34.345498 journal@recovery recovering @45 -11:28:34.352995 memdb@flush created L0@47 N·1 S·356B "eth..\x0e/(,v44":"eth..\x0e/(,v44" -11:28:34.354854 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] -11:28:34.373782 db@janitor F·18 G·0 -11:28:34.373820 db@open done T·28.864466ms -11:28:34.373958 table@compaction L0·16 -> L1·0 S·6KiB Q·45 -=============== Jul 13, 2018 (BST) =============== -11:41:20.358038 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:20.358169 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] -11:41:20.358188 db@open opening -11:41:20.358254 journal@recovery F·1 -11:41:20.358733 journal@recovery recovering @48 -11:41:20.366548 memdb@flush created L0@50 N·1 S·356B "eth..\x0e/(,v46":"eth..\x0e/(,v46" -11:41:20.366758 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] -11:41:20.381196 db@janitor F·19 G·0 -11:41:20.381237 db@open done T·23.03988ms -11:41:20.382138 table@compaction L0·17 -> L1·0 S·6KiB Q·47 -=============== Jul 13, 2018 (BST) =============== -13:24:29.055504 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:24:29.055677 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] -13:24:29.055701 db@open opening -13:24:29.055813 journal@recovery F·1 -13:24:29.061531 journal@recovery recovering @51 -13:24:29.070331 memdb@flush created L0@53 N·1 S·356B "eth..\x0e/(,v48":"eth..\x0e/(,v48" -13:24:29.070583 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] -13:24:29.087336 db@janitor F·20 G·0 -13:24:29.087367 db@open done T·31.654841ms -13:24:29.088359 table@compaction L0·18 -> L1·0 S·6KiB Q·49 -=============== Jul 13, 2018 (BST) =============== -13:27:13.482710 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:27:13.483399 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] -13:27:13.483562 db@open opening -13:27:13.483961 journal@recovery F·1 -13:27:13.491317 journal@recovery recovering @54 -13:27:13.501450 memdb@flush created L0@56 N·1 S·356B "eth..\x0e/(,v50":"eth..\x0e/(,v50" -13:27:13.511084 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:27:13.531538 db@janitor F·21 G·0 -13:27:13.531638 db@open done T·48.031341ms -13:27:13.531939 table@compaction L0·19 -> L1·0 S·7KiB Q·51 -=============== Jul 13, 2018 (BST) =============== -13:35:11.452220 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:35:11.452980 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:35:11.453145 db@open opening -13:35:11.453637 journal@recovery F·1 -13:35:11.454941 journal@recovery recovering @57 -13:35:11.464221 memdb@flush created L0@59 N·1 S·356B "eth..\x0e/(,v52":"eth..\x0e/(,v52" -13:35:11.465727 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] -13:35:11.483720 db@janitor F·22 G·0 -13:35:11.483834 db@open done T·30.575071ms -13:35:11.484083 table@compaction L0·20 -> L1·0 S·7KiB Q·53 -=============== Jul 13, 2018 (BST) =============== -13:51:52.767069 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:51:52.767205 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] -13:51:52.767224 db@open opening -13:51:52.767319 journal@recovery F·1 -13:51:52.767953 journal@recovery recovering @60 -13:51:52.776595 memdb@flush created L0@62 N·1 S·356B "eth..\x0e/(,v54":"eth..\x0e/(,v54" -13:51:52.776772 version@stat F·[21] S·7KiB[7KiB] Sc·[5.25] -13:51:52.792457 db@janitor F·23 G·0 -13:51:52.792484 db@open done T·25.251519ms -13:51:52.793412 table@compaction L0·21 -> L1·0 S·7KiB Q·55 -=============== Jul 13, 2018 (BST) =============== -13:56:18.257512 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:56:18.257637 version@stat F·[21] S·7KiB[7KiB] Sc·[5.25] -13:56:18.257653 db@open opening -13:56:18.257722 journal@recovery F·1 -13:56:18.259357 journal@recovery recovering @63 -13:56:18.266802 memdb@flush created L0@65 N·1 S·356B "eth..\x0e/(,v56":"eth..\x0e/(,v56" -13:56:18.268594 version@stat F·[22] S·8KiB[8KiB] Sc·[5.50] -13:56:18.287066 db@janitor F·24 G·0 -13:56:18.287093 db@open done T·29.432209ms -13:56:18.287861 table@compaction L0·22 -> L1·0 S·8KiB Q·57 diff --git a/poa-network/multi-peer/node1/geth/lightchaindata/MANIFEST-000067 b/poa-network/multi-peer/node1/geth/lightchaindata/MANIFEST-000067 deleted file mode 100644 index 4fd88fd9fe3bb9cc90b188bab7c874980cd24800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2746 zcmc)F%`3wJ9LMqRZ>F!vV#&iEka?JgZ7dI4D`gzG*-2@su^*;AXog&nBuYvy4$6sx za-tLmg(w%46FU%2JMDlArTG2@pNsGL`|j0e?&ivOkgX_&usWrNgM)VOOhTOwO{kr* z$ao+gNW|hAZ$_8a&D8O#ajA(>HLgxZY(uf=aA?GKetgzEZ9rKGnHmtb4rL`|szq2U%1X#ojj+`yD!{C1lD( z*gTY#kV%tdt9xsGVfAPt6k$F@%YUfK1m fVdwC{6#7oz)mW-ZQXXS(Xkj2c_?}cU{~mt;S7`=K diff --git a/poa-network/multi-peer/node1/geth/nodekey b/poa-network/multi-peer/node1/geth/nodekey deleted file mode 100644 index d8c4eb5..0000000 --- a/poa-network/multi-peer/node1/geth/nodekey +++ /dev/null @@ -1 +0,0 @@ -eca9ca1438314a1cfdb786668e7876efbc6535c278f86ab6b0417d5d93b4822b \ No newline at end of file diff --git a/poa-network/multi-peer/node1/geth/nodes/000086.ldb b/poa-network/multi-peer/node1/geth/nodes/000086.ldb deleted file mode 100644 index ce100a8bbd5f7a7da55a31ee3b31cd3ba7a34757..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352635 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 z 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 L1·0 S·16KiB Q·2021 -11:27:24.017458 table@build created L1@8 N·9 S·411B "n:/..ver,v1968":"version,v1" -11:27:24.017515 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:27:24.024914 table@compaction committed F-1 S-16KiB Ke·0 D·2010 T·21.885965ms -11:27:24.025012 table@remove removed @5 -11:27:24.025058 table@remove removed @2 -=============== Jul 12, 2018 (BST) =============== -11:34:08.348817 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:34:08.349286 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:34:08.349338 db@open opening -11:34:08.349538 journal@recovery F·1 -11:34:08.360736 journal@recovery recovering @6 -11:34:08.381586 memdb@flush created L0@9 N·982 S·7KiB "n:/..ver,v2988":"n:\xdc..ong,v2031" -11:34:08.384067 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] -11:34:08.399373 db@janitor F·4 G·0 -11:34:08.399408 db@open done T·50.032306ms -=============== Jul 12, 2018 (BST) =============== -11:53:49.125828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:53:49.125995 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] -11:53:49.126008 db@open opening -11:53:49.126052 journal@recovery F·1 -11:53:49.127385 journal@recovery recovering @10 -11:53:49.145327 memdb@flush created L0@12 N·3192 S·25KiB "n:/..ver,v6186":"n:\xdc..ong,v3015" -11:53:49.148934 version@stat F·[2 1] S·33KiB[33KiB 411B] Sc·[0.50 0.00] -11:53:49.175177 db@janitor F·5 G·0 -11:53:49.175228 db@open done T·49.210646ms -11:53:49.178029 table@compaction L0·2 -> L1·1 S·33KiB Q·6197 -11:53:49.187821 table@build created L1@15 N·9 S·412B "n:/..ver,v6186":"version,v1" -11:53:49.187864 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] -11:53:49.202969 table@compaction committed F-2 S-33KiB Ke·0 D·4174 T·24.897024ms -11:53:49.203108 table@remove removed @12 -11:53:49.203636 table@remove removed @9 -11:53:49.203769 table@remove removed @8 -=============== Jul 12, 2018 (BST) =============== -14:17:44.688701 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:17:44.689805 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] -14:17:44.689868 db@open opening -14:17:44.690063 journal@recovery F·1 -14:17:44.695883 journal@recovery recovering @13 -14:17:44.757316 memdb@flush created L0@16 N·10756 S·84KiB "n:/..ver,v16902":"n:\xdc..ong,v6200" -14:17:44.759028 version@stat F·[1 1] S·85KiB[84KiB 412B] Sc·[0.25 0.00] -14:17:44.786504 db@janitor F·4 G·0 -14:17:44.786549 db@open done T·96.656953ms -=============== Jul 12, 2018 (BST) =============== -14:39:51.282920 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:39:51.283067 version@stat F·[1 1] S·85KiB[84KiB 412B] Sc·[0.25 0.00] -14:39:51.283079 db@open opening -14:39:51.283127 journal@recovery F·1 -14:39:51.284732 journal@recovery recovering @17 -14:39:51.311699 memdb@flush created L0@19 N·3576 S·28KiB "n:/..ver,v20523":"n:\xdc..ong,v16961" -14:39:51.313974 version@stat F·[2 1] S·113KiB[113KiB 412B] Sc·[0.50 0.00] -14:39:51.335982 db@janitor F·5 G·0 -14:39:51.336021 db@open done T·52.932737ms -14:39:51.338270 table@compaction L0·2 -> L1·1 S·113KiB Q·20531 -14:39:51.354265 table@build created L1@22 N·9 S·411B "n:/..ver,v20523":"version,v1" -14:39:51.354323 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -14:39:51.361842 table@compaction committed F-2 S-113KiB Ke·0 D·14332 T·23.52416ms -14:39:51.361965 table@remove removed @19 -14:39:51.362037 table@remove removed @16 -14:39:51.362077 table@remove removed @15 -=============== Jul 12, 2018 (BST) =============== -15:37:20.197501 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:37:20.197779 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -15:37:20.197799 db@open opening -15:37:20.197907 journal@recovery F·1 -15:37:20.200023 journal@recovery recovering @20 -15:37:20.229689 memdb@flush created L0@23 N·9077 S·71KiB "n:/..ver,v29551":"n:\xdc..ong,v20538" -15:37:20.231484 version@stat F·[1 1] S·72KiB[71KiB 411B] Sc·[0.25 0.00] -15:37:20.251005 db@janitor F·4 G·0 -15:37:20.251043 db@open done T·53.232225ms -=============== Jul 12, 2018 (BST) =============== -15:48:32.385325 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:48:32.385492 version@stat F·[1 1] S·72KiB[71KiB 411B] Sc·[0.25 0.00] -15:48:32.385540 db@open opening -15:48:32.385604 journal@recovery F·1 -15:48:32.387030 journal@recovery recovering @24 -15:48:32.405585 memdb@flush created L0@26 N·1846 S·14KiB "n:/..ver,v31425":"n:\xdc..ong,v29612" -15:48:32.413016 version@stat F·[2 1] S·87KiB[86KiB 411B] Sc·[0.50 0.00] -15:48:32.439667 db@janitor F·5 G·0 -15:48:32.439756 db@open done T·54.201389ms -15:48:32.443897 table@compaction L0·2 -> L1·1 S·87KiB Q·31456 -15:48:32.463628 table@build created L1@29 N·9 S·411B "n:/..ver,v31425":"version,v1" -15:48:32.463710 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -15:48:32.474610 table@compaction committed F-2 S-86KiB Ke·0 D·10923 T·30.674873ms -15:48:32.475446 table@remove removed @26 -15:48:32.475684 table@remove removed @23 -15:48:32.475888 table@remove removed @22 -=============== Jul 12, 2018 (BST) =============== -16:05:29.136315 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:05:29.136476 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -16:05:29.136490 db@open opening -16:05:29.136531 journal@recovery F·1 -16:05:29.137978 journal@recovery recovering @27 -16:05:29.150419 memdb@flush created L0@30 N·2756 S·22KiB "n:/..ver,v34160":"n:\xdc..ong,v31463" -16:05:29.154204 version@stat F·[1 1] S·22KiB[22KiB 411B] Sc·[0.25 0.00] -16:05:29.169283 db@janitor F·4 G·0 -16:05:29.169318 db@open done T·32.818144ms -=============== Jul 12, 2018 (BST) =============== -16:23:49.780860 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:23:49.781083 version@stat F·[1 1] S·22KiB[22KiB 411B] Sc·[0.25 0.00] -16:23:49.781094 db@open opening -16:23:49.781139 journal@recovery F·1 -16:23:49.783143 journal@recovery recovering @31 -16:23:49.798476 memdb@flush created L0@33 N·2969 S·23KiB "n:/..ver,v37138":"n:\xdc..ong,v34222" -16:23:49.800475 version@stat F·[2 1] S·46KiB[45KiB 411B] Sc·[0.50 0.00] -16:23:49.816411 db@janitor F·5 G·0 -16:23:49.816455 db@open done T·35.352587ms -16:23:49.819583 table@compaction L0·2 -> L1·1 S·46KiB Q·37183 -16:23:49.830423 table@build created L1@36 N·9 S·414B "n:/..ver,v37138":"version,v1" -16:23:49.830470 version@stat F·[0 1] S·414B[0B 414B] Sc·[0.00 0.00] -16:23:49.837858 table@compaction committed F-2 S-45KiB Ke·0 D·5725 T·18.203746ms -16:23:49.837969 table@remove removed @33 -16:23:49.838055 table@remove removed @30 -16:23:49.838127 table@remove removed @29 -=============== Jul 12, 2018 (BST) =============== -16:40:12.766097 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:40:12.766286 version@stat F·[0 1] S·414B[0B 414B] Sc·[0.00 0.00] -16:40:12.766303 db@open opening -16:40:12.766353 journal@recovery F·1 -16:40:12.767975 journal@recovery recovering @34 -16:40:12.788242 memdb@flush created L0@37 N·2691 S·21KiB "n:/..ver,v39825":"n:\xdc..ong,v37186" -16:40:12.790316 version@stat F·[1 1] S·21KiB[21KiB 414B] Sc·[0.25 0.00] -16:40:12.807288 db@janitor F·4 G·0 -16:40:12.807344 db@open done T·41.030612ms -=============== Jul 12, 2018 (BST) =============== -16:57:40.476499 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:57:40.476704 version@stat F·[1 1] S·21KiB[21KiB 414B] Sc·[0.25 0.00] -16:57:40.476721 db@open opening -16:57:40.476773 journal@recovery F·1 -16:57:40.478538 journal@recovery recovering @38 -16:57:40.498173 memdb@flush created L0@40 N·2859 S·22KiB "n:/..ver,v42662":"n:\xdc..ong,v39883" -16:57:40.500177 version@stat F·[2 1] S·44KiB[44KiB 414B] Sc·[0.50 0.00] -16:57:40.516286 db@janitor F·5 G·0 -16:57:40.516360 db@open done T·39.628863ms -16:57:40.519300 table@compaction L0·2 -> L1·1 S·44KiB Q·42735 -16:57:40.541025 table@build created L1@43 N·9 S·410B "n:/..ver,v42662":"version,v1" -16:57:40.541082 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -16:57:40.548370 table@compaction committed F-2 S-44KiB Ke·0 D·5550 T·29.0303ms -16:57:40.548461 table@remove removed @40 -16:57:40.548509 table@remove removed @37 -16:57:40.548546 table@remove removed @36 -21:32:14.584473 memdb@flush N·43076 S·3MiB -21:32:14.692832 memdb@flush created L0@45 N·43076 S·339KiB "n:/..ver,v85802":"n:\xdc..ong,v42742" -21:32:14.692986 version@stat F·[1 1] S·339KiB[339KiB 410B] Sc·[0.25 0.00] -21:32:14.700477 memdb@flush committed F·1 T·115.839092ms -21:32:14.703567 journal@remove removed @41 -=============== Jul 13, 2018 (BST) =============== -02:05:39.815476 memdb@flush N·43069 S·3MiB -02:05:39.872158 memdb@flush created L0@47 N·43069 S·339KiB "n:/..ver,v128805":"n:\xdc..ong,v85814" -02:05:39.872235 version@stat F·[2 1] S·678KiB[678KiB 410B] Sc·[0.50 0.00] -02:05:39.879305 memdb@flush committed F·1 T·63.555708ms -02:05:39.880183 journal@remove removed @44 -06:37:33.787625 memdb@flush N·43071 S·3MiB -06:37:33.893979 memdb@flush created L0@49 N·43071 S·339KiB "n:/..ver,v171892":"n:\xdc..ong,v128889" -06:37:33.894267 version@stat F·[3 1] S·1018KiB[1017KiB 410B] Sc·[0.75 0.00] -06:37:33.902288 memdb@flush committed F·1 T·114.464773ms -06:37:33.906695 journal@remove removed @46 -=============== Jul 13, 2018 (BST) =============== -11:03:48.235622 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:03:48.235894 version@stat F·[3 1] S·1018KiB[1017KiB 410B] Sc·[0.75 0.00] -11:03:48.235928 db@open opening -11:03:48.236034 journal@recovery F·1 -11:03:48.240081 journal@recovery recovering @48 -11:03:48.351031 memdb@flush created L0@50 N·40869 S·322KiB "n:/..ver,v212809":"n:\xdc..ong,v171953" -11:03:48.355511 version@stat F·[4 1] S·1MiB[1MiB 410B] Sc·[1.00 0.00] -11:03:48.386506 db@janitor F·7 G·0 -11:03:48.386588 db@open done T·150.644258ms -11:03:48.386779 table@compaction L0·4 -> L1·1 S·1MiB Q·212821 -11:03:48.552028 table@build created L1@53 N·9 S·410B "n:/..ver,v212809":"version,v1" -11:03:48.552698 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -11:03:48.563808 table@compaction committed F-4 S-1MiB Ke·0 D·170085 T·176.390695ms -11:03:48.563964 table@remove removed @50 -11:03:48.564085 table@remove removed @49 -11:03:48.564184 table@remove removed @47 -11:03:48.564276 table@remove removed @45 -11:03:48.564312 table@remove removed @43 -=============== Jul 13, 2018 (BST) =============== -11:20:12.172435 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:20:12.172632 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -11:20:12.172647 db@open opening -11:20:12.172701 journal@recovery F·1 -11:20:12.174313 journal@recovery recovering @51 -11:20:12.246336 memdb@flush created L0@54 N·2676 S·21KiB "n:/..ver,v215430":"n:\xdc..ong,v212828" -11:20:12.248717 version@stat F·[1 1] S·21KiB[21KiB 410B] Sc·[0.25 0.00] -11:20:12.275257 db@janitor F·4 G·0 -11:20:12.275381 db@open done T·102.722613ms -=============== Jul 13, 2018 (BST) =============== -11:22:05.338759 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:22:05.338930 version@stat F·[1 1] S·21KiB[21KiB 410B] Sc·[0.25 0.00] -11:22:05.338942 db@open opening -11:22:05.338994 journal@recovery F·1 -11:22:05.340616 journal@recovery recovering @55 -11:22:05.396300 memdb@flush created L0@57 N·326 S·2KiB "n:/..ver,v215775":"n:\xdc..ong,v215506" -11:22:05.398077 version@stat F·[2 1] S·24KiB[24KiB 410B] Sc·[0.50 0.00] -11:22:05.414879 db@janitor F·5 G·0 -11:22:05.414913 db@open done T·75.962832ms -11:22:05.420289 table@compaction L0·2 -> L1·1 S·24KiB Q·215825 -11:22:05.434036 table@build created L1@60 N·9 S·401B "n:/..ver,v215775":"version,v1" -11:22:05.434096 version@stat F·[0 1] S·401B[0B 401B] Sc·[0.00 0.00] -11:22:05.462717 table@compaction committed F-2 S-24KiB Ke·0 D·3002 T·42.360212ms -11:22:05.462903 table@remove removed @57 -11:22:05.462991 table@remove removed @54 -11:22:05.463079 table@remove removed @53 -=============== Jul 13, 2018 (BST) =============== -11:28:36.626934 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:28:36.627111 version@stat F·[0 1] S·401B[0B 401B] Sc·[0.00 0.00] -11:28:36.627126 db@open opening -11:28:36.627182 journal@recovery F·1 -11:28:36.628843 journal@recovery recovering @58 -11:28:36.669496 memdb@flush created L0@61 N·992 S·8KiB "n:/..ver,v216740":"n:\xdc..ong,v215836" -11:28:36.671600 version@stat F·[1 1] S·8KiB[8KiB 401B] Sc·[0.25 0.00] -11:28:36.695725 db@janitor F·4 G·0 -11:28:36.695752 db@open done T·68.61716ms -=============== Jul 13, 2018 (BST) =============== -11:41:22.637074 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:22.637293 version@stat F·[1 1] S·8KiB[8KiB 401B] Sc·[0.25 0.00] -11:41:22.637310 db@open opening -11:41:22.637367 journal@recovery F·1 -11:41:22.638986 journal@recovery recovering @62 -11:41:22.703922 memdb@flush created L0@64 N·2080 S·16KiB "n:/..ver,v218865":"n:\xdc..ong,v216821" -11:41:22.705642 version@stat F·[2 1] S·25KiB[24KiB 401B] Sc·[0.50 0.00] -11:41:22.721609 db@janitor F·5 G·0 -11:41:22.724802 db@open done T·87.477513ms -11:41:22.728946 table@compaction L0·2 -> L1·1 S·25KiB Q·218899 -11:41:22.740990 table@build created L1@67 N·9 S·408B "n:/..ver,v218865":"version,v1" -11:41:22.741188 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] -11:41:22.759699 table@compaction committed F-2 S-24KiB Ke·0 D·3072 T·30.552034ms -11:41:22.760600 table@remove removed @64 -11:41:22.761139 table@remove removed @61 -11:41:22.761635 table@remove removed @60 -=============== Jul 13, 2018 (BST) =============== -13:24:31.284459 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:24:31.284658 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] -13:24:31.284683 db@open opening -13:24:31.284735 journal@recovery F·1 -13:24:31.286418 journal@recovery recovering @65 -13:24:31.369979 memdb@flush created L0@68 N·16357 S·129KiB "n:/..ver,v235239":"n:\xdc..ong,v218917" -13:24:31.372433 version@stat F·[1 1] S·129KiB[129KiB 408B] Sc·[0.25 0.00] -13:24:31.394761 db@janitor F·4 G·0 -13:24:31.394830 db@open done T·110.133266ms -=============== Jul 13, 2018 (BST) =============== -13:27:15.742235 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:27:15.743321 version@stat F·[1 1] S·129KiB[129KiB 408B] Sc·[0.25 0.00] -13:27:15.743503 db@open opening -13:27:15.743822 journal@recovery F·1 -13:27:15.751341 journal@recovery recovering @69 -13:27:15.810920 memdb@flush created L0@71 N·394 S·3KiB "n:/..ver,v235588":"n:\xdc..ong,v235275" -13:27:15.820870 version@stat F·[2 1] S·132KiB[132KiB 408B] Sc·[0.50 0.00] -13:27:15.839116 db@janitor F·5 G·0 -13:27:15.839339 db@open done T·95.783547ms -13:27:15.849542 table@compaction L0·2 -> L1·1 S·132KiB Q·235652 -13:27:15.883921 table@build created L1@74 N·9 S·413B "n:/..ver,v235588":"version,v1" -13:27:15.884019 version@stat F·[0 1] S·413B[0B 413B] Sc·[0.00 0.00] -13:27:15.891314 table@compaction committed F-2 S-132KiB Ke·0 D·16751 T·41.628392ms -13:27:15.891618 table@remove removed @71 -13:27:15.891721 table@remove removed @68 -13:27:15.891789 table@remove removed @67 -=============== Jul 13, 2018 (BST) =============== -13:35:13.735863 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:35:13.736583 version@stat F·[0 1] S·413B[0B 413B] Sc·[0.00 0.00] -13:35:13.736659 db@open opening -13:35:13.736879 journal@recovery F·1 -13:35:13.741447 journal@recovery recovering @72 -13:35:13.797063 memdb@flush created L0@75 N·153 S·1KiB "n:/..ail,v235686":"n:\xdc..ong,v235655" -13:35:13.804399 version@stat F·[1 1] S·1KiB[1KiB 413B] Sc·[0.25 0.00] -13:35:13.828011 db@janitor F·4 G·0 -13:35:13.828164 db@open done T·91.465186ms -13:35:15.051483 table@compaction L0·1 -> L1·1 S·1KiB Q·235831 -13:35:15.061764 table@build created L1@78 N·9 S·420B "n:/..ver,v235588":"version,v1" -13:35:15.062042 version@stat F·[0 1] S·420B[0B 420B] Sc·[0.00 0.00] -13:35:15.076736 table@compaction committed F-1 S-1KiB Ke·0 D·153 T·25.084612ms -13:35:15.077060 table@remove removed @75 -13:35:15.077330 table@remove removed @74 -=============== Jul 13, 2018 (BST) =============== -13:51:55.002019 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:51:55.002206 version@stat F·[0 1] S·420B[0B 420B] Sc·[0.00 0.00] -13:51:55.002219 db@open opening -13:51:55.002266 journal@recovery F·1 -13:51:55.004461 journal@recovery recovering @76 -13:51:55.029814 memdb@flush created L0@79 N·3645 S·137KiB "n:\x00..ail,v237491":"n:\xff..ing,v237554" -13:51:55.031961 version@stat F·[1 1] S·137KiB[137KiB 420B] Sc·[0.25 0.00] -13:51:55.048183 db@janitor F·4 G·0 -13:51:55.048215 db@open done T·45.987338ms -13:51:55.890342 table@compaction L0·1 -> L1·1 S·137KiB Q·239485 -13:51:55.906745 table@build created L1@82 N·2789 S·128KiB "n:\x00..ail,v237491":"version,v1" -13:51:55.906887 version@stat F·[0 1] S·128KiB[0B 128KiB] Sc·[0.00 0.00] -13:51:55.925112 table@compaction committed F-1 S-9KiB Ke·0 D·865 T·34.729153ms -13:51:55.925522 table@remove removed @79 -13:51:55.925786 table@remove removed @78 -=============== Jul 13, 2018 (BST) =============== -13:56:20.471399 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:56:20.471552 version@stat F·[0 1] S·128KiB[0B 128KiB] Sc·[0.00 0.00] -13:56:20.471567 db@open opening -13:56:20.471609 journal@recovery F·1 -13:56:20.472908 journal@recovery recovering @80 -13:56:20.542136 memdb@flush created L0@83 N·6533 S·242KiB "n:\x00..ing,v245815":"n:\xff..ing,v244816" -13:56:20.543934 version@stat F·[1 1] S·370KiB[242KiB 128KiB] Sc·[0.25 0.00] -13:56:20.559735 db@janitor F·4 G·0 -13:56:20.559777 db@open done T·88.197042ms -13:56:20.693865 table@compaction L0·1 -> L1·1 S·370KiB Q·245999 -13:56:20.712228 table@build created L1@86 N·7473 S·344KiB "n:\x00..ing,v245815":"version,v1" -13:56:20.712304 version@stat F·[0 1] S·344KiB[0B 344KiB] Sc·[0.00 0.00] -13:56:20.719453 table@compaction committed F-1 S-25KiB Ke·0 D·1849 T·25.531715ms -13:56:20.724192 table@remove removed @83 -13:56:20.724394 table@remove removed @82 -13:56:20.727645 db@close closing -13:56:20.727690 db@close done T·44.056µs diff --git a/poa-network/multi-peer/node1/geth/nodes/MANIFEST-000085 b/poa-network/multi-peer/node1/geth/nodes/MANIFEST-000085 deleted file mode 100644 index ad17958f5f75b41405238ad037bafb2a3008b009..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 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 JMrI}!1^~s!4paaD diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000002.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000002.ldb deleted file mode 100644 index c5bc9bfa773d6ad0b7dece0e64f30b64e9513800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 987 zcmeC={}9Tc(amT%XJS*&_TtxhZAWHA9eb=RZMnAPkGAK-z|Q?28)UN{FtRX!!H>=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsGqfv7>Ai1H+Dg zK5X-R*jO}z>sB+fFtYM)V+mYP_mF|1fsv76L0vFAqpC>*7=W?>Fisg5oxKCJ(%|NPo4l9NM0C-xfx7mS-9y}FeoyoW#*Km7U|`rmZj#TB&7arv71c>qzP=O@YRJI#6=i5neQYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=&~ggKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0QHestpET3 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000008.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000008.ldb deleted file mode 100644 index d2b26a1513df62490165abb9178df47524827180..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(5igKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7araSq}muu(H6 uxR{8GFmN)bG5+Ud)L=LX5{1|jQh)Z?Q%3!nOkyA*{2=^yL$^w)`)vRx>RJN; diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000011.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000011.ldb deleted file mode 100644 index df591285ec4a5126c6edcfcaadbe0d6cdbf90ba3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(2hgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(8jgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c40gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0Gb3^x&QzG diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000020.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000020.ldb deleted file mode 100644 index 0f885d9e99a6ddfd068f3d58435204b29fb142a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cA2gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c71gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cD3gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qiLgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm8l$aRU zK%$&L%*|leYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qoNgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qlMgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmH7Hgo`4N=yuF zAW=>r=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r05HB;{Qv*} diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000038.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000038.ldb deleted file mode 100644 index a05ec3826f2c34a6199189d16cc0a8392e95cf55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qrOgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*08mI;GXMYp diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000041.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000041.ldb deleted file mode 100644 index c8f05dd77cbe3eac74780b6ebaab315d0e462feb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANm$gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm?x!EOeQgq5PlH;yP;d9)crO9n~Yko diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000044.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000044.ldb deleted file mode 100644 index 627147b4d7b2f480a6a51150b612a39211a8ccf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANs&gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANp%gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANv(gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0AdtcNB{r; diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000053.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000053.ldb deleted file mode 100644 index 32548614e07c2dcfdabd893cf97d080abd9721d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HL=gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0A*QPO8@`> diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/000056.ldb b/poa-network/multi-peer/node2/geth/lightchaindata/000056.ldb deleted file mode 100644 index 3c07eed7394d4b6511ac7fd9c724fdf5e2425875..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HR?gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HO>gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HU@gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*09Bb=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yasH{-NVsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsGqfv7>Ai1H+Dg zK5X-R*jO}z>sB+fFtYM)V+mYP_mF|1fsv76L0vFAqpC>*7=W?>Fisg5e|={<9Nkcn z5m^|-d90&5>A|$8fAR#_K=Q&s%*|jj%fd~+f3fmGuM N;lCTYRZ87&0|27!N`(Lb diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/CURRENT b/poa-network/multi-peer/node2/geth/lightchaindata/CURRENT deleted file mode 100644 index 5d746f2..0000000 --- a/poa-network/multi-peer/node2/geth/lightchaindata/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000064 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/LOCK b/poa-network/multi-peer/node2/geth/lightchaindata/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/LOG b/poa-network/multi-peer/node2/geth/lightchaindata/LOG deleted file mode 100644 index 00afeb7..0000000 --- a/poa-network/multi-peer/node2/geth/lightchaindata/LOG +++ /dev/null @@ -1,233 +0,0 @@ -=============== Jul 12, 2018 (BST) =============== -11:09:03.617505 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:09:03.638619 db@open opening -11:09:03.639109 version@stat F·[] S·0B[] Sc·[] -11:09:03.659830 db@janitor F·2 G·0 -11:09:03.659867 db@open done T·21.106833ms -=============== Jul 12, 2018 (BST) =============== -11:24:28.339167 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:24:28.339267 version@stat F·[] S·0B[] Sc·[] -11:24:28.339277 db@open opening -11:24:28.339319 journal@recovery F·1 -11:24:28.339676 journal@recovery recovering @1 -11:24:28.347346 memdb@flush created L0@2 N·14 S·987B "9\x9c\x91..\x1dj\xe0,v4":"\xdb7C..b\xf5\xdc,v5" -11:24:28.347554 version@stat F·[1] S·987B[987B] Sc·[0.25] -11:24:28.366952 db@janitor F·3 G·0 -11:24:28.366980 db@open done T·27.695431ms -=============== Jul 12, 2018 (BST) =============== -11:27:21.708765 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:27:21.708882 version@stat F·[1] S·987B[987B] Sc·[0.25] -11:27:21.708892 db@open opening -11:27:21.708937 journal@recovery F·1 -11:27:21.709348 journal@recovery recovering @3 -11:27:21.717125 memdb@flush created L0@5 N·1 S·356B "eth..\x0e/(,v16":"eth..\x0e/(,v16" -11:27:21.717337 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] -11:27:21.747896 db@janitor F·4 G·0 -11:27:21.747933 db@open done T·39.033522ms -=============== Jul 12, 2018 (BST) =============== -11:34:06.126463 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:34:06.126604 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] -11:34:06.126618 db@open opening -11:34:06.126667 journal@recovery F·1 -11:34:06.127050 journal@recovery recovering @6 -11:34:06.134863 memdb@flush created L0@8 N·1 S·356B "eth..\x0e/(,v18":"eth..\x0e/(,v18" -11:34:06.135048 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] -11:34:06.150716 db@janitor F·5 G·0 -11:34:06.150741 db@open done T·24.114611ms -=============== Jul 12, 2018 (BST) =============== -11:53:46.820694 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:53:46.820798 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] -11:53:46.820810 db@open opening -11:53:46.820864 journal@recovery F·1 -11:53:46.821297 journal@recovery recovering @9 -11:53:46.831626 memdb@flush created L0@11 N·1 S·356B "eth..\x0e/(,v20":"eth..\x0e/(,v20" -11:53:46.831818 version@stat F·[4] S·2KiB[2KiB] Sc·[1.00] -11:53:46.846405 db@janitor F·6 G·0 -11:53:46.846432 db@open done T·25.614964ms -11:53:46.847063 table@compaction L0·4 -> L1·0 S·2KiB Q·22 -=============== Jul 12, 2018 (BST) =============== -14:17:42.392536 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:17:42.395630 version@stat F·[4] S·2KiB[2KiB] Sc·[1.00] -14:17:42.395645 db@open opening -14:17:42.395694 journal@recovery F·1 -14:17:42.395969 journal@recovery recovering @12 -14:17:42.413553 memdb@flush created L0@14 N·1 S·356B "eth..\x0e/(,v22":"eth..\x0e/(,v22" -14:17:42.414591 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] -14:17:42.442813 db@janitor F·7 G·0 -14:17:42.442842 db@open done T·47.187651ms -14:17:42.442909 table@compaction L0·5 -> L1·0 S·2KiB Q·23 -=============== Jul 12, 2018 (BST) =============== -14:39:49.043706 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:39:49.043821 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] -14:39:49.043835 db@open opening -14:39:49.043899 journal@recovery F·1 -14:39:49.044289 journal@recovery recovering @15 -14:39:49.051780 memdb@flush created L0@17 N·1 S·356B "eth..\x0e/(,v24":"eth..\x0e/(,v24" -14:39:49.052391 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] -14:39:49.081746 db@janitor F·8 G·0 -14:39:49.081769 db@open done T·37.92478ms -=============== Jul 12, 2018 (BST) =============== -15:37:17.901222 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:37:17.901345 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] -15:37:17.901358 db@open opening -15:37:17.901421 journal@recovery F·1 -15:37:17.901850 journal@recovery recovering @18 -15:37:17.910929 memdb@flush created L0@20 N·1 S·356B "eth..\x0e/(,v26":"eth..\x0e/(,v26" -15:37:17.911100 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] -15:37:17.925999 db@janitor F·9 G·0 -15:37:17.926024 db@open done T·24.65714ms -15:37:17.927077 table@compaction L0·7 -> L1·0 S·3KiB Q·27 -=============== Jul 12, 2018 (BST) =============== -15:48:30.025065 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:48:30.025198 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] -15:48:30.025211 db@open opening -15:48:30.025278 journal@recovery F·1 -15:48:30.025786 journal@recovery recovering @21 -15:48:30.038226 memdb@flush created L0@23 N·1 S·356B "eth..\x0e/(,v28":"eth..\x0e/(,v28" -15:48:30.038417 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] -15:48:30.066147 db@janitor F·10 G·0 -15:48:30.066173 db@open done T·40.953875ms -15:48:30.066226 table@compaction L0·8 -> L1·0 S·3KiB Q·29 -=============== Jul 12, 2018 (BST) =============== -16:05:26.776151 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:05:26.776271 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] -16:05:26.776283 db@open opening -16:05:26.776346 journal@recovery F·1 -16:05:26.776757 journal@recovery recovering @24 -16:05:26.787652 memdb@flush created L0@26 N·1 S·356B "eth..\x0e/(,v30":"eth..\x0e/(,v30" -16:05:26.789490 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] -16:05:26.816798 db@janitor F·11 G·0 -16:05:26.816853 db@open done T·40.562165ms -16:05:26.817677 table@compaction L0·9 -> L1·0 S·3KiB Q·31 -=============== Jul 12, 2018 (BST) =============== -16:23:47.409548 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:23:47.409692 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] -16:23:47.409705 db@open opening -16:23:47.409772 journal@recovery F·1 -16:23:47.410167 journal@recovery recovering @27 -16:23:47.423566 memdb@flush created L0@29 N·1 S·356B "eth..\x0e/(,v32":"eth..\x0e/(,v32" -16:23:47.423748 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] -16:23:47.446201 db@janitor F·12 G·0 -16:23:47.446221 db@open done T·36.509905ms -16:23:47.446274 table@compaction L0·10 -> L1·0 S·4KiB Q·33 -=============== Jul 12, 2018 (BST) =============== -16:40:10.390435 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:40:10.390563 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] -16:40:10.390577 db@open opening -16:40:10.390649 journal@recovery F·1 -16:40:10.391101 journal@recovery recovering @30 -16:40:10.411407 memdb@flush created L0@32 N·1 S·356B "eth..\x0e/(,v34":"eth..\x0e/(,v34" -16:40:10.411625 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] -16:40:10.440987 db@janitor F·13 G·0 -16:40:10.441011 db@open done T·50.42733ms -16:40:10.441063 table@compaction L0·11 -> L1·0 S·4KiB Q·35 -=============== Jul 12, 2018 (BST) =============== -16:57:38.124701 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:57:38.124826 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] -16:57:38.124838 db@open opening -16:57:38.124894 journal@recovery F·1 -16:57:38.125141 journal@recovery recovering @33 -16:57:38.138032 memdb@flush created L0@35 N·1 S·356B "eth..\x0e/(,v36":"eth..\x0e/(,v36" -16:57:38.138332 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] -16:57:38.159988 db@janitor F·14 G·0 -16:57:38.160014 db@open done T·35.167225ms -16:57:38.160670 table@compaction L0·12 -> L1·0 S·4KiB Q·37 -=============== Jul 13, 2018 (BST) =============== -11:03:46.000460 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:03:46.000607 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] -11:03:46.000618 db@open opening -11:03:46.000698 journal@recovery F·1 -11:03:46.001141 journal@recovery recovering @36 -11:03:46.008992 memdb@flush created L0@38 N·1 S·356B "eth..\x0e/(,v38":"eth..\x0e/(,v38" -11:03:46.009163 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] -11:03:46.023882 db@janitor F·15 G·0 -11:03:46.023908 db@open done T·23.283363ms -11:03:46.023980 table@compaction L0·13 -> L1·0 S·5KiB Q·39 -=============== Jul 13, 2018 (BST) =============== -11:20:09.942969 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:20:09.943598 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] -11:20:09.943626 db@open opening -11:20:09.943722 journal@recovery F·1 -11:20:09.947317 journal@recovery recovering @39 -11:20:09.958460 memdb@flush created L0@41 N·1 S·356B "eth..\x0e/(,v40":"eth..\x0e/(,v40" -11:20:09.959885 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] -11:20:09.975584 db@janitor F·16 G·0 -11:20:09.975619 db@open done T·31.977474ms -11:20:09.976379 table@compaction L0·14 -> L1·0 S·5KiB Q·41 -=============== Jul 13, 2018 (BST) =============== -11:22:02.953772 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:22:02.954444 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] -11:22:02.954479 db@open opening -11:22:02.954598 journal@recovery F·1 -11:22:02.966261 journal@recovery recovering @42 -11:22:02.978212 memdb@flush created L0@44 N·1 S·356B "eth..\x0e/(,v42":"eth..\x0e/(,v42" -11:22:02.978765 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] -11:22:02.999921 db@janitor F·17 G·0 -11:22:02.999956 db@open done T·45.466851ms -11:22:03.000743 table@compaction L0·15 -> L1·0 S·5KiB Q·43 -=============== Jul 13, 2018 (BST) =============== -11:28:34.365499 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:28:34.365667 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] -11:28:34.365687 db@open opening -11:28:34.365776 journal@recovery F·1 -11:28:34.367127 journal@recovery recovering @45 -11:28:34.380594 memdb@flush created L0@47 N·1 S·356B "eth..\x0e/(,v44":"eth..\x0e/(,v44" -11:28:34.380999 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] -11:28:34.403500 db@janitor F·18 G·0 -11:28:34.403536 db@open done T·37.840488ms -11:28:34.403948 table@compaction L0·16 -> L1·0 S·6KiB Q·45 -=============== Jul 13, 2018 (BST) =============== -11:41:30.386027 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:30.386185 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] -11:41:30.386203 db@open opening -11:41:30.386272 journal@recovery F·1 -11:41:30.386659 journal@recovery recovering @48 -11:41:30.394072 memdb@flush created L0@50 N·1 S·356B "eth..\x0e/(,v46":"eth..\x0e/(,v46" -11:41:30.394334 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] -11:41:30.410389 db@janitor F·19 G·0 -11:41:30.410973 db@open done T·24.760035ms -11:41:30.411851 table@compaction L0·17 -> L1·0 S·6KiB Q·47 -=============== Jul 13, 2018 (BST) =============== -13:24:39.113379 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:24:39.113565 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] -13:24:39.113598 db@open opening -13:24:39.113722 journal@recovery F·1 -13:24:39.114072 journal@recovery recovering @51 -13:24:39.121664 memdb@flush created L0@53 N·1 S·356B "eth..\x0e/(,v48":"eth..\x0e/(,v48" -13:24:39.121894 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] -13:24:39.136887 db@janitor F·20 G·0 -13:24:39.136917 db@open done T·23.308508ms -13:24:39.137816 table@compaction L0·18 -> L1·0 S·6KiB Q·49 -=============== Jul 13, 2018 (BST) =============== -13:52:02.783904 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:52:02.784074 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] -13:52:02.784090 db@open opening -13:52:02.784191 journal@recovery F·1 -13:52:02.784731 journal@recovery recovering @54 -13:52:02.792399 memdb@flush created L0@56 N·1 S·356B "eth..\x0e/(,v50":"eth..\x0e/(,v50" -13:52:02.792962 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:52:02.812311 db@janitor F·21 G·0 -13:52:02.812344 db@open done T·28.246007ms -13:52:02.813292 table@compaction L0·19 -> L1·0 S·7KiB Q·51 -=============== Jul 13, 2018 (BST) =============== -13:54:48.028647 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:54:48.028894 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:54:48.028938 db@open opening -13:54:48.029064 journal@recovery F·1 -13:54:48.033855 journal@recovery recovering @57 -13:54:48.047941 memdb@flush created L0@59 N·1 S·356B "eth..\x0e/(,v52":"eth..\x0e/(,v52" -13:54:48.048867 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] -13:54:48.066743 db@janitor F·22 G·0 -13:54:48.066802 db@open done T·37.834349ms -13:54:48.066923 table@compaction L0·20 -> L1·0 S·7KiB Q·53 -=============== Jul 13, 2018 (BST) =============== -13:56:28.259191 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:56:28.259335 version@stat F·[20] S·7KiB[7KiB] Sc·[5.00] -13:56:28.259356 db@open opening -13:56:28.259431 journal@recovery F·1 -13:56:28.259674 journal@recovery recovering @60 -13:56:28.267252 memdb@flush created L0@62 N·1 S·356B "eth..\x0e/(,v54":"eth..\x0e/(,v54" -13:56:28.267455 version@stat F·[21] S·7KiB[7KiB] Sc·[5.25] -13:56:28.283089 db@janitor F·23 G·0 -13:56:28.283173 db@open done T·23.806964ms -13:56:28.283266 table@compaction L0·21 -> L1·0 S·7KiB Q·55 diff --git a/poa-network/multi-peer/node2/geth/lightchaindata/MANIFEST-000064 b/poa-network/multi-peer/node2/geth/lightchaindata/MANIFEST-000064 deleted file mode 100644 index 9369821faad1fcdeac1e6ac332f6f63fe209349b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2627 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åDKpB@N6q_Y4h+hPcQRBbDD%QXW^9FTkcO~ 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ⅈ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 z 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 diff --git a/poa-network/multi-peer/node2/geth/nodes/CURRENT b/poa-network/multi-peer/node2/geth/nodes/CURRENT deleted file mode 100644 index c7a124b..0000000 --- a/poa-network/multi-peer/node2/geth/nodes/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000077 diff --git a/poa-network/multi-peer/node2/geth/nodes/LOCK b/poa-network/multi-peer/node2/geth/nodes/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/poa-network/multi-peer/node2/geth/nodes/LOG b/poa-network/multi-peer/node2/geth/nodes/LOG deleted file mode 100644 index d21ed53..0000000 --- a/poa-network/multi-peer/node2/geth/nodes/LOG +++ /dev/null @@ -1,299 +0,0 @@ -=============== Jul 12, 2018 (BST) =============== -11:09:05.859266 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:09:05.881724 db@open opening -11:09:05.886827 version@stat F·[] S·0B[] Sc·[] -11:09:05.902200 db@janitor F·2 G·0 -11:09:05.902230 db@open done T·20.463441ms -=============== Jul 12, 2018 (BST) =============== -11:24:30.549578 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:24:30.549938 version@stat F·[] S·0B[] Sc·[] -11:24:30.549967 db@open opening -11:24:30.550069 journal@recovery F·1 -11:24:30.555568 journal@recovery recovering @1 -11:24:30.575186 memdb@flush created L0@2 N·1953 S·15KiB "n:\xbb..ver,v1870":"version,v1" -11:24:30.579660 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] -11:24:30.598959 db@janitor F·3 G·0 -11:24:30.599047 db@open done T·49.061622ms -=============== Jul 12, 2018 (BST) =============== -11:27:23.929314 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:27:23.929673 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] -11:27:23.929707 db@open opening -11:27:23.929818 journal@recovery F·1 -11:27:23.933816 journal@recovery recovering @3 -11:27:23.944145 memdb@flush created L0@5 N·155 S·1KiB "n:\xbb..ver,v2057":"n:\xdc..ong,v1961" -11:27:23.948584 version@stat F·[2] S·17KiB[17KiB] Sc·[0.50] -11:27:23.965318 db@janitor F·4 G·0 -11:27:23.965391 db@open done T·35.663326ms -11:27:23.969673 table@compaction L0·2 -> L1·0 S·17KiB Q·2110 -11:27:23.983676 table@build created L1@8 N·9 S·411B "n:\xbb..ver,v2057":"version,v1" -11:27:23.983838 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:27:24.000730 table@compaction committed F-1 S-16KiB Ke·0 D·2099 T·30.949886ms -11:27:24.000800 table@remove removed @5 -11:27:24.000839 table@remove removed @2 -=============== Jul 12, 2018 (BST) =============== -11:34:08.322462 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:34:08.322604 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:34:08.322614 db@open opening -11:34:08.322650 journal@recovery F·1 -11:34:08.324145 journal@recovery recovering @6 -11:34:08.351791 memdb@flush created L0@9 N·957 S·7KiB "n:\xbb..ver,v3049":"n:\xdc..ong,v2117" -11:34:08.356450 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] -11:34:08.382422 db@janitor F·4 G·0 -11:34:08.382467 db@open done T·59.843968ms -=============== Jul 12, 2018 (BST) =============== -11:53:49.053572 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:53:49.053723 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] -11:53:49.053735 db@open opening -11:53:49.053775 journal@recovery F·1 -11:53:49.055338 journal@recovery recovering @10 -11:53:49.069911 memdb@flush created L0@12 N·3140 S·24KiB "n:\xbb..ver,v6197":"n:\xdc..ong,v3076" -11:53:49.071823 version@stat F·[2 1] S·33KiB[32KiB 411B] Sc·[0.50 0.00] -11:53:49.087260 db@janitor F·5 G·0 -11:53:49.087302 db@open done T·33.558786ms -11:53:49.089173 table@compaction L0·2 -> L1·1 S·33KiB Q·6209 -11:53:49.100536 table@build created L1@15 N·9 S·412B "n:\xbb..ver,v6197":"version,v1" -11:53:49.100861 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] -11:53:49.115649 table@compaction committed F-2 S-32KiB Ke·0 D·4097 T·26.423679ms -11:53:49.115759 table@remove removed @12 -11:53:49.115813 table@remove removed @9 -11:53:49.115854 table@remove removed @8 -=============== Jul 12, 2018 (BST) =============== -14:17:44.682705 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:17:44.683753 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] -14:17:44.683816 db@open opening -14:17:44.683982 journal@recovery F·1 -14:17:44.689029 journal@recovery recovering @13 -14:17:44.749579 memdb@flush created L0@16 N·10616 S·83KiB "n:\xbb..ver,v16777":"n:\xdc..ong,v6212" -14:17:44.750996 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] -14:17:44.779208 db@janitor F·4 G·0 -14:17:44.779238 db@open done T·95.395734ms -=============== Jul 12, 2018 (BST) =============== -14:39:51.265662 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:39:51.265819 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] -14:39:51.265832 db@open opening -14:39:51.265875 journal@recovery F·1 -14:39:51.267251 journal@recovery recovering @17 -14:39:51.282847 memdb@flush created L0@19 N·3518 S·28KiB "n:\xbb..ver,v20335":"n:\xdc..ong,v16833" -14:39:51.284827 version@stat F·[2 1] S·112KiB[112KiB 412B] Sc·[0.50 0.00] -14:39:51.304139 db@janitor F·5 G·0 -14:39:51.304178 db@open done T·38.337769ms -14:39:51.306434 table@compaction L0·2 -> L1·1 S·112KiB Q·20345 -14:39:51.328923 table@build created L1@22 N·9 S·410B "n:\xbb..ver,v20335":"version,v1" -14:39:51.329000 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -14:39:51.352502 table@compaction committed F-2 S-112KiB Ke·0 D·14134 T·46.026738ms -14:39:51.352618 table@remove removed @19 -14:39:51.352681 table@remove removed @16 -14:39:51.352719 table@remove removed @15 -=============== Jul 12, 2018 (BST) =============== -15:37:20.124805 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:37:20.125293 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -15:37:20.125338 db@open opening -15:37:20.125492 journal@recovery F·1 -15:37:20.131018 journal@recovery recovering @20 -15:37:20.167319 memdb@flush created L0@23 N·9030 S·71KiB "n:\xbb..ver,v29311":"n:\xdc..ong,v20356" -15:37:20.170842 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] -15:37:20.187160 db@janitor F·4 G·0 -15:37:20.187230 db@open done T·61.857192ms -=============== Jul 12, 2018 (BST) =============== -15:48:32.297828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:48:32.297998 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] -15:48:32.298011 db@open opening -15:48:32.298064 journal@recovery F·1 -15:48:32.299666 journal@recovery recovering @24 -15:48:32.368672 memdb@flush created L0@26 N·1824 S·14KiB "n:\xbb..ver,v31169":"n:\xdc..ong,v29379" -15:48:32.370730 version@stat F·[2 1] S·86KiB[85KiB 410B] Sc·[0.50 0.00] -15:48:32.387501 db@janitor F·5 G·0 -15:48:32.387524 db@open done T·89.5036ms -15:48:32.391376 table@compaction L0·2 -> L1·1 S·86KiB Q·31201 -15:48:32.409611 table@build created L1@29 N·9 S·411B "n:\xbb..ver,v31169":"version,v1" -15:48:32.409682 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -15:48:32.424137 table@compaction committed F-2 S-85KiB Ke·0 D·10854 T·32.684737ms -15:48:32.424229 table@remove removed @26 -15:48:32.424293 table@remove removed @23 -15:48:32.424332 table@remove removed @22 -=============== Jul 12, 2018 (BST) =============== -16:05:29.052109 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:05:29.052302 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -16:05:29.052322 db@open opening -16:05:29.052385 journal@recovery F·1 -16:05:29.053889 journal@recovery recovering @27 -16:05:29.070585 memdb@flush created L0@30 N·2723 S·21KiB "n:\xbb..ver,v33872":"n:\xdc..ong,v31212" -16:05:29.072728 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] -16:05:29.088665 db@janitor F·4 G·0 -16:05:29.088693 db@open done T·36.35836ms -=============== Jul 12, 2018 (BST) =============== -16:23:49.639965 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:23:49.640119 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] -16:23:49.640132 db@open opening -16:23:49.640177 journal@recovery F·1 -16:23:49.641522 journal@recovery recovering @31 -16:23:49.702907 memdb@flush created L0@33 N·2951 S·23KiB "n:\xbb..ver,v36828":"n:\xdc..ong,v33936" -16:23:49.707537 version@stat F·[2 1] S·45KiB[45KiB 411B] Sc·[0.50 0.00] -16:23:49.726802 db@janitor F·5 G·0 -16:23:49.726888 db@open done T·86.744755ms -16:23:49.730542 table@compaction L0·2 -> L1·1 S·45KiB Q·36877 -16:23:49.755043 table@build created L1@36 N·9 S·404B "n:\xbb..ver,v36828":"version,v1" -16:23:49.755142 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] -16:23:49.769539 table@compaction committed F-2 S-45KiB Ke·0 D·5674 T·38.915634ms -16:23:49.769669 table@remove removed @33 -16:23:49.769735 table@remove removed @30 -16:23:49.769777 table@remove removed @29 -=============== Jul 12, 2018 (BST) =============== -16:40:12.633424 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:40:12.633675 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] -16:40:12.633694 db@open opening -16:40:12.633751 journal@recovery F·1 -16:40:12.635430 journal@recovery recovering @34 -16:40:12.653741 memdb@flush created L0@37 N·2658 S·21KiB "n:\xbb..ver,v39480":"n:\xdc..ong,v36880" -16:40:12.655362 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] -16:40:12.672204 db@janitor F·4 G·0 -16:40:12.672249 db@open done T·38.544509ms -=============== Jul 12, 2018 (BST) =============== -16:57:40.345817 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:57:40.345996 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] -16:57:40.346012 db@open opening -16:57:40.346070 journal@recovery F·1 -16:57:40.347980 journal@recovery recovering @38 -16:57:40.363783 memdb@flush created L0@40 N·2786 S·22KiB "n:\xbb..ver,v42253":"n:\xdc..ong,v39543" -16:57:40.365500 version@stat F·[2 1] S·44KiB[43KiB 404B] Sc·[0.50 0.00] -16:57:40.381342 db@janitor F·5 G·0 -16:57:40.381385 db@open done T·35.364738ms -16:57:40.383292 table@compaction L0·2 -> L1·1 S·44KiB Q·42323 -16:57:40.408961 table@build created L1@43 N·9 S·410B "n:\xbb..ver,v42253":"version,v1" -16:57:40.409041 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -16:57:40.423831 table@compaction committed F-2 S-43KiB Ke·0 D·5444 T·40.39884ms -16:57:40.423935 table@remove removed @40 -16:57:40.423986 table@remove removed @37 -16:57:40.424026 table@remove removed @36 -21:39:50.525477 memdb@flush N·43421 S·3MiB -21:39:50.610325 memdb@flush created L0@45 N·43421 S·341KiB "n:\xbb..ver,v85728":"n:\xdc..ong,v42330" -21:39:50.610621 version@stat F·[1 1] S·341KiB[341KiB 410B] Sc·[0.25 0.00] -21:39:50.619942 memdb@flush committed F·1 T·94.239078ms -21:39:50.627386 journal@remove removed @41 -=============== Jul 13, 2018 (BST) =============== -02:22:42.318770 memdb@flush N·43426 S·3MiB -02:22:42.349319 memdb@flush created L0@47 N·43426 S·341KiB "n:\xbb..ver,v129168":"n:\xdc..ong,v85750" -02:22:42.349367 version@stat F·[2 1] S·682KiB[682KiB 410B] Sc·[0.50 0.00] -02:22:42.356398 memdb@flush committed F·1 T·37.578228ms -02:22:42.357339 journal@remove removed @44 -07:04:10.330333 memdb@flush N·43422 S·3MiB -07:04:10.393823 memdb@flush created L0@49 N·43422 S·341KiB "n:\xbb..ver,v172517":"n:\xdc..ong,v129177" -07:04:10.393906 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] -07:04:10.401140 memdb@flush committed F·1 T·70.637042ms -07:04:10.404444 journal@remove removed @46 -=============== Jul 13, 2018 (BST) =============== -11:03:48.229037 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:03:48.229335 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] -11:03:48.229357 db@open opening -11:03:48.229460 journal@recovery F·1 -11:03:48.233070 journal@recovery recovering @48 -11:03:48.333384 memdb@flush created L0@50 N·35960 S·283KiB "n:\xbb..ver,v208539":"n:\xdc..ong,v172602" -11:03:48.335105 version@stat F·[4 1] S·1MiB[1MiB 410B] Sc·[1.00 0.00] -11:03:48.365177 db@janitor F·7 G·0 -11:03:48.365234 db@open done T·135.861856ms -11:03:48.365374 table@compaction L0·4 -> L1·1 S·1MiB Q·208553 -11:03:48.537826 table@build created L1@53 N·9 S·411B "n:\xbb..ver,v208539":"version,v1" -11:03:48.537925 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:03:48.552126 table@compaction committed F-4 S-1MiB Ke·0 D·166229 T·186.66634ms -11:03:48.552301 table@remove removed @50 -11:03:48.552405 table@remove removed @49 -11:03:48.552509 table@remove removed @47 -11:03:48.552616 table@remove removed @45 -11:03:48.552651 table@remove removed @43 -=============== Jul 13, 2018 (BST) =============== -11:20:12.182469 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:20:12.182651 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:20:12.182664 db@open opening -11:20:12.182717 journal@recovery F·1 -11:20:12.184513 journal@recovery recovering @51 -11:20:12.241385 memdb@flush created L0@54 N·2632 S·21KiB "n:\xbb..ver,v211126":"n:\xdc..ong,v208560" -11:20:12.243129 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] -11:20:12.267182 db@janitor F·4 G·0 -11:20:12.267224 db@open done T·84.550385ms -=============== Jul 13, 2018 (BST) =============== -11:22:05.344239 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:22:05.344426 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] -11:22:05.344439 db@open opening -11:22:05.344495 journal@recovery F·1 -11:22:05.346064 journal@recovery recovering @55 -11:22:05.396304 memdb@flush created L0@57 N·327 S·2KiB "n:\xbb..ver,v211460":"n:\xdc..ong,v211193" -11:22:05.398077 version@stat F·[2 1] S·24KiB[23KiB 411B] Sc·[0.50 0.00] -11:22:05.423465 db@janitor F·5 G·0 -11:22:05.423498 db@open done T·79.043478ms -11:22:05.431533 table@compaction L0·2 -> L1·1 S·24KiB Q·211514 -11:22:05.447314 table@build created L1@60 N·9 S·410B "n:\xbb..ver,v211460":"version,v1" -11:22:05.447458 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -11:22:05.465235 table@compaction committed F-2 S-23KiB Ke·0 D·2959 T·33.57446ms -11:22:05.465771 table@remove removed @57 -11:22:05.465835 table@remove removed @54 -11:22:05.465892 table@remove removed @53 -=============== Jul 13, 2018 (BST) =============== -11:28:36.605530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:28:36.605766 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -11:28:36.605790 db@open opening -11:28:36.605861 journal@recovery F·1 -11:28:36.605970 journal@recovery recovering @58 -11:28:36.669491 memdb@flush created L0@61 N·1083 S·8KiB "n:\xbb..ver,v212511":"n:\xdc..ong,v211525" -11:28:36.675160 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] -11:28:36.702895 db@janitor F·4 G·0 -11:28:36.702923 db@open done T·97.12478ms -=============== Jul 13, 2018 (BST) =============== -11:41:32.591748 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:32.592105 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] -11:41:32.592141 db@open opening -11:41:32.592263 journal@recovery F·1 -11:41:32.596765 journal@recovery recovering @62 -11:41:32.663254 memdb@flush created L0@64 N·2051 S·16KiB "n:\xbb..ver,v214616":"n:\xdc..ong,v212601" -11:41:32.667391 version@stat F·[2 1] S·25KiB[25KiB 410B] Sc·[0.50 0.00] -11:41:32.687539 db@janitor F·5 G·0 -11:41:32.687649 db@open done T·95.481415ms -11:41:32.693255 table@compaction L0·2 -> L1·1 S·25KiB Q·214650 -11:41:32.705795 table@build created L1@67 N·9 S·402B "n:\xbb..ver,v214616":"version,v1" -11:41:32.705947 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] -11:41:32.716509 table@compaction committed F-2 S-25KiB Ke·0 D·3134 T·23.166583ms -11:41:32.716920 table@remove removed @64 -11:41:32.717040 table@remove removed @61 -11:41:32.717124 table@remove removed @60 -=============== Jul 13, 2018 (BST) =============== -13:24:41.332660 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:24:41.333223 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] -13:24:41.333279 db@open opening -13:24:41.333442 journal@recovery F·1 -13:24:41.338137 journal@recovery recovering @65 -13:24:41.431439 memdb@flush created L0@68 N·16181 S·126KiB "n:\xbb..ver,v230767":"n:\xdc..ong,v214663" -13:24:41.436600 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] -13:24:41.455095 db@janitor F·4 G·0 -13:24:41.455178 db@open done T·121.864633ms -=============== Jul 13, 2018 (BST) =============== -13:52:04.996573 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:52:04.996949 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] -13:52:04.996993 db@open opening -13:52:04.997131 journal@recovery F·1 -13:52:05.001435 journal@recovery recovering @69 -13:52:05.038322 memdb@flush created L0@71 N·373 S·3KiB "n:\xbb..ver,v231162":"n:\xdc..ong,v230839" -13:52:05.042832 version@stat F·[2 1] S·129KiB[129KiB 402B] Sc·[0.50 0.00] -13:52:05.062434 db@janitor F·5 G·0 -13:52:05.062495 db@open done T·65.477336ms -13:52:05.066040 table@compaction L0·2 -> L1·1 S·129KiB Q·231206 -13:52:05.082072 table@build created L1@74 N·9 S·408B "n:\xbb..ver,v231162":"version,v1" -13:52:05.082302 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] -13:52:05.096557 table@compaction committed F-2 S-129KiB Ke·0 D·16554 T·30.442172ms -13:52:05.096669 table@remove removed @71 -13:52:05.096762 table@remove removed @68 -13:52:05.096809 table@remove removed @67 -=============== Jul 13, 2018 (BST) =============== -13:54:50.248625 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:54:50.249067 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] -13:54:50.249113 db@open opening -13:54:50.249268 journal@recovery F·1 -13:54:50.255685 journal@recovery recovering @72 -13:54:50.390496 memdb@flush created L0@75 N·6566 S·237KiB "n:\x00..ail,v235060":"n:\xff..ing,v235771" -13:54:50.392211 version@stat F·[1 1] S·237KiB[237KiB 408B] Sc·[0.25 0.00] -13:54:50.407405 db@janitor F·4 G·0 -13:54:50.407439 db@open done T·158.300632ms -13:55:22.967627 table@compaction L0·1 -> L1·1 S·237KiB Q·238097 -13:55:23.046954 table@build created L1@78 N·4978 S·219KiB "n:\x00..ail,v235060":"version,v1" -13:55:23.047304 version@stat F·[0 1] S·219KiB[0B 219KiB] Sc·[0.00 0.00] -13:55:23.055317 table@compaction committed F-1 S-17KiB Ke·0 D·1597 T·87.525732ms -13:55:23.056075 table@remove removed @75 -13:55:23.056416 table@remove removed @74 diff --git a/poa-network/multi-peer/node2/geth/nodes/MANIFEST-000077 b/poa-network/multi-peer/node2/geth/nodes/MANIFEST-000077 deleted file mode 100644 index ed5755705aacd31393887de7a3e8846dbf2f1213..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 852 zcmeA_$H1J!#KlUkOVlai$8R9TW*o>`pgoS$2eSd>_jU&Q3Y?8kEUARjA3OrF)9 zjkkYX7kFJO@ZiyHxm@FdBO5&4KdGr|J+jq&8+VLgv)-q8rcBWt%r7+#-n3`j5iBg{ zsFTcbUZ-H(Q>o2T|0&j{MM>6XUzY>7LH z%KNGdb~jgV?+8Lzk(Qa4l9rg6!)P)MYz5Hp|I;4M)?6=g{ApZ4YUdq~R+;bdI?B!| z{TqWsvh^ICKhNCP{jBPmY=(A$E!*AAf)i60a9lW0b!=1aT{*6_DG~n>hJ)Ro33UJO z8N)@)PU!yQ-V{Y#BN(gEt$a7dxZhm3zE2O;+e01OOahU@-sy diff --git a/poa-network/multi-peer/node2/geth/transactions.rlp b/poa-network/multi-peer/node2/geth/transactions.rlp deleted file mode 100755 index e69de29..0000000 diff --git a/poa-network/single-peer/node1/geth/LOCK b/poa-network/single-peer/node1/geth/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/poa-network/single-peer/node1/geth/chaindata/000002.ldb b/poa-network/single-peer/node1/geth/chaindata/000002.ldb deleted file mode 100644 index cb7629dadbb346002c1352d775009edf0e0fb3d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 794 zcmZqTS-_yl;qmwO)qhgKGv=!socMbFa^72w75h2Nuf2?)weaa5#*5)M8Ce+^81$GJ z3s%N#Sojn?QWH~Bix|1488YxN7&0euYB4Z0#WJukvT$le z96E4-!Qu{MYDq?FQEF+fZgPHJT4uU#-5j7iH>Z6{wNi3MVrHIaijtL~siCQkQbvAm zYHXHKrtPq)XV}yQv+TB1|vZM6_3Q?3?(Zig9?LRj0_A)yg>}6yh#kkKv@e( z0fnT>s>HmK%+g$5VHXn}rR1E)z>vqt!O2}G$;iX0@s_1d1?V<5P9L71Oj!#!xzZRJIu^*D@qKaccx=_`)~)H= z&RmhYEaWOZrK?2v!$POO4p%0-Phs$~W%%H{;B34Ls~T6P=?0IN!numFKj%d{N3MS0 zdwzOMF<;Dw>l_QhUdW3}p9x*|zuEQKqys*M4tiVMQ36d71{ zGI~`o{9}ZoZHx>ij1A5I|Nn1ji583O+)-Nhhrvht>1sabZFe*|t{TaFmiQdqaN!_t zoe4t|BSVt|6GMlfvxp`qV+kWOC!YW#gCS!PCwG??3j;f+7BEJPMT%3CON&x`mV$nLLI<37?n+?@itYy6{{`B|=DKRo~ng@Mn;Lzw{tXssy!pOww z!1JSPp+a2_gUF7wA1MtBcny;n8QQ)u%{h9>jj`>!vdyHr+D&(kGaq=$ur2shle%^F zuNy3}txF1k>4*UsZw!pz_U&KNbm)Ca{59j|v?W7h&LJKF9c=b zcERGIn{PU<(3}?iF@L#*>;XY9vvd6_>xI6CU28ovuXsn=kCcW5Osx88j0_(#7lgf# z7neR0y6k_m>$6D*e&j`aJdmE5v-SXElK$4m$y*c`9KGbm*!Er7W>Q`4raQ-(4?Jbq z7JRBn-MaeM4VKu}B?Szc93F>v9SYxl!DF&vR@oKl{O`O^zs1Z~xh>R@vdl=gk56BN zk%NK3sD;5mP{Aj$xWp+ZKRKI`hf|8-aFq*#1`D5pM`~h9Y7ryvG(!d+21Di~PAvw8 zrdS3RMs`lEh(iYsFj(ASOfAVsElMrT)lJUNOUq2xt(yas=i{_bsa8tPNX*RhOi{8j zG&MBUQOd~AO)V|~8p--v11P4Wl$u#!XllSKz+faOpyH8OoS|f;WKd!7i;;mri8qMB zlsAdN7$|EYDWH&4S(TVql3AL|E9_#Tqm-PJSy-B?WL2$HkXn?P&v-xuXj(yjGSCEL z#z`WzwG2WE8Jy1q7#Q*xxjDJ(B!S-2Xk@KZ0lJNo(}(9LQ{4hiE?`J^ERa3p`{Lg5 z*s9g7Thq6lxgvF0$W?kuSBdb4g-(ARu1t2H!r*1g(6HdPxpT}a`BQaLOSjyT$^85A zqPnuGij1A5I|Nn1ji583O+|gP0 zhhc&C)75;=+wN#`Ts4yUEb%$I;le@Qw!)_mdP_cAypwTLc4$#{yFPvWWrjLWhB`)u zrVu8E4nZdoO-{xVMmA190Y(Nx#v)GcE;|+mE>10AEEtOvrzV#crRrv5RtpT z$U`vxg{sA(bxd_yd!sfRsGqfv7>Ai1H+Dg zK5X-R*jO}z>sB+fFtYM)V+mYP_mF|1fsv76L0vFAqpC>*7=W?>Fisg5oxKCJ(%|NPo4l9NM0C-xfx7mS-9y}FeoyoW#*Km7U|`rmZj#TB&7arv71c>qzP=O@YRJI#6=i5neQYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=&~ggKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0QHestpET3 diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000008.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000008.ldb deleted file mode 100644 index d2b26a1513df62490165abb9178df47524827180..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(5igKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7araSq}muu(H6 uxR{8GFmN)bG5+Ud)L=LX5{1|jQh)Z?Q%3!nOkyA*{2=^yL$^w)`)vRx>RJN; diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000011.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000011.ldb deleted file mode 100644 index df591285ec4a5126c6edcfcaadbe0d6cdbf90ba3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(2hgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU=(8jgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c40gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0Gb3^x&QzG diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000020.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000020.ldb deleted file mode 100644 index 0f885d9e99a6ddfd068f3d58435204b29fb142a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cA2gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3c71gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weV3cD3gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qiLgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm8l$aRU zK%$&L%*|leYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qoNgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qlMgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmH7Hgo`4N=yuF zAW=>r=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r05HB;{Qv*} diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000038.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000038.ldb deleted file mode 100644 index a05ec3826f2c34a6199189d16cc0a8392e95cf55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU{qrOgKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmCfzZ<$$O5JY*08mI;GXMYp diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000041.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000041.ldb deleted file mode 100644 index c8f05dd77cbe3eac74780b6ebaab315d0e462feb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANm$gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm?x!EOeQgq5PlH;yP;d9)crO9n~Yko diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000044.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000044.ldb deleted file mode 100644 index 627147b4d7b2f480a6a51150b612a39211a8ccf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANs&gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmI|AGN&>A=Va7iI0+JkNQKm&J@%AQeYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANp%gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmYH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weVANv(gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0AdtcNB{r; diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000053.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000053.ldb deleted file mode 100644 index 32548614e07c2dcfdabd893cf97d080abd9721d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HL=gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQmr=4P<#aoet6!Jx>TmYGwMTBMhgT9%rVlBDNU3gl&7aragI?4qzP=) wj0r9#;vx*3%xR4OITZfil)B#r0A*QPO8@`> diff --git a/poa-network/single-peer/node1/geth/lightchaindata/000056.ldb b/poa-network/single-peer/node1/geth/lightchaindata/000056.ldb deleted file mode 100644 index 3c07eed7394d4b6511ac7fd9c724fdf5e2425875..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmZ3$^dXhO;tpeKNk(c>YH6-+a(-S~X1ea-U5CPVU+|c0m{oQ~I{!QG({C~JRc;G) zq%1Si?c>weU^HR?gKDMZjKs`5&lDvqLsLUj9i@!?+|=Td)Wj60oc!c$ps0>gYG#3< zsR6G5i;)hmfQm L1·0 S·2KiB Q·22 -=============== Jul 12, 2018 (BST) =============== -14:17:42.392536 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:17:42.395630 version@stat F·[4] S·2KiB[2KiB] Sc·[1.00] -14:17:42.395645 db@open opening -14:17:42.395694 journal@recovery F·1 -14:17:42.395969 journal@recovery recovering @12 -14:17:42.413553 memdb@flush created L0@14 N·1 S·356B "eth..\x0e/(,v22":"eth..\x0e/(,v22" -14:17:42.414591 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] -14:17:42.442813 db@janitor F·7 G·0 -14:17:42.442842 db@open done T·47.187651ms -14:17:42.442909 table@compaction L0·5 -> L1·0 S·2KiB Q·23 -=============== Jul 12, 2018 (BST) =============== -14:39:49.043706 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:39:49.043821 version@stat F·[5] S·2KiB[2KiB] Sc·[1.25] -14:39:49.043835 db@open opening -14:39:49.043899 journal@recovery F·1 -14:39:49.044289 journal@recovery recovering @15 -14:39:49.051780 memdb@flush created L0@17 N·1 S·356B "eth..\x0e/(,v24":"eth..\x0e/(,v24" -14:39:49.052391 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] -14:39:49.081746 db@janitor F·8 G·0 -14:39:49.081769 db@open done T·37.92478ms -=============== Jul 12, 2018 (BST) =============== -15:37:17.901222 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:37:17.901345 version@stat F·[6] S·2KiB[2KiB] Sc·[1.50] -15:37:17.901358 db@open opening -15:37:17.901421 journal@recovery F·1 -15:37:17.901850 journal@recovery recovering @18 -15:37:17.910929 memdb@flush created L0@20 N·1 S·356B "eth..\x0e/(,v26":"eth..\x0e/(,v26" -15:37:17.911100 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] -15:37:17.925999 db@janitor F·9 G·0 -15:37:17.926024 db@open done T·24.65714ms -15:37:17.927077 table@compaction L0·7 -> L1·0 S·3KiB Q·27 -=============== Jul 12, 2018 (BST) =============== -15:48:30.025065 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:48:30.025198 version@stat F·[7] S·3KiB[3KiB] Sc·[1.75] -15:48:30.025211 db@open opening -15:48:30.025278 journal@recovery F·1 -15:48:30.025786 journal@recovery recovering @21 -15:48:30.038226 memdb@flush created L0@23 N·1 S·356B "eth..\x0e/(,v28":"eth..\x0e/(,v28" -15:48:30.038417 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] -15:48:30.066147 db@janitor F·10 G·0 -15:48:30.066173 db@open done T·40.953875ms -15:48:30.066226 table@compaction L0·8 -> L1·0 S·3KiB Q·29 -=============== Jul 12, 2018 (BST) =============== -16:05:26.776151 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:05:26.776271 version@stat F·[8] S·3KiB[3KiB] Sc·[2.00] -16:05:26.776283 db@open opening -16:05:26.776346 journal@recovery F·1 -16:05:26.776757 journal@recovery recovering @24 -16:05:26.787652 memdb@flush created L0@26 N·1 S·356B "eth..\x0e/(,v30":"eth..\x0e/(,v30" -16:05:26.789490 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] -16:05:26.816798 db@janitor F·11 G·0 -16:05:26.816853 db@open done T·40.562165ms -16:05:26.817677 table@compaction L0·9 -> L1·0 S·3KiB Q·31 -=============== Jul 12, 2018 (BST) =============== -16:23:47.409548 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:23:47.409692 version@stat F·[9] S·3KiB[3KiB] Sc·[2.25] -16:23:47.409705 db@open opening -16:23:47.409772 journal@recovery F·1 -16:23:47.410167 journal@recovery recovering @27 -16:23:47.423566 memdb@flush created L0@29 N·1 S·356B "eth..\x0e/(,v32":"eth..\x0e/(,v32" -16:23:47.423748 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] -16:23:47.446201 db@janitor F·12 G·0 -16:23:47.446221 db@open done T·36.509905ms -16:23:47.446274 table@compaction L0·10 -> L1·0 S·4KiB Q·33 -=============== Jul 12, 2018 (BST) =============== -16:40:10.390435 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:40:10.390563 version@stat F·[10] S·4KiB[4KiB] Sc·[2.50] -16:40:10.390577 db@open opening -16:40:10.390649 journal@recovery F·1 -16:40:10.391101 journal@recovery recovering @30 -16:40:10.411407 memdb@flush created L0@32 N·1 S·356B "eth..\x0e/(,v34":"eth..\x0e/(,v34" -16:40:10.411625 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] -16:40:10.440987 db@janitor F·13 G·0 -16:40:10.441011 db@open done T·50.42733ms -16:40:10.441063 table@compaction L0·11 -> L1·0 S·4KiB Q·35 -=============== Jul 12, 2018 (BST) =============== -16:57:38.124701 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:57:38.124826 version@stat F·[11] S·4KiB[4KiB] Sc·[2.75] -16:57:38.124838 db@open opening -16:57:38.124894 journal@recovery F·1 -16:57:38.125141 journal@recovery recovering @33 -16:57:38.138032 memdb@flush created L0@35 N·1 S·356B "eth..\x0e/(,v36":"eth..\x0e/(,v36" -16:57:38.138332 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] -16:57:38.159988 db@janitor F·14 G·0 -16:57:38.160014 db@open done T·35.167225ms -16:57:38.160670 table@compaction L0·12 -> L1·0 S·4KiB Q·37 -=============== Jul 13, 2018 (BST) =============== -11:03:46.000460 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:03:46.000607 version@stat F·[12] S·4KiB[4KiB] Sc·[3.00] -11:03:46.000618 db@open opening -11:03:46.000698 journal@recovery F·1 -11:03:46.001141 journal@recovery recovering @36 -11:03:46.008992 memdb@flush created L0@38 N·1 S·356B "eth..\x0e/(,v38":"eth..\x0e/(,v38" -11:03:46.009163 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] -11:03:46.023882 db@janitor F·15 G·0 -11:03:46.023908 db@open done T·23.283363ms -11:03:46.023980 table@compaction L0·13 -> L1·0 S·5KiB Q·39 -=============== Jul 13, 2018 (BST) =============== -11:20:09.942969 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:20:09.943598 version@stat F·[13] S·5KiB[5KiB] Sc·[3.25] -11:20:09.943626 db@open opening -11:20:09.943722 journal@recovery F·1 -11:20:09.947317 journal@recovery recovering @39 -11:20:09.958460 memdb@flush created L0@41 N·1 S·356B "eth..\x0e/(,v40":"eth..\x0e/(,v40" -11:20:09.959885 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] -11:20:09.975584 db@janitor F·16 G·0 -11:20:09.975619 db@open done T·31.977474ms -11:20:09.976379 table@compaction L0·14 -> L1·0 S·5KiB Q·41 -=============== Jul 13, 2018 (BST) =============== -11:22:02.953772 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:22:02.954444 version@stat F·[14] S·5KiB[5KiB] Sc·[3.50] -11:22:02.954479 db@open opening -11:22:02.954598 journal@recovery F·1 -11:22:02.966261 journal@recovery recovering @42 -11:22:02.978212 memdb@flush created L0@44 N·1 S·356B "eth..\x0e/(,v42":"eth..\x0e/(,v42" -11:22:02.978765 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] -11:22:02.999921 db@janitor F·17 G·0 -11:22:02.999956 db@open done T·45.466851ms -11:22:03.000743 table@compaction L0·15 -> L1·0 S·5KiB Q·43 -=============== Jul 13, 2018 (BST) =============== -11:28:34.365499 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:28:34.365667 version@stat F·[15] S·5KiB[5KiB] Sc·[3.75] -11:28:34.365687 db@open opening -11:28:34.365776 journal@recovery F·1 -11:28:34.367127 journal@recovery recovering @45 -11:28:34.380594 memdb@flush created L0@47 N·1 S·356B "eth..\x0e/(,v44":"eth..\x0e/(,v44" -11:28:34.380999 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] -11:28:34.403500 db@janitor F·18 G·0 -11:28:34.403536 db@open done T·37.840488ms -11:28:34.403948 table@compaction L0·16 -> L1·0 S·6KiB Q·45 -=============== Jul 13, 2018 (BST) =============== -11:41:30.386027 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:30.386185 version@stat F·[16] S·6KiB[6KiB] Sc·[4.00] -11:41:30.386203 db@open opening -11:41:30.386272 journal@recovery F·1 -11:41:30.386659 journal@recovery recovering @48 -11:41:30.394072 memdb@flush created L0@50 N·1 S·356B "eth..\x0e/(,v46":"eth..\x0e/(,v46" -11:41:30.394334 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] -11:41:30.410389 db@janitor F·19 G·0 -11:41:30.410973 db@open done T·24.760035ms -11:41:30.411851 table@compaction L0·17 -> L1·0 S·6KiB Q·47 -=============== Jul 13, 2018 (BST) =============== -13:24:39.113379 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:24:39.113565 version@stat F·[17] S·6KiB[6KiB] Sc·[4.25] -13:24:39.113598 db@open opening -13:24:39.113722 journal@recovery F·1 -13:24:39.114072 journal@recovery recovering @51 -13:24:39.121664 memdb@flush created L0@53 N·1 S·356B "eth..\x0e/(,v48":"eth..\x0e/(,v48" -13:24:39.121894 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] -13:24:39.136887 db@janitor F·20 G·0 -13:24:39.136917 db@open done T·23.308508ms -13:24:39.137816 table@compaction L0·18 -> L1·0 S·6KiB Q·49 -=============== Jul 13, 2018 (BST) =============== -13:39:12.018429 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:39:12.019064 version@stat F·[18] S·6KiB[6KiB] Sc·[4.50] -13:39:12.019145 db@open opening -13:39:12.019839 journal@recovery F·1 -13:39:12.021641 journal@recovery recovering @54 -13:39:12.030692 memdb@flush created L0@56 N·1 S·356B "eth..\x0e/(,v50":"eth..\x0e/(,v50" -13:39:12.032915 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:39:12.052820 db@janitor F·21 G·0 -13:39:12.052920 db@open done T·33.639977ms -=============== Jul 13, 2018 (BST) =============== -13:41:58.941624 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:41:58.942136 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:41:58.942205 db@open opening -13:41:58.942530 journal@recovery F·1 -13:41:58.943580 journal@recovery recovering @57 -13:41:58.946268 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:41:58.963116 db@janitor F·21 G·0 -13:41:58.963242 db@open done T·21.000186ms -13:41:58.963542 table@compaction L0·19 -> L1·0 S·7KiB Q·51 -=============== Jul 13, 2018 (BST) =============== -13:50:49.450674 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:50:49.450804 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:50:49.450822 db@open opening -13:50:49.450889 journal@recovery F·1 -13:50:49.451330 journal@recovery recovering @59 -13:50:49.452188 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:50:49.467448 db@janitor F·21 G·0 -13:50:49.467489 db@open done T·16.657771ms -=============== Jul 13, 2018 (BST) =============== -13:54:34.930429 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:54:34.930546 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:54:34.930560 db@open opening -13:54:34.930626 journal@recovery F·1 -13:54:34.930819 journal@recovery recovering @61 -13:54:34.931374 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:54:34.947674 db@janitor F·21 G·0 -13:54:34.947767 db@open done T·17.191913ms -=============== Jul 13, 2018 (BST) =============== -13:57:08.944621 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:57:08.945178 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:57:08.945263 db@open opening -13:57:08.945603 journal@recovery F·1 -13:57:08.947077 journal@recovery recovering @63 -13:57:08.951043 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -13:57:08.971140 db@janitor F·21 G·0 -13:57:08.971265 db@open done T·25.961614ms -13:57:08.971547 table@compaction L0·19 -> L1·0 S·7KiB Q·51 -=============== Jul 13, 2018 (BST) =============== -14:14:56.449979 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:14:56.450651 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -14:14:56.450749 db@open opening -14:14:56.451334 journal@recovery F·1 -14:14:56.452603 journal@recovery recovering @65 -14:14:56.457641 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -14:14:56.475716 db@janitor F·21 G·0 -14:14:56.475804 db@open done T·24.938608ms -14:14:56.476030 table@compaction L0·19 -> L1·0 S·7KiB Q·51 -=============== Jul 13, 2018 (BST) =============== -14:34:07.781663 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:34:07.782320 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -14:34:07.782416 db@open opening -14:34:07.782844 journal@recovery F·1 -14:34:07.784127 journal@recovery recovering @67 -14:34:07.786947 version@stat F·[19] S·7KiB[7KiB] Sc·[4.75] -14:34:07.805547 db@janitor F·21 G·0 -14:34:07.805659 db@open done T·23.18933ms diff --git a/poa-network/single-peer/node1/geth/lightchaindata/MANIFEST-000070 b/poa-network/single-peer/node1/geth/lightchaindata/MANIFEST-000070 deleted file mode 100644 index e86e81de59824bd86660c0db774e409d7814455c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2270 zcmbWw&ntrg9LMqRGt*beuO&a88OxZ*k7t-}Bo4MA!zDm5`|cVe3#qJ=znN)-=M_CD(iV?O9WhG=PL|7GNC1ff<*bh|`7 zrSJOQm;TkW^nzpZS+V{zTC&X_*sr*rS9cE|%R)ct+ZtDOX{y8C7g`(&2S1*a%>Uyr DLOxQ< diff --git a/poa-network/single-peer/node1/geth/nodekey b/poa-network/single-peer/node1/geth/nodekey deleted file mode 100644 index 8a307c3..0000000 --- a/poa-network/single-peer/node1/geth/nodekey +++ /dev/null @@ -1 +0,0 @@ -7b40b607cd20a19d0464f74d9b90d668aaa67f2a61951301205c6a73f572e8e0 \ No newline at end of file diff --git a/poa-network/single-peer/node1/geth/nodes/000098.ldb b/poa-network/single-peer/node1/geth/nodes/000098.ldb deleted file mode 100644 index ecead2545dd3cee12daa10ea1221bff19fa8ee03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1327685 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

    ~_P6?SYn1K&B2G1fb@Ss9^ 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 ioa@Q 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 Q>p%kBXj9&KM#JuA*3eO(qsuGtwz%4YlUX2W|8; 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 I#5GzKO7kU+S9^afV<^hie+5)7+yw! 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%0AnvT&k~lQYrkUGIwi)}JK3Q$MeCa634g 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

      d8jpY=v}T#Q+oycwm*q!C-;t=qiG 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

      =6&|7AZ@2Y~sx76MjT_WMsJo`GNe$2olqU!9_ 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

      wmY|Wu%Ijgy>y99!^cHQ+| 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

      $=IJ30B;gpK*CtB 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 NmiUTfY9HUo3jk(b>k0q> From 922c52aa215bda1e8f1d681587994cc69882ab54 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 18 Jul 2018 09:29:23 +0100 Subject: [PATCH 063/203] Added connection to rinkeby --- ion-cli/rinkeby.json | 9 +++++++++ migrations/2_deploy_contracts.js | 2 +- package.json | 2 +- scripts/killClique | 6 ++++++ scripts/runClique | 31 +++++++++++++++++++++++++++++++ scripts/runSingleNode | 10 ++++++++++ scripts/runTestrpc | 11 +++++++++++ 7 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 ion-cli/rinkeby.json create mode 100755 scripts/killClique create mode 100755 scripts/runClique create mode 100755 scripts/runSingleNode create mode 100755 scripts/runTestrpc diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json new file mode 100644 index 0000000..a6094a3 --- /dev/null +++ b/ion-cli/rinkeby.json @@ -0,0 +1,9 @@ +{ + "rpc-to":"http://127.0.0.1:8545", + "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-to":"../poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "rpc-from":"https://rinkeby.infura.io", + "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-from":"../poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f" +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 8ec45e4..b2b757a 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -7,7 +7,7 @@ module.exports = async (deployer) => { try { deployer.deploy(Recover) .then(() => Recover.deployed) - .then(() => deployer.deploy(Validation, ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"], "0xc3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28")) + .then(() => deployer.deploy(Validation, ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"], "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) .then(() => Validation.deployed) .then(() => deployer.deploy(PatriciaTrie)) .then(() => PatriciaTrie.deployed) diff --git a/package.json b/package.json index a70e349..6288097 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "web3-utils": "^1.0.0-beta.33" }, "scripts": { - "testrpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", "deploy": "truffle deploy --network development", "depclique": "truffle deploy --network clique", diff --git a/scripts/killClique b/scripts/killClique new file mode 100755 index 0000000..51f9057 --- /dev/null +++ b/scripts/killClique @@ -0,0 +1,6 @@ +#!/bin/bash +tmux kill-session -t boot +tmux kill-session -t node1 +tmux kill-session -t node2 +tmux kill-session -t node3 +tmux kill-session -t node diff --git a/scripts/runClique b/scripts/runClique new file mode 100755 index 0000000..1fa8d65 --- /dev/null +++ b/scripts/runClique @@ -0,0 +1,31 @@ +#!/bin/bash + +# Launch the boot node +tmux new -s boot -n selsig -d +tmux send-keys -t boot "bootnode -nodekey poa-network/multi-peer/boot.key -verbosity 9 -addr :30310" C-m + +# Launch the noodle 1 +tmux new -s node1 -n geth_and_console -d +tmux send-keys -t node1 "rm -rf poa-network/multi-peer/node1/geth/chaindata" C-m +tmux send-keys -t node1 "rm -rf poa-network/multi-peer/node2/geth/chaindata" C-m +tmux send-keys -t node1 "geth --datadir poa-network/multi-peer/node1/ init poa-network/multi-peer/genesis.json" C-m +tmux send-keys -t node1 "geth --datadir poa-network/multi-peer/node1/ --syncmode 'full' --port 30311 --rpc --rpcaddr 'localhost' --rpcport 8501 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '0' -unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password poa-network/multi-peer/node1/password.txt --mine" C-m +tmux split-window -h -t node1:geth_and_console +tmux send-keys -t node1 "sleep 5s" C-m +tmux send-keys -t node1 "geth attach ipc:poa-network/multi-peer/node1/geth.ipc" C-m + +# Launch the noodle 2 +tmux new -s node2 -n geth_and_console -d +tmux send-keys -t node2 "geth --datadir poa-network/multi-peer/node2/ init poa-network/multi-peer/genesis.json" C-m +tmux send-keys -t node2 "geth --datadir poa-network/multi-peer/node2/ --syncmode 'full' --port 30312 --rpc --rpcaddr 'localhost' --rpcport 8502 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '0' -unlock '0x8671e5e08d74f338ee1c462340842346d797afd3' --password poa-network/multi-peer/node2/password.txt --mine" C-m +tmux split-window -h -t node2:geth_and_console +tmux send-keys -t node2 "sleep 5s" C-m +tmux send-keys -t node2 "geth attach ipc:poa-network/multi-peer/node2/geth.ipc" C-m + +# Launch the noodle 3 - testrpc +tmux new -s node3 -n geth_and_console -d +tmux send-keys -t node3 "npm run testrpc" C-m +tmux split-window -h -t node3:geth_and_console +tmux send-keys -t node3 "sleep 5s" C-m +tmux send-keys -t node3 "geth attach http://127.0.0.1:8545" C-m +tmux ls diff --git a/scripts/runSingleNode b/scripts/runSingleNode new file mode 100755 index 0000000..c380e72 --- /dev/null +++ b/scripts/runSingleNode @@ -0,0 +1,10 @@ +#!/bin/bash + +# Launch the noodle 1 +tmux new -s node1 -n geth_and_console -d +tmux send-keys -t node1 "rm -rf poa-network/single-peer/node1/geth/chaindata" C-m +tmux send-keys -t node1 "geth --datadir poa-network/single-peer/node1/ init poa-network/single-peer/genesis.json" C-m +tmux send-keys -t node1 "geth --datadir poa-network/single-peer/node1/ --syncmode 'full' --rpc --rpcaddr 'localhost' --rpcport 8501 --networkid 1515 --gasprice '0' -unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password poa-network/single-peer/node1/password.txt --mine" C-m +tmux split-window -h -t node1:geth_and_console +tmux send-keys -t node1 "sleep 4s" C-m +tmux send-keys -t node1 "geth attach ipc:poa-network/single-peer/node1/geth.ipc" C-m diff --git a/scripts/runTestrpc b/scripts/runTestrpc new file mode 100755 index 0000000..e5aad34 --- /dev/null +++ b/scripts/runTestrpc @@ -0,0 +1,11 @@ +#!/bin/bash + +# Launch the noodle 3 - testrpc +tmux new -s node -n geth_and_console -d +tmux send-keys -t node "rm -rf build/contracts/*" C-m +tmux send-keys -t node "npm run testrpc" C-m +tmux split-window -h -t node:geth_and_console +tmux send-keys -t node "sleep 5s" C-m +tmux send-keys -t node "npm run deploy" C-m +tmux send-keys -t node "geth attach http://127.0.0.1:8545" C-m +tmux ls From 73305c97fc6417c28372c68a0bf6045806a742f2 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 19 Jul 2018 09:48:16 +0100 Subject: [PATCH 064/203] Added test for encoding, also removed Ion tests from make tests as they do not run without testrpc --- ion-cli/cli/rpc.go | 2 + .../contracts/{ion_test.go => test_ion.go} | 103 ++++++++++++++++-- ion-cli/utils/rlp.go | 85 +++++++++++++++ ion-cli/utils/rlp_test.go | 58 ++++++++++ scripts/killClique | 6 - scripts/runClique | 31 ------ scripts/runSingleNode | 10 -- scripts/runTestrpc | 11 -- test/ion.js | 5 +- 9 files changed, 243 insertions(+), 68 deletions(-) rename ion-cli/contracts/{ion_test.go => test_ion.go} (59%) create mode 100644 ion-cli/utils/rlp.go create mode 100644 ion-cli/utils/rlp_test.go delete mode 100755 scripts/killClique delete mode 100755 scripts/runClique delete mode 100755 scripts/runSingleNode delete mode 100755 scripts/runTestrpc diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 18e49b3..b476abb 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -90,12 +90,14 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by fmt.Printf("Error: %s", err) return } + fmt.Printf("\n%+x\n", b) err = json.Unmarshal([]byte(b), &blockHeader) if err != nil { latestBlock(client) fmt.Printf("Error: %s", err) return } + fmt.Printf("\n%v\n", blockHeader) // Generate an interface to encode the blockheader without the signature in the extraData prefixBlock = encodeBlock(blockHeader) diff --git a/ion-cli/contracts/ion_test.go b/ion-cli/contracts/test_ion.go similarity index 59% rename from ion-cli/contracts/ion_test.go rename to ion-cli/contracts/test_ion.go index 46511bf..88c7bde 100644 --- a/ion-cli/contracts/ion_test.go +++ b/ion-cli/contracts/test_ion.go @@ -1,36 +1,36 @@ package contract import ( - "encoding/hex" + "context" "fmt" "log" + "math/big" + "strings" "testing" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/assert" ) -var CLIENT = "http://127.0.0.1:8501" +var CLIENT = "http://127.0.0.1:8545" var DEPLOYEDCHAINID = "ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" var TESTCHAINID = "22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" - var TESTBLOCK = []byte(`{'difficulty': 2,'extraData': '0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00', 'gasLimit': 5635559972940396, 'gasUsed': 273138, 'hash': '0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4', 'logsBloom': '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 'miner':'0x0000000000000000000000000000000000000000','mixHash': '0x0000000000000000000000000000000000000000000000000000000000000000','nonce':'0x0000000000000000','number': 5446,'parentHash': '0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284','receiptsRoot': '0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1','sha3Uncles':'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347','size': 2027,'stateRoot':'0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967','timestamp': 1531327572,'totalDifficulty': 10893,'transactions': [ '0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3','0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5','0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8','0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6','0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8','0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1','0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446','0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462','0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e','0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314','0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d','0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede','0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc'],'transactionsRoot': '0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35','uncles': []}`) - var KEY = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` +var IONADDR = common.HexToAddress("0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613") // Test ion contract gets deployed correctly func Test_IonDeployment(t *testing.T) { // Create an IPC based RPC connection to a remote node - conn, err := ethclient.Dial("http://127.0.0.1:8501") + conn, err := ethclient.Dial(CLIENT) if err != nil { log.Fatalf("Failed to connect to the Ethereum client: %v", err) } - ionAddr := common.HexToAddress("0xc290566df007e57a09e31ffe9a6d6627ab536ce2") - - ion, err := NewIon(ionAddr, conn) + ion, err := NewIon(IONADDR, conn) if err != nil { log.Fatalf("Failed to instantiate Ion contract: %v", err) } @@ -38,7 +38,7 @@ func Test_IonDeployment(t *testing.T) { if err != nil { log.Fatalf("Failed to retrieve chainId: %v", err) } - deployedChainId, err := hex.DecodeString(DEPLOYEDCHAINID) + // deployedChainId, err := hex.DecodeString(DEPLOYEDCHAINID) if err != nil { log.Fatalf("Failed to retrieve chainId: %v", err) } @@ -47,3 +47,88 @@ func Test_IonDeployment(t *testing.T) { CHAINID := fmt.Sprintf("%x", chainId) assert.Equal(t, DEPLOYEDCHAINID, CHAINID) } + +// Tests register chain is successful +func Test_RegisterChain(t *testing.T) { + // Create an IPC based RPC connection to a remote node + conn, err := ethclient.Dial(CLIENT) + if err != nil { + log.Fatalf("Failed to connect to the Ethereum client: %v", err) + } + + // Create new transactor + auth, err := bind.NewTransactor(strings.NewReader(KEY), "password1") + if err != nil { + log.Fatalf("Failed to create authorized transactor: %v", err) + } + // Get a suggested gas price + gasPrice, err := conn.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatal(err) + } + auth.Value = big.NewInt(0) // in wei + auth.GasLimit = uint64(300000) // in units + auth.GasPrice = gasPrice + + ion, err := NewIon(IONADDR, conn) + if err != nil { + log.Fatalf("Failed to instantiate Ion contract: %v", err) + } + + testChainId := [32]byte{} + copy(testChainId[:], []byte(TESTCHAINID)) + + // Register an alternate chain + _, err = ion.RegisterChain(auth, testChainId) + if err != nil { + log.Fatalf("Failed to instantiate Ion contract: %v", err) + } + + // Register an alternate chain + _, err = ion.RegisterChain(auth, testChainId) + assert.NotEqual(t, nil, err) +} + +// Test the a Tx Proof is successfully validated +// func Test_SubmitBlock(t *testing.T) { +// // Create an IPC based RPC connection to a remote node +// conn, err := ethclient.Dial(CLIENT) +// if err != nil { +// log.Fatalf("Failed to connect to the Ethereum client: %v", err) +// } + +// // Create new transactor +// auth, err := bind.NewTransactor(strings.NewReader(KEY), "password1") +// if err != nil { +// log.Fatalf("Failed to create authorized transactor: %v", err) +// } +// // Get a suggested gas price +// gasPrice, err := conn.SuggestGasPrice(context.Background()) +// if err != nil { +// log.Fatal(err) +// } +// auth.Value = big.NewInt(0) // in wei +// auth.GasLimit = uint64(300000) // in units +// auth.GasPrice = gasPrice + +// ion, err := NewIon(IONADDR, conn) +// if err != nil { +// log.Fatalf("Failed to instantiate Ion contract: %v", err) +// } + +// testChainId := [32]byte{} +// copy(testChainId[:], []byte(TESTCHAINID)) + +// // Register an alternate chain +// _, err = ion.RegisterChain(auth, testChainId) +// if err != nil { +// log.Fatalf("Failed to instantiate Ion contract: %v", err) +// } + +// fmt.Printf("%+v", TESTBLOCK) +// } + +// // Test the a Tx Proof is successfully validated +// func Test_TxProof(t *testing.T) { + +// } diff --git a/ion-cli/utils/rlp.go b/ion-cli/utils/rlp.go new file mode 100644 index 0000000..b809740 --- /dev/null +++ b/ion-cli/utils/rlp.go @@ -0,0 +1,85 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package utils + +import ( + "encoding/hex" + "fmt" + "reflect" + + "github.com/ethereum/go-ethereum/rlp" +) + +// Header used to marshall blocks into a string based struct +type Header struct { + ParentHash string `json:"parentHash"` + UncleHash string `json:"sha3Uncles"` + Coinbase string `json:"miner"` + Root string `json:"stateRoot"` + TxHash string `json:"transactionsRoot"` + ReceiptHash string `json:"receiptsRoot"` + Bloom string `json:"logsBloom"` + Difficulty string `json:"difficulty"` + Number string `json:"number"` + GasLimit string `json:"gasLimit"` + GasUsed string `json:"gasUsed"` + Time string `json:"timestamp"` + Extra string `json:"extraData"` + MixDigest string `json:"mixHash"` + Nonce string `json:"nonce"` +} + +// EncodePrefix calculate prefix of the entire signed block +func EncodePrefix(blockHeader Header) (prefix []byte) { + blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] + blockInterface := GenerateInterface(blockHeader) + encodedPrefixBlock := EncodeBlock(blockInterface) + + return encodedPrefixBlock[1:3] +} + +// EncodeExtraData calculate prefix of the extraData with the signature +func EncodeExtraData(blockHeader Header) (prefix []byte) { + blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] + encExtra, err := hex.DecodeString(blockHeader.Extra[2:]) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + + encodedExtraData := EncodeBlock(encExtra) + + return encodedExtraData[0:1] +} + +// GenerateInterface Creates an interface for a block +func GenerateInterface(blockHeader Header) (rest interface{}) { + blockInterface := []interface{}{} + s := reflect.ValueOf(&blockHeader).Elem() + + // Append items into the interface + for i := 0; i < s.NumField(); i++ { + f := s.Field(i).String() + // fmt.Printf("\n%s", f) + + // Remove the 0x prefix + f = f[2:] + + // single character then pre-pending a 0 turns it into a byte + if len(f)%2 != 0 { + f = "0" + f + } + + element, _ := hex.DecodeString(f) + blockInterface = append(blockInterface, element) + } + + return blockInterface +} + +// Encodes a block +func EncodeBlock(blockInterface interface{}) (h []byte) { + h, _ = rlp.EncodeToBytes(blockInterface) + + return h +} diff --git a/ion-cli/utils/rlp_test.go b/ion-cli/utils/rlp_test.go new file mode 100644 index 0000000..275329f --- /dev/null +++ b/ion-cli/utils/rlp_test.go @@ -0,0 +1,58 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package utils_test + +import ( + "encoding/hex" + "encoding/json" + "log" + "testing" + + "github.com/clearmatics/ion/ion-cli/utils" + "github.com/stretchr/testify/assert" +) + +var EXPECTEDINTERFACE = "[6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 0000000000000000000000000000000000000000 53580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2d 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 02 01 47c94c 00 58ee45da d783010600846765746887676f312e372e33856c696e757800000000000000009f1efa1efa72af138c915966c639544a0255e6288e188c22ce9168c10dbe46da3d88b4aa065930119fb886210bf01a084fde5d3bc48d8aa38bca92e4fcc5215100 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000]" + +var EXPECTEDRLPBLOCK = "f90256a06341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a053580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002018347c94c008458ee45dab861d783010600846765746887676f312e372e33856c696e757800000000000000009f1efa1efa72af138c915966c639544a0255e6288e188c22ce9168c10dbe46da3d88b4aa065930119fb886210bf01a084fde5d3bc48d8aa38bca92e4fcc5215100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + +var block = `{"parentHash": "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177", "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "miner": "0x0000000000000000000000000000000000000000","stateRoot": "0x53580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2d","transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "difficulty": "0x2", "number": "0x1","gasLimit": "0x47c94c", "gasUsed": "0x0", "timestamp": "0x58ee45da", "extraData": "0xd783010600846765746887676f312e372e33856c696e757800000000000000009f1efa1efa72af138c915966c639544a0255e6288e188c22ce9168c10dbe46da3d88b4aa065930119fb886210bf01a084fde5d3bc48d8aa38bca92e4fcc5215100", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","nonce": "0x0000000000000000"}` + +// EncodePrefix calculate prefix of the entire signed block +func Test_EncodePrefix(t *testing.T) { + var blockHeader utils.Header + err := json.Unmarshal([]byte(block), &blockHeader) + if err != nil { + log.Fatal("Unmarshal failed", err) + } + prefix := utils.EncodePrefix(blockHeader) + + assert.Equal(t, "\x02\x14", string(prefix)) +} + +// EncodeExtraData calculate prefix of the extraData field without the signatures +func Test_EncodeExtraData(t *testing.T) { + var blockHeader utils.Header + err := json.Unmarshal([]byte(block), &blockHeader) + if err != nil { + log.Fatal("Unmarshal failed", err) + } + prefix := utils.EncodeExtraData(blockHeader) + + assert.Equal(t, "\xa0", string(prefix)) +} + +// EncodeBlock rlp encodes the martialled JSON struct +func Test_EncodeBlock(t *testing.T) { + var blockHeader utils.Header + err := json.Unmarshal([]byte(block), &blockHeader) + if err != nil { + log.Fatal("Unmarshal failed", err) + } + blockInterface := utils.GenerateInterface(blockHeader) + + rlpBlock := utils.EncodeBlock(blockInterface) + + strRlpBlock := hex.EncodeToString(rlpBlock) + assert.Equal(t, EXPECTEDRLPBLOCK, strRlpBlock) +} diff --git a/scripts/killClique b/scripts/killClique deleted file mode 100755 index 51f9057..0000000 --- a/scripts/killClique +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -tmux kill-session -t boot -tmux kill-session -t node1 -tmux kill-session -t node2 -tmux kill-session -t node3 -tmux kill-session -t node diff --git a/scripts/runClique b/scripts/runClique deleted file mode 100755 index 1fa8d65..0000000 --- a/scripts/runClique +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# Launch the boot node -tmux new -s boot -n selsig -d -tmux send-keys -t boot "bootnode -nodekey poa-network/multi-peer/boot.key -verbosity 9 -addr :30310" C-m - -# Launch the noodle 1 -tmux new -s node1 -n geth_and_console -d -tmux send-keys -t node1 "rm -rf poa-network/multi-peer/node1/geth/chaindata" C-m -tmux send-keys -t node1 "rm -rf poa-network/multi-peer/node2/geth/chaindata" C-m -tmux send-keys -t node1 "geth --datadir poa-network/multi-peer/node1/ init poa-network/multi-peer/genesis.json" C-m -tmux send-keys -t node1 "geth --datadir poa-network/multi-peer/node1/ --syncmode 'full' --port 30311 --rpc --rpcaddr 'localhost' --rpcport 8501 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '0' -unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password poa-network/multi-peer/node1/password.txt --mine" C-m -tmux split-window -h -t node1:geth_and_console -tmux send-keys -t node1 "sleep 5s" C-m -tmux send-keys -t node1 "geth attach ipc:poa-network/multi-peer/node1/geth.ipc" C-m - -# Launch the noodle 2 -tmux new -s node2 -n geth_and_console -d -tmux send-keys -t node2 "geth --datadir poa-network/multi-peer/node2/ init poa-network/multi-peer/genesis.json" C-m -tmux send-keys -t node2 "geth --datadir poa-network/multi-peer/node2/ --syncmode 'full' --port 30312 --rpc --rpcaddr 'localhost' --rpcport 8502 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '0' -unlock '0x8671e5e08d74f338ee1c462340842346d797afd3' --password poa-network/multi-peer/node2/password.txt --mine" C-m -tmux split-window -h -t node2:geth_and_console -tmux send-keys -t node2 "sleep 5s" C-m -tmux send-keys -t node2 "geth attach ipc:poa-network/multi-peer/node2/geth.ipc" C-m - -# Launch the noodle 3 - testrpc -tmux new -s node3 -n geth_and_console -d -tmux send-keys -t node3 "npm run testrpc" C-m -tmux split-window -h -t node3:geth_and_console -tmux send-keys -t node3 "sleep 5s" C-m -tmux send-keys -t node3 "geth attach http://127.0.0.1:8545" C-m -tmux ls diff --git a/scripts/runSingleNode b/scripts/runSingleNode deleted file mode 100755 index c380e72..0000000 --- a/scripts/runSingleNode +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Launch the noodle 1 -tmux new -s node1 -n geth_and_console -d -tmux send-keys -t node1 "rm -rf poa-network/single-peer/node1/geth/chaindata" C-m -tmux send-keys -t node1 "geth --datadir poa-network/single-peer/node1/ init poa-network/single-peer/genesis.json" C-m -tmux send-keys -t node1 "geth --datadir poa-network/single-peer/node1/ --syncmode 'full' --rpc --rpcaddr 'localhost' --rpcport 8501 --networkid 1515 --gasprice '0' -unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password poa-network/single-peer/node1/password.txt --mine" C-m -tmux split-window -h -t node1:geth_and_console -tmux send-keys -t node1 "sleep 4s" C-m -tmux send-keys -t node1 "geth attach ipc:poa-network/single-peer/node1/geth.ipc" C-m diff --git a/scripts/runTestrpc b/scripts/runTestrpc deleted file mode 100755 index e5aad34..0000000 --- a/scripts/runTestrpc +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# Launch the noodle 3 - testrpc -tmux new -s node -n geth_and_console -d -tmux send-keys -t node "rm -rf build/contracts/*" C-m -tmux send-keys -t node "npm run testrpc" C-m -tmux split-window -h -t node:geth_and_console -tmux send-keys -t node "sleep 5s" C-m -tmux send-keys -t node "npm run deploy" C-m -tmux send-keys -t node "geth attach http://127.0.0.1:8545" C-m -tmux ls diff --git a/test/ion.js b/test/ion.js index 5a38239..6aafe0c 100644 --- a/test/ion.js +++ b/test/ion.js @@ -91,12 +91,15 @@ contract('Ion.js', (accounts) => { await ion.RegisterChain(TESTCHAINID).should.be.rejected; }) - it('Submit Block', async () => { + it.only('Submit Block', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); await ion.RegisterChain(TESTCHAINID); // Submit block should succeed + console.log(TESTCHAINID) + console.log(TESTBLOCK.hash) + console.log(TESTBLOCK) await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) let blockHash = await ion.m_blockhashes(TESTCHAINID, 0); From 0aaec951bb3acbe9743e41df1d0cf3ca63b7fb47 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 19 Jul 2018 10:00:11 +0100 Subject: [PATCH 065/203] testing changed so integration tests are skipped for CI --- ion-cli/Makefile | 3 +++ ion-cli/contracts/{test_ion.go => ion_test.go} | 9 +++++++++ 2 files changed, 12 insertions(+) rename ion-cli/contracts/{test_ion.go => ion_test.go} (97%) diff --git a/ion-cli/Makefile b/ion-cli/Makefile index d8cf34a..da06ea5 100644 --- a/ion-cli/Makefile +++ b/ion-cli/Makefile @@ -8,6 +8,9 @@ clean: @rm *.out test: + @go test ./... -v -short + +integration-test: @go test ./... -v format: diff --git a/ion-cli/contracts/test_ion.go b/ion-cli/contracts/ion_test.go similarity index 97% rename from ion-cli/contracts/test_ion.go rename to ion-cli/contracts/ion_test.go index 88c7bde..fdf64d1 100644 --- a/ion-cli/contracts/test_ion.go +++ b/ion-cli/contracts/ion_test.go @@ -22,8 +22,14 @@ var TESTBLOCK = []byte(`{'difficulty': 2,'extraData': '0xd88301080b8467657468886 var KEY = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` var IONADDR = common.HexToAddress("0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613") +// NOTE: These tests are skipped if go test -short is called + // Test ion contract gets deployed correctly func Test_IonDeployment(t *testing.T) { + if testing.Short() { + t.Skip("skipping testing in short mode") + } + // Create an IPC based RPC connection to a remote node conn, err := ethclient.Dial(CLIENT) if err != nil { @@ -50,6 +56,9 @@ func Test_IonDeployment(t *testing.T) { // Tests register chain is successful func Test_RegisterChain(t *testing.T) { + if testing.Short() { + t.Skip("skipping testing in short mode") + } // Create an IPC based RPC connection to a remote node conn, err := ethclient.Dial(CLIENT) if err != nil { From d7f430916c05a0799cfaaf8d6a13ea0a2075803f Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 19 Jul 2018 15:24:48 +0100 Subject: [PATCH 066/203] Added instructions on how to do testing and removed all the network stuff :) --- README.md | 56 ++++-------- ion-cli/contracts/ion_test.go | 90 +++++++++++-------- ...--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 0 ion-cli/setup.json | 4 +- poa-network/multi-peer/accounts.txt | 2 - poa-network/multi-peer/boot.key | 1 - poa-network/multi-peer/genesis.json | 33 ------- poa-network/multi-peer/node1/password.txt | 1 - ...--8671e5e08d74f338ee1c462340842346d797afd3 | 1 - poa-network/multi-peer/node2/password.txt | 1 - poa-network/single-peer/accounts.txt | 2 - poa-network/single-peer/genesis.json | 30 ------- ...--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 1 - poa-network/single-peer/node1/password.txt | 1 - test/ion.js | 3 - 15 files changed, 71 insertions(+), 155 deletions(-) rename {poa-network/multi-peer/node1 => ion-cli}/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d (100%) delete mode 100644 poa-network/multi-peer/accounts.txt delete mode 100644 poa-network/multi-peer/boot.key delete mode 100644 poa-network/multi-peer/genesis.json delete mode 100644 poa-network/multi-peer/node1/password.txt delete mode 100644 poa-network/multi-peer/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 delete mode 100644 poa-network/multi-peer/node2/password.txt delete mode 100644 poa-network/single-peer/accounts.txt delete mode 100644 poa-network/single-peer/genesis.json delete mode 100644 poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d delete mode 100644 poa-network/single-peer/node1/password.txt diff --git a/README.md b/README.md index 5f6e7f2..75351f4 100644 --- a/README.md +++ b/README.md @@ -50,51 +50,17 @@ Which hopefully returns this: ├── Makefile ├── migrations ├── package.json -├── poa-network ├── README.md ├── test └── truffle.js ``` -#### Initialise Nodes -Network files are found in the `/path/to/ion/poa-network` directory. Enter the poa-network directory and initialise the two nodes which will be sealing blocks: -``` -$ cd /path/to/ion/poa-network -$ geth --datadir node1/ init genesis.json -$ geth --datadir node2/ init genesis.json -``` - -#### Launch the Bootnode -The boot node tells the peers how to connect with each other. In another terminal instance run: -``` -$ bootnode -nodekey boot.key -verbosity 9 -addr :30310 -$ INFO [06-07|12:16:21] UDP listener up self=enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@[::]:30310 -``` -As the peers communicate this terminal should fill with logs. - -***Note:*** bootnode may not be found if go-ethereum/geth is not installed fully. +### Testing Contracts +In order to test the Solidity contracts using the Javascript tests a testrpc must be run. As the validation contract relies upon receiving signatures in the `extraData` field of the block header it is not sufficient to run an instance of ganache-cli, rather a Clique PoA chain must be initialised. -#### Start and Attach to the Nodes -Each node must be launched either as a background operation or on separate terminal instances. Thus from the poa-network directory for node 1 run: -``` -$ geth --datadir node1/ --syncmode 'full' --port 30311 --rpc --rpcaddr 'localhost' --rpcport 8501 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '1' -unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password node1/password.txt --mine -``` -then attach: -``` -$ geth attach node1/geth.ipc -``` - and again for node 2: -``` -$ geth --datadir node2/ --syncmode 'full' --port 30312 --rpc --rpcaddr 'localhost' --rpcport 8502 --bootnodes 'enode://dcb1dbf8d710eb7d10e0e2db1e6d3370c4b048efe47c7a85c4b537b60b5c11832ef25f026915b803e928c1d93f01b853131e412c6308c4c6141d1504c78823c8@127.0.0.1:30310' --networkid 1515 --gasprice '0' -unlock '0x8671e5e08d74f338ee1c462340842346d797afd3' --password node2/password.txt --mine -``` -attaching: -``` -$ geth attach node2/geth.ipc -``` -***Note:*** that IPC has been used to attach to the nodes, this allows the clique module to be used. +To use the tests please follow the instructions on how to run a single validator Clique chain given [here](https://github.com/maxrobot/network-geth). Additionally you must ensure that the account sealing blocks is identical to that defined in the `validation.js` test itself `0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d`. -### Testing Contracts -After launching the network, from the root of the repository: +Having launched a single-validator clique chain with the sealer `0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d`, run the tests as follows. ``` $ npm install $ npm run test @@ -109,10 +75,18 @@ In its current form the Ion CLI allows the user to connect to two separate block ``` $ cd ion-cli $ make build +``` +In order to run the basic unit tests for the Ion CLI run, +``` $ make test ``` If the tests pass successfully then the CLI can be run. +Additional integration tests can be run however it requires launching a Clique PoA chain as above. To run the integration tests launch command, +``` +$ make integration-test +``` + #### Running Ion CLI As mentioned in the project description this simple implementation of the validation contract is active only on a single blockchain, however the CLI is simulating the passing of the headers to and from as if it were between separate chains. @@ -124,7 +98,7 @@ $ npm run deploy Following this we can attach to the Ion Command Line Interface, ``` -$ cd /path/to/validation/src +$ cd /path/to/ion/ion-cli $ make build ``` Assuming a successful build we must create a setup file which contains the connection of the separate blockchains, user accounts, account keystores, and the address of the deployed validation contract. Change the default values in the example setup.json then run the `ion-cli` poiinting to the modified setup file. @@ -151,8 +125,12 @@ running help displays the available commands. Commands: clear clear the screen exit exit the program + generateTxProof use: generateTxProof [Transaction Hash] [Block Number] + description: Returns the proof of a specific transaction held within a Patricia trie getBlock use: getBlock [integer] description: Returns block header specified + getValidationBlock use: latestValidationBlock + description: Returns hash of the last block submitted to the validation contract getValidators use: getValidators description: Returns the whitelist of validators from validator contract help display help diff --git a/ion-cli/contracts/ion_test.go b/ion-cli/contracts/ion_test.go index fdf64d1..ca2b356 100644 --- a/ion-cli/contracts/ion_test.go +++ b/ion-cli/contracts/ion_test.go @@ -2,12 +2,14 @@ package contract import ( "context" + "encoding/json" "fmt" "log" "math/big" "strings" "testing" + "github.com/clearmatics/ion/ion-cli/utils" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" @@ -18,7 +20,7 @@ var CLIENT = "http://127.0.0.1:8545" var DEPLOYEDCHAINID = "ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" var TESTCHAINID = "22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" -var TESTBLOCK = []byte(`{'difficulty': 2,'extraData': '0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00', 'gasLimit': 5635559972940396, 'gasUsed': 273138, 'hash': '0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4', 'logsBloom': '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 'miner':'0x0000000000000000000000000000000000000000','mixHash': '0x0000000000000000000000000000000000000000000000000000000000000000','nonce':'0x0000000000000000','number': 5446,'parentHash': '0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284','receiptsRoot': '0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1','sha3Uncles':'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347','size': 2027,'stateRoot':'0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967','timestamp': 1531327572,'totalDifficulty': 10893,'transactions': [ '0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3','0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5','0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8','0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6','0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8','0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1','0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446','0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462','0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e','0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314','0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d','0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede','0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc'],'transactionsRoot': '0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35','uncles': []}`) +var TESTBLOCK = `{"difficulty": "2","extraData": "0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00", "gasLimit": "5635559972940396", "gasUsed": "273138", "hash": "0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "miner":"0x0000000000000000000000000000000000000000","mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number": "5446","parentHash": "0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284","receiptsRoot": "0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size": "2027","stateRoot":"0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967","timestamp": "1531327572","totalDifficulty": "10893","transactions": [ "0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3","0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5","0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8","0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6","0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8","0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1","0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446","0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462","0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e","0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314","0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d","0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede","0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc"],"transactionsRoot": "0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35","uncles": []}` var KEY = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` var IONADDR = common.HexToAddress("0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613") @@ -99,43 +101,55 @@ func Test_RegisterChain(t *testing.T) { } // Test the a Tx Proof is successfully validated -// func Test_SubmitBlock(t *testing.T) { -// // Create an IPC based RPC connection to a remote node -// conn, err := ethclient.Dial(CLIENT) -// if err != nil { -// log.Fatalf("Failed to connect to the Ethereum client: %v", err) -// } - -// // Create new transactor -// auth, err := bind.NewTransactor(strings.NewReader(KEY), "password1") -// if err != nil { -// log.Fatalf("Failed to create authorized transactor: %v", err) -// } -// // Get a suggested gas price -// gasPrice, err := conn.SuggestGasPrice(context.Background()) -// if err != nil { -// log.Fatal(err) -// } -// auth.Value = big.NewInt(0) // in wei -// auth.GasLimit = uint64(300000) // in units -// auth.GasPrice = gasPrice - -// ion, err := NewIon(IONADDR, conn) -// if err != nil { -// log.Fatalf("Failed to instantiate Ion contract: %v", err) -// } - -// testChainId := [32]byte{} -// copy(testChainId[:], []byte(TESTCHAINID)) - -// // Register an alternate chain -// _, err = ion.RegisterChain(auth, testChainId) -// if err != nil { -// log.Fatalf("Failed to instantiate Ion contract: %v", err) -// } - -// fmt.Printf("%+v", TESTBLOCK) -// } +func Test_SubmitBlock(t *testing.T) { + // Create an IPC based RPC connection to a remote node + conn, err := ethclient.Dial(CLIENT) + if err != nil { + log.Fatalf("Failed to connect to the Ethereum client: %v", err) + } + + // Create new transactor + auth, err := bind.NewTransactor(strings.NewReader(KEY), "password1") + if err != nil { + log.Fatalf("Failed to create authorized transactor: %v", err) + } + // Get a suggested gas price + gasPrice, err := conn.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatal(err) + } + auth.Value = big.NewInt(0) // in wei + auth.GasLimit = uint64(300000) // in units + auth.GasPrice = gasPrice + + // ion, err := NewIon(IONADDR, conn) + // if err != nil { + // log.Fatalf("Failed to instantiate Ion contract: %v", err) + // } + + deployChainId := [32]byte{} + copy(deployChainId[:], []byte(DEPLOYEDCHAINID)) + + _, _, ion, err := DeployIon(auth, conn, deployChainId) + + testChainId := [32]byte{} + copy(testChainId[:], []byte(TESTCHAINID)) + + // Register an alternate chain + _, err = ion.RegisterChain(auth, testChainId) + if err != nil { + log.Fatalf("Failed to instantiate Ion contract: %v", err) + } + + fmt.Printf("\n%+s", TESTBLOCK) + var blockHeader utils.Header + err = json.Unmarshal([]byte(TESTBLOCK), &blockHeader) + if err != nil { + log.Fatal("Unmarshal failed", err) + } + fmt.Printf("\n%+s", blockHeader) + +} // // Test the a Tx Proof is successfully validated // func Test_TxProof(t *testing.T) { diff --git a/poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/ion-cli/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d similarity index 100% rename from poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d rename to ion-cli/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d diff --git a/ion-cli/setup.json b/ion-cli/setup.json index bf6032c..8a80e72 100644 --- a/ion-cli/setup.json +++ b/ion-cli/setup.json @@ -1,10 +1,10 @@ { "rpc-to":"http://127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", "rpc-from":"http://127.0.0.1:8501", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-from":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f" } diff --git a/poa-network/multi-peer/accounts.txt b/poa-network/multi-peer/accounts.txt deleted file mode 100644 index f349749..0000000 --- a/poa-network/multi-peer/accounts.txt +++ /dev/null @@ -1,2 +0,0 @@ -2be5ab0e43b6dc2908d5321cf318f35b80d0c10d -8671e5e08d74f338ee1c462340842346d797afd3 diff --git a/poa-network/multi-peer/boot.key b/poa-network/multi-peer/boot.key deleted file mode 100644 index d94de32..0000000 --- a/poa-network/multi-peer/boot.key +++ /dev/null @@ -1 +0,0 @@ -8f7dc7dc11a16dcdbbe201b224116c69b00fe547f3b7cb728492994f7d871dcf \ No newline at end of file diff --git a/poa-network/multi-peer/genesis.json b/poa-network/multi-peer/genesis.json deleted file mode 100644 index 8dd1dbb..0000000 --- a/poa-network/multi-peer/genesis.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "config": { - "chainId": 1515, - "homesteadBlock": 1, - "eip150Block": 2, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 3, - "eip158Block": 3, - "byzantiumBlock": 4, - "clique": { - "period": 1, - "epoch": 30000 - } - }, - "nonce": "0x0", - "timestamp": "0x5b165989", - "extraData": "0x00000000000000000000000000000000000000000000000000000000000000002be5ab0e43b6dc2908d5321cf318f35b80d0c10d8671e5e08d74f338ee1c462340842346d797afd30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0xFFFFFF", - "difficulty": "0x1", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "2be5ab0e43b6dc2908d5321cf318f35b80d0c10d": { - "balance": "0x200000000000000000000000000000000000000000000000000000000000000" - }, - "8671e5e08d74f338ee1c462340842346d797afd3": { - "balance": "0x200000000000000000000000000000000000000000000000000000000000000" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/poa-network/multi-peer/node1/password.txt b/poa-network/multi-peer/node1/password.txt deleted file mode 100644 index 4b93364..0000000 --- a/poa-network/multi-peer/node1/password.txt +++ /dev/null @@ -1 +0,0 @@ -password1 diff --git a/poa-network/multi-peer/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 b/poa-network/multi-peer/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 deleted file mode 100644 index a3b0cbe..0000000 --- a/poa-network/multi-peer/node2/keystore/UTC--2018-06-05T09-31-02.740926404Z--8671e5e08d74f338ee1c462340842346d797afd3 +++ /dev/null @@ -1 +0,0 @@ -{"address":"8671e5e08d74f338ee1c462340842346d797afd3","crypto":{"cipher":"aes-128-ctr","ciphertext":"8e132192c0603d01c60ae60c806903d2c2efe7475ba4269620b45203070c8d20","cipherparams":{"iv":"2711ec3033e13c5510dee3b202006307"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"26129bdcf528ce669072b8881a665037388b438495523bc3c29e0b48824fa078"},"mac":"1803bdb38057ecf32870a014307ea380156755f5aa2736ca92fbac7a24c80266"},"id":"a26c0645-090f-440a-9e2b-31f65d0720b2","version":3} \ No newline at end of file diff --git a/poa-network/multi-peer/node2/password.txt b/poa-network/multi-peer/node2/password.txt deleted file mode 100644 index 1a4ccc7..0000000 --- a/poa-network/multi-peer/node2/password.txt +++ /dev/null @@ -1 +0,0 @@ -password2 diff --git a/poa-network/single-peer/accounts.txt b/poa-network/single-peer/accounts.txt deleted file mode 100644 index f349749..0000000 --- a/poa-network/single-peer/accounts.txt +++ /dev/null @@ -1,2 +0,0 @@ -2be5ab0e43b6dc2908d5321cf318f35b80d0c10d -8671e5e08d74f338ee1c462340842346d797afd3 diff --git a/poa-network/single-peer/genesis.json b/poa-network/single-peer/genesis.json deleted file mode 100644 index 5cba62b..0000000 --- a/poa-network/single-peer/genesis.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "config": { - "chainId": 1515, - "homesteadBlock": 1, - "eip150Block": 2, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 3, - "eip158Block": 3, - "byzantiumBlock": 4, - "clique": { - "period": 1, - "epoch": 30000 - } - }, - "nonce": "0x0", - "timestamp": "0x5b165989", - "extraData": "0x00000000000000000000000000000000000000000000000000000000000000002be5ab0e43b6dc2908d5321cf318f35b80d0c10d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0xFFFFFF", - "difficulty": "0x1", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "2be5ab0e43b6dc2908d5321cf318f35b80d0c10d": { - "balance": "0x200000000000000000000000000000000000000000000000000000000000000" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d deleted file mode 100644 index 0d2f3cc..0000000 --- a/poa-network/single-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d +++ /dev/null @@ -1 +0,0 @@ -{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3} \ No newline at end of file diff --git a/poa-network/single-peer/node1/password.txt b/poa-network/single-peer/node1/password.txt deleted file mode 100644 index 4b93364..0000000 --- a/poa-network/single-peer/node1/password.txt +++ /dev/null @@ -1 +0,0 @@ -password1 diff --git a/test/ion.js b/test/ion.js index 6aafe0c..af71329 100644 --- a/test/ion.js +++ b/test/ion.js @@ -97,9 +97,6 @@ contract('Ion.js', (accounts) => { await ion.RegisterChain(TESTCHAINID); // Submit block should succeed - console.log(TESTCHAINID) - console.log(TESTBLOCK.hash) - console.log(TESTBLOCK) await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) let blockHash = await ion.m_blockhashes(TESTCHAINID, 0); From 361c1527fd56d7a9dbe26c2312e4b4337edf08a0 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 20 Jul 2018 17:10:43 +0100 Subject: [PATCH 067/203] Adding docker testrpc --- .travis.yml | 6 +++ Dockerfile | 26 +++++++++++ README.md | 9 ++-- contracts/Validation.sol | 26 ++++++----- ...--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 1 + ...e5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt | 1 + docker_build/clique.json | 30 +++++++++++++ docker_build/launch_geth.sh | 2 + docker_build/password | 1 + package-lock.json | 2 +- test/ion.js | 2 +- test/validation.js | 43 +++++++++++-------- 12 files changed, 110 insertions(+), 39 deletions(-) create mode 100644 Dockerfile create mode 100644 docker_build/account/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d create mode 100644 docker_build/account/password-2be5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt create mode 100644 docker_build/clique.json create mode 100755 docker_build/launch_geth.sh create mode 100644 docker_build/password diff --git a/.travis.yml b/.travis.yml index eaf3140..718cf38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,11 @@ language: go +services: + - docker + +before_install: + - docker build . -t node + matrix: include: - os: linux diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a1bd702 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM ubuntu:16.04 + +LABEL version="1.0" +LABEL maintainer="mgb@clearmatics.com" + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install --yes software-properties-common +RUN add-apt-repository ppa:ethereum/ethereum +RUN apt-get update && apt-get install --yes geth + +RUN adduser --disabled-login --gecos "" eth_user + +COPY docker_build /home/eth_user/docker_build +RUN chown -R eth_user:eth_user /home/eth_user/docker_build + +USER eth_user + +WORKDIR /home/eth_user + +RUN geth --datadir docker_build/account/ init docker_build/clique.json + +EXPOSE 8545 + +ENTRYPOINT bash + diff --git a/README.md b/README.md index 75351f4..39d1570 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,7 @@ In order to use the smart contracts and run the tests it is necessary to first i ### Requirements * golang version: 1.9.x -### Initialise Clique PoA Blockchain -The instructions are based on the tutorial of [Salanfe](https://hackernoon.com/setup-your-own-private-proof-of-authority-ethereum-network-with-geth-9a0a3750cda8) but has the more complicated parts already initialised. - -First install an instance of [geth](https://geth.ethereum.org/downloads/) and clone the repo. - +### Installing Ion Having cloned and entered the repo: ``` $ git clone git@github.com:maxrobot/validation.git @@ -41,6 +37,8 @@ $ tree -L 1 Which hopefully returns this: ``` +. +├── abi ├── CODE_OF_CONDUCT.md ├── contracts ├── CONTRIBUTING.md @@ -50,6 +48,7 @@ Which hopefully returns this: ├── Makefile ├── migrations ├── package.json +├── package-lock.json ├── README.md ├── test └── truffle.js diff --git a/contracts/Validation.sol b/contracts/Validation.sol index e86b3b4..bd9d6e5 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -3,12 +3,11 @@ pragma solidity ^0.4.23; import "./libraries/ECVerify.sol"; -import "./libraries/RLP.sol"; import "./libraries/SolidityUtils.sol"; contract Validation { address owner; - address[] public validators; + address[] validators; uint256 blockHeight; bytes32 blockHash; @@ -22,9 +21,7 @@ contract Validation { mapping (address => bool) m_validators; event broadcastSig(address owner); - event broadcastHashData(bytes header, bytes parentHash, bytes rootHash); event broadcastHash(bytes32 blockHash); - event broadcastHash2(bytes blockHash); /* * @param _validators list of validators at block 0 @@ -71,14 +68,13 @@ contract Validation { * @param prefixHeader the new prefix for the signed hash header * @param prefixExtraData the new prefix for the extraData field */ - function ValidateBlock(bytes _header, bytes prefixHeader, bytes prefixExtraData) public { + function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public { // Check the parent hash is the same as the previous block submitted - bytes32 _parentBlockHash = SolUtils.BytesToBytes32(_header, 4); - + bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header, 4); require(_parentBlockHash==blockHash, "Not child of previous block!"); - uint256 length = _header.length; - bytes32 _blockHash = keccak256(_header); + uint256 length = header.length; + bytes32 _blockHash = keccak256(header); emit broadcastHash(_blockHash); @@ -88,28 +84,30 @@ contract Validation { bytes memory headerEnd = new bytes(42); // Extract the start of the header and replace the length - SolUtils.BytesToBytes(headerStart, _header, 0); + SolUtils.BytesToBytes(headerStart, header, 0); assembly { let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) } // Extract the real extra data and create the signed hash - SolUtils.BytesToBytes(extraData, _header, length-140); + SolUtils.BytesToBytes(extraData, header, length-140); assembly { let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) } // Extract the end of the header - SolUtils.BytesToBytes(headerEnd, _header, length-42); + SolUtils.BytesToBytes(headerEnd, header, length-42); bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); + // emit broadcastHash2(newHeader); + bytes32 hashData = keccak256(newHeader); // Extract the signature of the hash create above - SolUtils.BytesToBytes(extraDataSig, _header, length-107); + SolUtils.BytesToBytes(extraDataSig, header, length-107); address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); - require(m_validators[sig_addr]==true, "Signer not a validator!"); + // require(m_validators[sig_addr]==true, "Signer not a validator!"); // Append the new block to the struct blockHash = _blockHash; diff --git a/docker_build/account/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/docker_build/account/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d new file mode 100644 index 0000000..0d2f3cc --- /dev/null +++ b/docker_build/account/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d @@ -0,0 +1 @@ +{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3} \ No newline at end of file diff --git a/docker_build/account/password-2be5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt b/docker_build/account/password-2be5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt new file mode 100644 index 0000000..06a351c --- /dev/null +++ b/docker_build/account/password-2be5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt @@ -0,0 +1 @@ +password1 \ No newline at end of file diff --git a/docker_build/clique.json b/docker_build/clique.json new file mode 100644 index 0000000..1e4dff0 --- /dev/null +++ b/docker_build/clique.json @@ -0,0 +1,30 @@ +{ + "config": { + "chainId": 1515, + "homesteadBlock": 1, + "eip150Block": 2, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 3, + "eip158Block": 3, + "byzantiumBlock": 4, + "clique": { + "period": 1, + "epoch": 30000 + } + }, + "nonce": "0x0", + "timestamp": "0x5b165989", + "extraData": "0x00000000000000000000000000000000000000000000000000000000000000002be5ab0e43b6dc2908d5321cf318f35b80d0c10d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0xFFFFFFFFFFFF", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "2be5ab0e43b6dc2908d5321cf318f35b80d0c10d": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/docker_build/launch_geth.sh b/docker_build/launch_geth.sh new file mode 100755 index 0000000..8c0c657 --- /dev/null +++ b/docker_build/launch_geth.sh @@ -0,0 +1,2 @@ +!#/bin/bash +geth --datadir eth_common/account/ --syncmode 'full' --port 30311 --rpc --rpcaddr '0.0.0.0' --rpcport 8545 --networkid 1515 --gasprice '0' --targetgaslimit 0xFFFFFFFFFFFF --unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password eth_common/account/password-2be5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt --mine diff --git a/docker_build/password b/docker_build/password new file mode 100644 index 0000000..7bb7ff6 --- /dev/null +++ b/docker_build/password @@ -0,0 +1 @@ +here_is_password diff --git a/package-lock.json b/package-lock.json index 133c62c..0c2c273 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2522,7 +2522,7 @@ } }, "eth-proof": { - "version": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#35a299bc72d30b72ff6f2a4e0100caaf3516cfe2", + "version": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#f3a79ae8b86e5904eeabfac68b1a82f865c2affa", "requires": { "ethereumjs-block": "1.7.1", "ethereumjs-tx": "1.3.6", diff --git a/test/ion.js b/test/ion.js index af71329..5a38239 100644 --- a/test/ion.js +++ b/test/ion.js @@ -91,7 +91,7 @@ contract('Ion.js', (accounts) => { await ion.RegisterChain(TESTCHAINID).should.be.rejected; }) - it.only('Submit Block', async () => { + it('Submit Block', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); await ion.RegisterChain(TESTCHAINID); diff --git a/test/validation.js b/test/validation.js index 35c3749..91a0fdd 100644 --- a/test/validation.js +++ b/test/validation.js @@ -67,7 +67,9 @@ contract.only('Validation.js', (accounts) => { const blockNum = 1; // Hash of the genesis block - const genHash = "0xfddbd5fe1a53989f2730c8f5cfd36eed28a8bf0837d6e95f9aa1e5fc01d157d9"; + const genesisBlock = web3.eth.getBlock(0); + // const genHash = genesisBlock.hash; + const genHash = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; // Find the validator of block 1 as it is not known a priori const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; @@ -152,13 +154,14 @@ contract.only('Validation.js', (accounts) => { const encodedBlockHeader = '0x' + rlp.encode(blockHeader).toString('hex'); const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); assert.equal(block.hash, blockHeaderHash); - + const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); const headerHash = Web3Utils.sha3(encodedHeader); - // The new prefixes should be calculated off chain - const prefixHeader = '0x0214'; - const prefixExtraData = '0xa0'; + // Get Prefixes + const prefixHeader = '0x' + encodedHeader.substring(4, 8); + const prefixExtraData = '0x' + encodedExtraData.substring(2,4); const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; @@ -221,6 +224,7 @@ contract.only('Validation.js', (accounts) => { // Encode and sign the new header const encodedHeader = '0x' + rlp.encode(header).toString('hex'); + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); const headerHash = Util.sha3(encodedHeader); // However we cannot be sure which validator is s @@ -257,9 +261,9 @@ contract.only('Validation.js', (accounts) => { const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); assert.equal(block.hash, blockHeaderHash); - // The new prefixes should be calculated off chain - const prefixHeader = '0x0214'; - const prefixExtraData = '0xa0'; + // Get Prefixes + const prefixHeader = '0x' + encodedHeader.substring(4, 8); + const prefixExtraData = '0x' + encodedExtraData.substring(2,4); const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; @@ -271,7 +275,7 @@ contract.only('Validation.js', (accounts) => { it('Test: Inauthentic Block Submission - ValidateBlock()', async () => { const validation = await Validation.new(validators, genHash); const accounts = web3.eth.accounts; - const signer = validators[1]; + const signer = validators[0]; // Get a single block const block = web3.eth.getBlock(blockNum); @@ -325,7 +329,7 @@ contract.only('Validation.js', (accounts) => { const encodedHeader = '0x' + rlp.encode(header).toString('hex'); const headerHash = Util.sha3(encodedHeader); - const privateKey = Buffer.from('d18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083', 'hex') + const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') const sig = Util.ecsign(headerHash, privateKey) if (this._chainId > 0) { @@ -338,12 +342,13 @@ contract.only('Validation.js', (accounts) => { const newSigBytes = Buffer.concat([sig.r, sig.s]); let newSig; + // Need to understand why but signature requires different v than in others to recover correctly const bytes = hexToBytes(extraData); const finalByte = bytes.splice(bytes.length-1); if (finalByte.toString('hex')=="00") - newSig = newSigBytes.toString('hex') + '00'; - else (finalByte.toString('hex')=="01") newSig = newSigBytes.toString('hex') + '01'; + else (finalByte.toString('hex')=="01") + newSig = newSigBytes.toString('hex') + '00'; // Append signature to the end of extraData const sigBytes = hexToBytes(newSig.toString('hex')); @@ -370,11 +375,12 @@ contract.only('Validation.js', (accounts) => { ]; const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - // The new prefixes should be calculated off chain - const prefixHeader = '0x0214'; - const prefixExtraData = '0xa0'; + // Get Prefixes + const prefixHeader = '0x' + encodedHeader.substring(4, 8); + const prefixExtraData = '0x' + encodedExtraData.substring(2,4); const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; @@ -484,11 +490,12 @@ contract.only('Validation.js', (accounts) => { ]; const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - // The new prefixes should be calculated off chain - const prefixHeader = '0x0214'; - const prefixExtraData = '0xa0'; + // Get Prefixes + const prefixHeader = '0x' + encodedHeader.substring(4, 8); + const prefixExtraData = '0x' + encodedExtraData.substring(2,4); try { const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); From 2c3da0237c8ac28da19b25be9c5733e37b0696f6 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Sun, 22 Jul 2018 11:25:40 +0100 Subject: [PATCH 068/203] docker should launch testrpc in the background... I hope --- .travis.yml | 3 +++ docker_build/launch_geth.sh | 2 +- ...31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 1 + ion-cli/config/config_test.go | 2 +- ion-cli/contracts/ion_test.go | 4 ++++ 5 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d diff --git a/.travis.yml b/.travis.yml index 718cf38..d7af338 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ services: before_install: - docker build . -t node + - docker run --name testrpc --rm -d -it -p 127.0.0.1:8545:8545 node bash + - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh matrix: include: @@ -15,6 +17,7 @@ matrix: - cd ./ion-cli - go get -t ./... - make test + - make integration-test notifications: slack: diff --git a/docker_build/launch_geth.sh b/docker_build/launch_geth.sh index 8c0c657..e211e66 100755 --- a/docker_build/launch_geth.sh +++ b/docker_build/launch_geth.sh @@ -1,2 +1,2 @@ !#/bin/bash -geth --datadir eth_common/account/ --syncmode 'full' --port 30311 --rpc --rpcaddr '0.0.0.0' --rpcport 8545 --networkid 1515 --gasprice '0' --targetgaslimit 0xFFFFFFFFFFFF --unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password eth_common/account/password-2be5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt --mine +geth --datadir docker_build/account/ --syncmode 'full' --port 30311 --rpc --rpcaddr '0.0.0.0' --rpcport 8545 --networkid 1515 --gasprice '0' --targetgaslimit 0xFFFFFFFFFFFF --unlock '0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d' --password docker_build/account/password-2be5ab0e43b6dc2908d5321cf318f35b80d0c10d.txt --mine diff --git a/ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d new file mode 100644 index 0000000..0d2f3cc --- /dev/null +++ b/ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d @@ -0,0 +1 @@ +{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3} \ No newline at end of file diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 92eeff5..a3c6e2f 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -22,7 +22,7 @@ func Test_Read_ValidSetupJson(t *testing.T) { } func Test_Read_ValidKeystore(t *testing.T) { - path := findPath() + "../../poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + path := findPath() + "./UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" contents := config.ReadString(path) const val = "{\"address\":\"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa\",\"cipherparams\":{\"iv\":\"4aa66b789ee2d98cf77272a72eeeaa50\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e\"},\"mac\":\"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3\"},\"id\":\"a3cc1eae-3e36-4659-b759-6cf416216e72\",\"version\":3}" diff --git a/ion-cli/contracts/ion_test.go b/ion-cli/contracts/ion_test.go index ca2b356..0a6a00e 100644 --- a/ion-cli/contracts/ion_test.go +++ b/ion-cli/contracts/ion_test.go @@ -102,6 +102,10 @@ func Test_RegisterChain(t *testing.T) { // Test the a Tx Proof is successfully validated func Test_SubmitBlock(t *testing.T) { + if testing.Short() { + t.Skip("skipping testing in short mode") + } + // Create an IPC based RPC connection to a remote node conn, err := ethclient.Dial(CLIENT) if err != nil { From 4c49d51742cbd8afcd114032b1e3336d052cd3ae Mon Sep 17 00:00:00 2001 From: maxrobot Date: Sun, 22 Jul 2018 11:37:45 +0100 Subject: [PATCH 069/203] Mapped to the correct clique port and testing the npm in travis --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d7af338..50f069d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ services: before_install: - docker build . -t node - - docker run --name testrpc --rm -d -it -p 127.0.0.1:8545:8545 node bash + - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh matrix: @@ -14,10 +14,11 @@ matrix: dist: trusty go: 1.9.x script: + - npm install + - npm run test - cd ./ion-cli - go get -t ./... - make test - - make integration-test notifications: slack: From 0262b3e8ab9455515d62e01efda2617398b39490 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Sun, 22 Jul 2018 11:45:46 +0100 Subject: [PATCH 070/203] previous build failed due to access rights for shirikatsu/eth-proof using https --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6288097..a950788 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", - "eth-proof": "git@github.com:Shirikatsu/eth-proof.git#log-encoding", + "eth-proof": "git+https://git@github.com:Shirikatsu/eth-proof.git#log-encoding", "ethereumjs-block": "^2.0.0", "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", From 9f84cc724d8517739b6e9a7a96cbccd8e0cc3067 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Sun, 22 Jul 2018 13:25:16 +0100 Subject: [PATCH 071/203] typo in the way git repo was downloaded --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a950788..dfb787f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", - "eth-proof": "git+https://git@github.com:Shirikatsu/eth-proof.git#log-encoding", + "eth-proof": "git+https://github.com:Shirikatsu/eth-proof.git#log-encoding", "ethereumjs-block": "^2.0.0", "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", From f5ca3400530cf8eb32d8dee6adcfe60ca1e93e47 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Sun, 22 Jul 2018 13:33:16 +0100 Subject: [PATCH 072/203] Path was incorrect for packages.json --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c2c273..af7978e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2522,7 +2522,7 @@ } }, "eth-proof": { - "version": "git+ssh://git@github.com/Shirikatsu/eth-proof.git#f3a79ae8b86e5904eeabfac68b1a82f865c2affa", + "version": "git+https://github.com/Shirikatsu/eth-proof.git#f3a79ae8b86e5904eeabfac68b1a82f865c2affa", "requires": { "ethereumjs-block": "1.7.1", "ethereumjs-tx": "1.3.6", diff --git a/package.json b/package.json index dfb787f..a760d5b 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", - "eth-proof": "git+https://github.com:Shirikatsu/eth-proof.git#log-encoding", + "eth-proof": "git+https://github.com/Shirikatsu/eth-proof.git#log-encoding", "ethereumjs-block": "^2.0.0", "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", From c7a8b3068a7d1319bbbafc64e69f355475478551 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Sun, 22 Jul 2018 13:52:47 +0100 Subject: [PATCH 073/203] Dealt with the issue of sig.v being defined incorrectly for inauthentic block submission --- .travis.yml | 1 - test/validation.js | 13 ++++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 50f069d..d1906cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,5 @@ matrix: notifications: slack: - on_success: never on_failure: always secure: k6j6BWCTMJ6U7JXhy0yBcJpfkOw4eUNnL9xyufiI6Ue5Cf+NvN9FJxNZvoz4BvVSitq/BSlcWGjQoIW5AoWtf15tl4hvQmFN4YYHT79TKjRGEcSBg1+D55aXmjIM3UwHtCOuSJxAkl7dTgWAJ3FU0/aBqy96OsODjhcP8VeuMay+2Z+kT/QQjtO5rduHfLpeJxVfoEdhXR9QjHozV287rE49E6wWV6KzNCDOYy3CFGkQsgBQzlxkmlvhwbjDeNb72UcruSh50ic78/NLru3AXwRFx2yc1fkr2Nv9q6l5r9I1iWek8EZ46OCe/dQ004s7PI7knVx1vssdA3ksLDyRzhNHvWpn1EI1fi4Aqc+ki9vHbccR5c1pw85zwcQiLEoVFpJ+MpfHi9ExmAJmvvrzz2RBMqsL5JuSfInxiSLyX6vSVpufgZYrDKAemWXhR030dQQZ8BVQOCbt2lzCgHZajmDvrOktq6QdTFzEz/JjyorXn+0Rpho+7FHY5sW9KdgvmexI9SAjjz0BgcQzof9QKpyuRZpbboWRxPsfPUQDlx+Wxm541ndunGNQ2mVXqSgKaTQShiKhhu7dOPevw1a+dreJ6n8afL9pfW4SHcs0O+FlHvAnLAbRDvbnxROF89RRDiTVBdC6h7vcAX6lNDFUxF0F1bYTiWE0s4+umB2zlqc= diff --git a/test/validation.js b/test/validation.js index 91a0fdd..cfe8d81 100644 --- a/test/validation.js +++ b/test/validation.js @@ -227,8 +227,6 @@ contract.only('Validation.js', (accounts) => { const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); const headerHash = Util.sha3(encodedHeader); - // However we cannot be sure which validator is s - // const privateKey = Buffer.from('d18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083', 'hex') const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') let signature = await signHeader(headerHash, privateKey, extraData); @@ -338,17 +336,18 @@ contract.only('Validation.js', (accounts) => { const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); const addrBuf = Util.pubToAddress(pubKey); + assert.equal(signer, '0x'+addrBuf.toString('hex')); const newSigBytes = Buffer.concat([sig.r, sig.s]); let newSig; // Need to understand why but signature requires different v than in others to recover correctly - const bytes = hexToBytes(extraData); - const finalByte = bytes.splice(bytes.length-1); - if (finalByte.toString('hex')=="00") - newSig = newSigBytes.toString('hex') + '01'; - else (finalByte.toString('hex')=="01") + if (sig.v=="27") { newSig = newSigBytes.toString('hex') + '00'; + } + if (sig.v=="28") { + newSig = newSigBytes.toString('hex') + '01'; + } // Append signature to the end of extraData const sigBytes = hexToBytes(newSig.toString('hex')); From 7a7d0cbeb18ed3f4294e1703644c6fdf8edcbec7 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Tue, 24 Jul 2018 14:53:26 +0100 Subject: [PATCH 074/203] Patricia proofs now account for vestigial nodes. **NOTE**: UNTESTED --- contracts/EventConsuming.sol | 21 ----- contracts/EventVerifier.sol | 24 ++++++ contracts/PatriciaTrie.sol | 122 +++++++++++++++++++--------- contracts/Trigger.sol | 9 +++ test/ion.js | 153 ++++++++++++++++++++++++++++------- test/rinkeby.js | 128 +++++++++++++++++++++++++++++ test/trie.js | 77 ++++++++++++++++++ 7 files changed, 446 insertions(+), 88 deletions(-) delete mode 100644 contracts/EventConsuming.sol create mode 100644 contracts/EventVerifier.sol create mode 100644 contracts/Trigger.sol create mode 100644 test/rinkeby.js create mode 100644 test/trie.js diff --git a/contracts/EventConsuming.sol b/contracts/EventConsuming.sol deleted file mode 100644 index dfea2b0..0000000 --- a/contracts/EventConsuming.sol +++ /dev/null @@ -1,21 +0,0 @@ -pragma solidity ^0.4.23; - -contract EventConsuming { - uint256[] consumedNonces; - address ionCompatible; - - constructor(address _ionCompAddress) public { - ionCompatible = _ionCompAddress; - } - - modifier IonCompatibleOnly(){ - require( msg.sender == ionCompatible, - "Caller is not IonCompatible contract." - ); - _; - } - - function consumeEvent(uint256 nonce) internal { - consumedNonces.push(nonce); - } -} \ No newline at end of file diff --git a/contracts/EventVerifier.sol b/contracts/EventVerifier.sol new file mode 100644 index 0000000..ba884c4 --- /dev/null +++ b/contracts/EventVerifier.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.23; + +import "./RLP.sol"; + +contract EventVerifier { + + function verify(bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool) { + RLP.RLPItem[] memory receipt = RLP.toList(RLP.toRLPItem(_rlpReceipt)); + + RLP.RLPItem[] memory logs = RLP.toList(receipt[3]); + + require( logs.length == 1 ); + + bytes memory b_address = RLP.toBytes(logs[0]); + bytes20 b20_address; + assembly { + b20_address := mload(add(b_address, 0)) + } + + require( b20_address == _expectedAddress ); + + return true; + } +} diff --git a/contracts/PatriciaTrie.sol b/contracts/PatriciaTrie.sol index 65b35a2..105cf6f 100644 --- a/contracts/PatriciaTrie.sol +++ b/contracts/PatriciaTrie.sol @@ -9,60 +9,108 @@ library PatriciaTrie { RLP.RLPItem[] memory parentNodes = RLP.toList(nodes); bytes32 currentNodeKey = _root; - bytes memory b_currentNode; - RLP.RLPItem[] memory currentNode; uint traversedNibbles = 0; bytes memory path = toNibbleArray(_path, false); for (uint i = 0; i < parentNodes.length; i++) { - b_currentNode = RLP.toBytes(parentNodes[i]); - - if (currentNodeKey != keccak256(b_currentNode)) { + if (currentNodeKey != keccak256(RLP.toBytes(parentNodes[i]))) { return false; } - currentNode = RLP.toList(parentNodes[i]); + RLP.RLPItem[] memory currentNode = RLP.toList(parentNodes[i]); if (currentNode.length == 17) { // Branch Node - if (traversedNibbles == path.length) { - - if(keccak256(RLP.toBytes(currentNode[16])) == keccak256(_value)) { - return true; - } else { - return false; - } - } - - uint16 nextPathNibble = uint16(path[traversedNibbles]); - currentNodeKey = RLP.toBytes32(currentNode[nextPathNibble]); - traversedNibbles += 1; - + (currentNodeKey, traversedNibbles) = processBranchNode(currentNode, traversedNibbles, path, _value); } else if (currentNode.length == 2) { // Extension/Leaf Node - bytes memory nextPathNibbles = RLP.toData(currentNode[0]); - traversedNibbles += toNibbleArray(nextPathNibbles, true).length; - - if (traversedNibbles == path.length) { - if(keccak256(RLP.toData(currentNode[1])) == keccak256(_value)) { - return true; - } else { - return false; - } - } - - // Reached a leaf before end of the path. Proof false. - if (toNibbleArray(nextPathNibbles, true).length == 0) { - return false; - } - - bytes memory nextNodeKey = RLP.toData(currentNode[1]); - currentNodeKey = bytesToBytes32(nextNodeKey, 0); + (currentNodeKey, traversedNibbles) = processExtensionLeafNode(currentNode, traversedNibbles, path, _value); } else { return false; } + + // Read comment block below for explanation of this + if (currentNodeKey == 0x0) { + return traversedNibbles == 1; + } + } + } + + /** + Node Processing + + processBranchNodes returns (bytes32 currentNodeKey, uint traversedNibbles) + processExtensionLeafNode returns (bytes32 currentNodeKey, uint traversedNibbles) + + Due to the dual nature of how a branch node may be processed where the next node in the path could be either + referenced by hash or nested in the branch node is the total RLP-encoded node is less than 32 bytes (vestigial node), + we required separation of logic due to "stack-too-deep" issues and opted for a messy returning of reused variables. + These returned variables now hold two purposes: + + * currentNodeKey (bytes32): Holds value of the hash of the next node to be processed. If processing is finished this + value is 0x0. + * traversedNibbles (uint): Tracks how many nibbles have been traversed. If processing is finished this value will + be 0 if verification failed, and 1 if verification succeeded. + + The dual-functionality of these variables is the crux of how I avoided stack issues which makes the code somewhat + unreadable. If there is an improvement to this algorithm that can make it more readable please share. + + */ + + function processBranchNode(RLP.RLPItem[] memory _currentNode, uint _traversedNibbles, bytes memory _path, bytes _value) private returns (bytes32, uint) { + if (_traversedNibbles == _path.length) { + return (0x0, checkNodeValue(_value, RLP.toBytes(_currentNode[16])) ? 1 : 0); + } + + uint16 nextPathNibble = uint16(_path[_traversedNibbles]); + RLP.RLPItem memory nextNode = _currentNode[nextPathNibble]; + _traversedNibbles += 1; + + bytes32 currentNodeKey; + if (RLP.toBytes(nextNode).length < 32) { + //Vestigial 'Node' + (currentNodeKey, _traversedNibbles) = processVestigialNode(nextNode, _traversedNibbles, _path, _value); + } else { + currentNodeKey = RLP.toBytes32(_currentNode[nextPathNibble]); + } + return (currentNodeKey, _traversedNibbles); + } + + function processExtensionLeafNode(RLP.RLPItem[] memory _currentNode, uint _traversedNibbles, bytes memory _path, bytes _value) private returns (bytes32, uint) { + bytes memory nextPathNibbles = RLP.toData(_currentNode[0]); + _traversedNibbles += toNibbleArray(nextPathNibbles, true).length; + + if (_traversedNibbles == _path.length) { + return (0x0, checkNodeValue(_value, RLP.toData(_currentNode[1])) ? 1 : 0); } + + // Reached a leaf before end of the path. Proof false. + if (toNibbleArray(nextPathNibbles, true).length == 0) { + return (0x0, 0); + } + + bytes memory nextNodeKey = RLP.toData(_currentNode[1]); + bytes32 currentNodeKey = bytesToBytes32(nextNodeKey, 0); + + return (currentNodeKey, _traversedNibbles); + } + + function processVestigialNode(RLP.RLPItem memory _nextNode, uint _traversedNibbles, bytes memory _path, bytes _value) private returns (bytes32, uint) { + RLP.RLPItem[] memory currentNode = RLP.toList(_nextNode); + if (currentNode.length == 17) { + // Extension Node + return processBranchNode(currentNode, _traversedNibbles, _path, _value); + } else if (currentNode.length == 2) { + // Leaf Node + return processExtensionLeafNode(currentNode, _traversedNibbles, _path, _value); + } else { + return (0x0, 0); + } + } + + function checkNodeValue(bytes _expected, bytes _nodeValue) private returns (bool) { + return keccak256(_expected) == keccak256(_nodeValue); } function toNibbleArray(bytes b, bool hexPrefixed) private pure returns (bytes) { diff --git a/contracts/Trigger.sol b/contracts/Trigger.sol new file mode 100644 index 0000000..ece8548 --- /dev/null +++ b/contracts/Trigger.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.4.23; + +contract Trigger { + event Triggered(address caller); + + function fire() public { + emit Triggered(msg.sender); + } +} diff --git a/test/ion.js b/test/ion.js index ca2b5a4..97cee01 100644 --- a/test/ion.js +++ b/test/ion.js @@ -5,19 +5,16 @@ const Web3Utils = require('web3-utils'); const BN = require('bignumber.js') const merkle = require('./helpers/merkle.js') const encoder = require('./helpers/encoder.js') -const Trie = require('merkle-patricia-tree'); const rlp = require('rlp'); const async = require('async') -const EthereumTx = require('ethereumjs-tx'); -const EthereumBlock = require('ethereumjs-block/from-rpc') const levelup = require('levelup'); const sha3 = require('js-sha3').keccak_256 -const EP = require('eth-proof'); const Web3 = require('web3'); const Ion = artifacts.require("Ion"); const PatriciaTrie = artifacts.require("PatriciaTrie"); +const Function = artifacts.require("Function"); require('chai') .use(require('chai-as-promised')) @@ -26,37 +23,107 @@ require('chai') const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" + +/* +MAIN NET TEST DATA +*/ + +//const TESTBLOCK = { +// difficulty: 12549329517745, +// extraData: "0xd783010303844765746887676f312e352e31856c696e7578", +// gasLimit: 3141592, +// gasUsed: 63000, +// hash: "0x95c3a05973fec7bf98f1131a72e607b4eba171d0576571cf83ee7162bbcdb7d9", +// logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", +// miner: "0x95581ea0c5b362933f3523138f54d51eae817211", +// mixHash: "0xa01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6", +// nonce: "0x1c080c4ec6f2553b", +// number: 1000002, +// parentHash: "0xcb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4f", +// receiptsRoot: "0x97097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647", +// sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", +// size: 883, +// stateRoot: "0x643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5", +// timestamp: 1455404078, +// totalDifficulty: 7135227569124568698, +// transactions: ["0x2bd653c639c086ad1c6e468d2cbdba76fc144f747373be6d2db7854d0d0e36e7", "0x7e3abff232dd5fc72db441807bcd59d9f17311a960a8f6ff6d0e693c22fa1eb2", "0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893"], +// transactionsRoot: "0xdbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2", +// uncles: [] +//} +// +//const TESTRLPENCODING = "0xf90217a0cb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495581ea0c5b362933f3523138f54d51eae817211a0643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5a0dbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2a097097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000860b69de53fcb1830f4242832fefd882f6188456bfb42e98d783010303844765746887676f312e352e31856c696e7578a0a01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6881c080c4ec6f2553b" +//const TEST_PATH = "0x02" +// +//const TEST_TX_VALUE = "0xf8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" +//const TEST_TX_NODES = "0xf9011df851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" +// +//const TEST_RECEIPT_VALUE = "0xf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" +//const TEST_RECEIPT_NODES = "0xf901d8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" + +/* +RINKEBY TEST DATA +*/ + const TESTBLOCK = { - difficulty: 12549329517745, - extraData: "0xd783010303844765746887676f312e352e31856c696e7578", - gasLimit: 3141592, - gasUsed: 63000, - hash: "0x95c3a05973fec7bf98f1131a72e607b4eba171d0576571cf83ee7162bbcdb7d9", - logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - miner: "0x95581ea0c5b362933f3523138f54d51eae817211", - mixHash: "0xa01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6", - nonce: "0x1c080c4ec6f2553b", - number: 1000002, - parentHash: "0xcb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4f", - receiptsRoot: "0x97097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647", - sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - size: 883, - stateRoot: "0x643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5", - timestamp: 1455404078, - totalDifficulty: 7135227569124568698, - transactions: ["0x2bd653c639c086ad1c6e468d2cbdba76fc144f747373be6d2db7854d0d0e36e7", "0x7e3abff232dd5fc72db441807bcd59d9f17311a960a8f6ff6d0e693c22fa1eb2", "0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893"], - transactionsRoot: "0xdbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2", + difficulty: 2, + extraData: '0xd68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100', + gasLimit: 7509409, + gasUsed: 2883490, + hash: '0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7', + logsBloom: '0x22440000020000090000000000000000041000080000008000088000080000000200000400000800000000000000400000000000000000000010000008020102000000000000080000000008800000000000022000000004000000010000000000080000000620400440100010200400082000000000000080040010000100020020000000000000080080000001000000000100000400480000000002000000002000080018000008108000100000000000000000020000050010001004000000000102000040004000000000000000000000004400000000000000000000000208000000000400008200020000004022400000000004000200848000000000', + miner: '0x0000000000000000000000000000000000000000', + mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x0000000000000000', + number: 2657422, + parentHash: '0x3471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35', + receiptsRoot: '0x907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ff', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: 4848, + stateRoot: '0xf526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444', + timestamp: 1531931421, + totalDifficulty: 5023706, + transactions: + [ '0x7adbc5ee3712552a1e85962c3ea3d82394cfed7960d60c12d60ebafe67445450', + '0x6be870e6dfb11894b64371560ec39e563cef91642afd193bfa67874f3508a282', + '0x5ba6422455cb7127958df15c453bfe60d92921b647879864b531fd6589e36af4', + '0xa2597e6fe6882626e12055b1378025aa64a85a03dd23f5dc66034f2ef3746810', + '0x7ffb940740050ae3604f99a4eef07c83de5d75076cae42cb1561c370cba3a0a3', + '0x4d6326a6d4cf606c7e44a4ae6710acd3876363bcaabd1b1b59d29fff4da223c5', + '0x10b3360ef00cd7c4faf826365fddbd33938292c98c55a4cdb37194a142626f63', + '0x655290cb44be2e64d3b1825a86d5647579015c5cffb03ede7f67eb34cea6b97f', + '0x6b5e025ea558f4872112a39539ce9a819bfbb795b04eefcc45e1cf5ea947614c', + '0xefd68b516babcf8a4ca74a358cfca925d9d2d5177ef7b859f3d9183ff522efe8', + '0xa056eeeeb098fd5adb283e12e77a239797c96860c21712963f183937613d3391', + '0xa5d1adf694e3442975a13685a9c7d9013c05a4fdcea5bc827566a331b2fead2b', + '0x95a47360f89c48f0b1a484cbeee8816b6a0e2fc321bdb9db48082bd7272b4ebc', + '0x896d29a87393c6607844fa545d38eb96056d5310a6b4e056dc00adde67c24be2', + '0xef3ce2ad9259920094f7fd5ad00453b35888662696ae9b85a393e55cde3ec28d', + '0x2de8af9b4e84b3ac93adfce81964cc69bafd0a2dbcac3a5f7628ee9e56fd1c8a', + '0x2790cdb3377f556e8f5bc8eaaf9c6c0d36d0f242c2e4226af2aac0203f43019b', + '0x98ae65246249785bd1ac8157900f7e1a2c69d5c3b3ffc97d55b9eacab3e212f0', + '0x7d4f090c58880761eaaab1399864d4a52631db8f0b21bfb7051f9a214ad07993', + '0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e', + '0x2af8f6c49d1123077f1efd13764cb2a50ff922fbaf49327efc44c6048c38c968', + '0x6d5e1753dc91dae7d528ab9b02350e726e006a5591a5d315a34a46e2a951b3fb', + '0xdc864827159c7fde6bbd1672ed9a90ce5d69f5d0c81761bf689775d19a90387e', + '0x22fb4d90a7125988b2857c50709e544483f898cb1e8036477f9ddd94b177bf93', + '0x999c2e2ba342bed4ccedea01d638db3bbd1abd6d10784c317843880841db6dec', + '0x11355abb5fe745ed458b2a78e116f4a8c2fe046a131eafe08f30d23bd9d10394' ], + transactionsRoot: '0x07f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586', uncles: [] } -const TESTRLPENCODING = "0xf90217a0cb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495581ea0c5b362933f3523138f54d51eae817211a0643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5a0dbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2a097097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000860b69de53fcb1830f4242832fefd882f6188456bfb42e98d783010303844765746887676f312e352e31856c696e7578a0a01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6881c080c4ec6f2553b" -const TEST_PATH = "0x02" +const TESTRLPENCODING = "0xf9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +const TEST_PATH = "0x13" + +const TEST_TX_VALUE = "0xf86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" +const TEST_TX_NODES = "0xf90235f871a0804f9c841a6a1d3361d79980581c84e5b4d3e4c9bf33951346775542d0ee0728a0edadb5e660118ea4323654191131b62c81fc00203a15a21c925f9f50d0e4b3e4808080808080a03eda2d64b94c5ed45026a29c75c99677d44c561ea5efea30c1db6299871d5c2e8080808080808080f90151a0bc285699e68d2fe18e7af2cdf7e7e6456e91a3fd31e3c9935bc5bef92e94bf4ba06eb963b2c3a3b6c07a7221aa6f6f86f7cb8ddb45ab1ff1a9dc781f34da1f081fa0deea5b5566e7a5634d91c5fb56e25f4370e3531e2fd71ee17ed6c4ad0be2ced3a0b4e9d14555f162e811cfbcbff9b98a271a197b75271565f693912c2ff75e2131a03b0bc2d764fbefd76848ee2da7b211eb230ede08d8c54e6a868be9f5e42122c1a0b6dd488ad4fb82b0a98dff81ac6766d1dec26b29dc06174de1d315b0ab0bdf0ca066c20ff06dc33777f53eec32b0b9a8d99872bec24bb3998bb520ae6897c21d7ea02db2a399f611ba7993efb4768938a6f61b4add8959ce4c89f201f41e882ff375a02e31051a9f938b9b342b8070db3dd829f62da8d0c83a6dff91a4e3b4cb2adb9ea090e75708e7dbf856b75ed126a960085419fcde0e6a0129a92dffc0cb83ac089680808080808080f86c20b869f86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" -const TEST_TX_VALUE = "0xf8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" -const TEST_TX_NODES = "0xf9011df851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" +const TEST_RECEIPT_VALUE = "0xf901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" +const TEST_RECEIPT_NODES = "0xf90335f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" -const TEST_RECEIPT_VALUE = "0xf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" -const TEST_RECEIPT_NODES = "0xf901d8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" +const TRIG_FIRED_RINKEBY_TXHASH = "0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e" +const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { @@ -159,8 +226,9 @@ contract('Ion.js', (accounts) => { await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); - let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH); + nodes = generateTestReceiptRLPNodes(); + let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, "0x"+nodes.toString('hex'), TEST_PATH); console.log("Gas used to submit check receipt proof = " + tx.receipt.gasUsed.toString() + " gas"); }) @@ -213,3 +281,28 @@ contract('Ion.js', (accounts) => { await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; }) }) + +async function verifyReceipts(eP, txHash) { + await eP.getReceiptTrieRoot(txHash).then( (root) => { + console.log("EP RECEIPT Root hash = 0x" + root.toString('hex')) + }) + + var verified; + await eP.getReceiptProof(txHash).then( (proof) => { + verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); + }) + return verified; +} + +function generateTestReceiptRLPNodes() { + let root = Buffer.from("f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080", 'hex'); + second = Buffer.from("f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080", 'hex'); + leaf = Buffer.from("f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e", 'hex'); + + decodedRoot = rlp.decode(root); + decodedSecond = rlp.decode(second); + decodedLeaf = rlp.decode(leaf); + + nodes = rlp.encode([decodedRoot, decodedSecond, decodedLeaf]); + return nodes; +} \ No newline at end of file diff --git a/test/rinkeby.js b/test/rinkeby.js new file mode 100644 index 0000000..2b42ce5 --- /dev/null +++ b/test/rinkeby.js @@ -0,0 +1,128 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Web3Utils = require('web3-utils'); +const HDWalletProvider = require('truffle-hdwallet-provider'); +const mnemonic = "select they inform invite result believe equal daughter front arrest wagon miss same menu twenty"; +const addr = "0x279884e133f9346f2fad9cc158222068221b613e"; + +const rlp = require('rlp'); +const Web3 = require('web3'); +const EP = require('eth-proof'); +const deployedTrig = "0x61621bcf02914668f8404c1f860e92fc1893f74c"; +const trigAbi = [{"anonymous":false,"inputs":[{"indexed":false,"name":"caller","type":"address"}],"name":"Triggered","type":"event"},{"constant":false,"inputs":[],"name":"fire","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]; + +const TRIG_FIRED_RINKEBY_TXHASH = "0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e" +const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 + +function fireTrigger() { + web3 = new Web3(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); + trig = new web3.eth.Contract(trigAbi, deployedTrig); + + trig.methods.fire().send({from: addr}).on('transactionHash', function(hash) { console.log(hash) }); +} + +async function getTxProof() { + var eP = new EP(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); + + await eP.getTransactionTrieRoot(TRIG_FIRED_RINKEBY_TXHASH).then( (root) => { + console.log("EP TX Root hash = 0x" + root.toString('hex')) + }) + + var txValue; + var txPath; + var txParentNodes; + await eP.getTransactionProof(TRIG_FIRED_RINKEBY_TXHASH).then( (proof) => { + verified = EP.transaction(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); + + txValue = rlp.encode(proof.value); + txPath = proof.path; + txParentNodes = rlp.encode(proof.parentNodes); + }) + console.log("EP TX VALUE = 0x" + txValue.toString('hex')); + console.log("EP TX PATH = 0x" + txPath.toString('hex')); + console.log("EP TX PARENT NODES = 0x" + txParentNodes.toString('hex')); + +} + +async function getReceiptProof() { + var eP = new EP(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); + web3 = new Web3(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); +// receipt = await web3.eth.getTransactionReceipt(TRIG_FIRED_RINKEBY_TXHASH); +// console.log(receipt); + + await eP.getReceiptTrieRoot(TRIG_FIRED_RINKEBY_TXHASH).then( (root) => { + console.log("EP RECEIPT Root hash = 0x" + root.toString('hex')) + }) + + var txValue; + var txPath; + var txParentNodes; + await eP.getReceiptProof(TRIG_FIRED_RINKEBY_TXHASH).then( (proof) => { + verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); + console.log("VERIFIED: " + verified) + + txValue = rlp.encode(proof.value); + txPath = proof.path; + txParentNodes = rlp.encode(proof.parentNodes); + }) + console.log("EP RECEIPT VALUE = 0x" + txValue.toString('hex')); + console.log("EP RECEIPT PATH = 0x" + txPath.toString('hex')); + console.log("EP RECEIPT PARENT NODES = 0x" + txParentNodes.toString('hex')); + +} + +function rlpEncodeReceipt(receipt) { + let fields = [receipt.] +} + + +receipt = { blockHash: '0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7', + + blockNumber: 2657422, + + contractAddress: null, + + cumulativeGasUsed: 2435175, + + from: '0x279884e133f9346f2fad9cc158222068221b613e', + + gasUsed: 22467, + + logs: + + [ { address: '0x61621BCf02914668F8404C1f860E92fC1893F74c', + + topics: [Array], + + data: '0x000000000000000000000000279884e133f9346f2fad9cc158222068221b613e', + + blockNumber: 2657422, + + transactionHash: '0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e', + + transactionIndex: 19, + + blockHash: '0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7', + + logIndex: 25, + + removed: false, + + id: 'log_ad29b82c' } ], + + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000', + + status: true, + + to: '0x61621bcf02914668f8404c1f860e92fc1893f74c', + + transactionHash: '0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e', + + transactionIndex: 19 } + +console.log(rlpEncodeReceipt(receipt)); +//getTxProof(); +//getReceiptProof(); + +//console.log(rlp.decode("0xf902780182ab33b9010000000000020000080000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000008000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000010000000020020000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000020000010010000000000000000002000000000000000000000000000000000000000000000000000000000000000000000400000000000000000022000000000000000000000000000000f9016ef89b949edcb9a9c4d34b5d6a082c86cb4f117a1394f831f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000001b31d19b6a9a942bbf3c197ca1e5efede3ff8ff2a0000000000000000000000000e05a6d421f1375864bc6e28567993e815eefec23a00000000000000000000000000000000000000000000000004563918244f40000f8cf941b31d19b6a9a942bbf3c197ca1e5efede3ff8ff2e1a0970a6f99f3b845055cfa2283651f03abd1202ee9ececa9ca4f034161dd02457bb896000000000000000000000000e05a6d421f1375864bc6e28567993e815eefec230000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001652657761726420666f72206461696c79206c6f67696e")); diff --git a/test/trie.js b/test/trie.js new file mode 100644 index 0000000..0932291 --- /dev/null +++ b/test/trie.js @@ -0,0 +1,77 @@ +var Trie = require('merkle-patricia-tree') +levelup = require('levelup') +const rlp = require('rlp'); +const HDWalletProvider = require('truffle-hdwallet-provider'); +const mnemonic = "select they inform invite result believe equal daughter front arrest wagon miss same menu twenty"; + +const Web3 = require('web3'); +const EP = require('eth-proof'); +web3 = new Web3(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); + +function processLogs(logs) { + var rlpLogs = []; + for (var i = 0; i < logs.length; i++) { + var address = Buffer.from(logs[i].address.slice(2), 'hex') + var topics = logs[i].topics.map(topic => Buffer.from(topic.slice(2), 'hex')) + var data = Buffer.from(logs[i].data.slice(2), 'hex') + rlpLogs.push([address, topics, data]); + } + return rlpLogs; +} + +async function getReceipt(txHash) { + receipt = await web3.eth.getTransactionReceipt(txHash); + + var cummulativeGas = Buffer.from(receipt.cumulativeGasUsed.toString('16'), 'hex') + var bloomFilter = Buffer.from(receipt.logsBloom.slice(2), 'hex') + var setOfLogs = processLogs(receipt.logs); + + if (receipt.status !== undefined && receipt.status != null){ + var status = receipt.status ? Buffer.from('01', 'hex') : Buffer.from('00', 'hex'); + var rawReceipt = rlp.encode([status,cummulativeGas,bloomFilter,setOfLogs]); + return rawReceipt; + } else { + var postTransactionState = strToBuf(receipt.root) + var rawReceipt = rlp.encode([postTransactionState, cummulativeGas,bloomFilter,setOfLogs]) + return rawReceipt; + } +} + +async function addReceiptToTrie(trie, txHash, prevTrieRoot) { + console.log("Inserting receipt for hash: " + txHash); + receipt = await getReceipt(txHash); + console.log("RECEIPT RLP:" + receipt.toString('hex')) + + tx = await web3.eth.getTransaction(txHash); + path = rlp.encode(tx.transactionIndex); + console.log("Key: " + path.toString('hex')); + + console.log(trie.root) + console.log(prevTrieRoot) + do { + await trie.put(path, receipt, (error) => {console.log("ERROR:" + error)}); + } while (trie.root == prevTrieRoot) +} + +async function generateReceiptProof(block) { + block = await web3.eth.getBlock(block); + + txs = block.transactions; + + var trie = new Trie(); + var lastTrieRoot = "" + for (let i = 0; i < 2; i++) { + await addReceiptToTrie(trie, txs[i], lastTrieRoot); + lastTrieRoot = trie.root; + } +} + +//generateReceiptProof("0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7"); + +let root = Buffer.from("f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080", 'hex') +let second = Buffer.from("f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e", 'hex') +let leaf = Buffer.from("f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080", 'hex') + +nodes = rlp.encode([root, second, leaf]); + +console.log(nodes.toString('hex')) \ No newline at end of file From 4002f3eabc043c989277766a7b2936dcca8f34bf Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Tue, 24 Jul 2018 18:55:14 +0100 Subject: [PATCH 075/203] Functional skeleton is working and testable. Currently verifying proofs against the Trigger.sol contract deployed to Rinkeby and consuming an event emitted by the contract --- contracts/EventConsumable.sol | 9 ---- contracts/EventVerifier.sol | 70 ++++++++++++++++++++++--- contracts/Function.sol | 88 ++++++++++++++++++++++++++++++-- migrations/2_deploy_contracts.js | 8 ++- test/ion.js | 55 ++++++++++++++++++++ 5 files changed, 207 insertions(+), 23 deletions(-) delete mode 100644 contracts/EventConsumable.sol diff --git a/contracts/EventConsumable.sol b/contracts/EventConsumable.sol deleted file mode 100644 index 0ab6de3..0000000 --- a/contracts/EventConsumable.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma solidity ^0.4.0; - -contract EventConsumable { - event IonCompatibleEvent( - bytes32 originChain, - bytes32[] destinationChain, - address emittedFromContract, - uint256 nonce); -} diff --git a/contracts/EventVerifier.sol b/contracts/EventVerifier.sol index ba884c4..f61242c 100644 --- a/contracts/EventVerifier.sol +++ b/contracts/EventVerifier.sol @@ -3,22 +3,76 @@ pragma solidity ^0.4.23; import "./RLP.sol"; contract EventVerifier { + function verify(bytes20 _contractEmittedAddress, bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool) { - function verify(bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool) { + /* Here we decode the receipt into it's consituents and grab the logs as we know it's position in the receipt + object and proceed to decode the logs also. + */ RLP.RLPItem[] memory receipt = RLP.toList(RLP.toRLPItem(_rlpReceipt)); - RLP.RLPItem[] memory logs = RLP.toList(receipt[3]); - require( logs.length == 1 ); - bytes memory b_address = RLP.toBytes(logs[0]); - bytes20 b20_address; - assembly { - b20_address := mload(add(b_address, 0)) + /* + In this example there should be only one set of logs but in other cases there may be multiple sets of logs, + one set per event emitted per transaction. It will be the writer of the event verifier to locate the correct + log in the receipts through iteration. + */ + assert( logs.length == 1 ); + + + // The log decoded into a list: log = [ contractAddress (bytes32), topics (array), data (bytes) ] + RLP.RLPItem[] memory log = RLP.toList(logs[0]); + + + /* + In the case where there are multiple logs, the below code should iterate through them to find the correct one: + + bytes32 expectedEventSignature = 0xsomespecifichash + RLP.RLPItem[] memory log; + for (uint i = 0; i < logs.length; i++) { + log = RLP.toList(logs[i]); + RLP.RLPItem[] memory topics = RLP.toList(log[1]); + bytes32 eventSignature = RLP.toBytes32(topics[0]); + if (eventSignature == expectedEventSignature) { + break; + } } - require( b20_address == _expectedAddress ); + And then separated into it's constituents for processing below: + */ + bytes memory contractEmittedEvent = RLP.toData(log[0]); + RLP.RLPItem[] memory topics = RLP.toList(log[1]); + bytes memory data = RLP.toData(log[2]); + + bytes20 emissionSource = bytesToBytes20(contractEmittedEvent, 0); + assert( emissionSource == _contractEmittedAddress); + /* + This section below is specific to this event and checks the relevant data. + In this event we only expect a single un-indexed address parameter which will be present in the data field. + The data field pads it's contents if they are less than 32 bytes. Therefore we know that our address parameter + exists in the 20 least significant bytes of the data field. + + We copy the last 20 bytes of our data field to a bytes20 variable to compare against the supplied expected + parameter in the event from our function call. This acts as our conditional check that the event called is what + the user expects. + */ + bytes20 b20_address = bytesToBytes20(data, data.length - 20); + assert( b20_address == _expectedAddress ); + + /* + Once verified, the logs of this specific event are proven as true and returns as such. Else, the execution + reverts. + */ return true; } + + function bytesToBytes20(bytes _b, uint _offset) private pure returns (bytes20) { + bytes20 out; + + for (uint i = 0; i < 20; i++) { + out |= bytes20(_b[_offset + i] & 0xFF) >> (i * 8); + } + return out; + } } diff --git a/contracts/Function.sol b/contracts/Function.sol index c69ddbb..f592734 100644 --- a/contracts/Function.sol +++ b/contracts/Function.sol @@ -1,17 +1,95 @@ pragma solidity ^0.4.23; -import "./EventConsuming.sol"; +import "./EventVerifier.sol"; +import "./Ion.sol"; -contract Function is EventConsuming { - constructor(address _ionCompAddress) EventConsuming(_ionCompAddress) {} +/* + This function contract is the consumer of an event and performs some execution thereafter. In practice, this would + be written by a contract designer that intends to consume specific events from another chain. As such all behaviour + and dependence on such event must be defined here. + Common custom behaviour may include: + * Keeping an array of transaction hashes denoting the specific events from that transaction that + have already been consumed to restrict multiple consumption or 'double spend' of events. + * Extending the amount of expected event parameters above the stack limit. This might then require some other method + of passing expected parameters to the contract possibly via RLP-encoding to compress all data to a single argument + and decoding them within the `verifyAndExecute` function. + * Including multiple event verifiers if a function requires proof of multiple state transitions from other chains. + This would also bloat the local scope which is prone to 'stack too deep' issues which would require custom + workarounds. +*/ +contract Function { + /* The Ion contract that proofs would be made to. Ensure that prior to verification attempts that the relevant + blocks have been submitted to the Ion contract. */ + Ion ion; + + /* The event verifier for the specific event being consumed. Each event would require a different event verifier to + be deployed and each consumer would reference the relevant verifier to prove logs. */ + EventVerifier verifier; + + /* Custom event that fires when execution is performed successfully. */ event Executed(); - function execute() IonCompatibleOnly { + /* Constructor. Requires Ion contract address and all used event verifier contract addresses. In this case we only + use one verifier. */ + constructor(address _ionAddr, address _verifierAddr) public { + ion = Ion(_ionAddr); + verifier = EventVerifier(_verifierAddr); + } + + /* This is the function that is intended to be executed upon successful verification of proofs */ + function execute() internal { emit Executed(); } - function CheckReceipt() IonCompatibleOnly { + /* + verifyAndExecute + + Core parameters for verification + param: _chainId (bytes32) Chain ID of the chain that the event being consumed was emitted on. This may require + altering to (bytes) if proofs from multiple chains are needed. + param: _blockHash (bytes32) Block hash of block with event to be consumed. This may require altering to (bytes) + if proofs from multiple chains are needed. + param: _contractEmittedAddress (bytes20) Contract address of the source of event emission. This may require + altering to (bytes) if proofs from multiple chains are needed. + param: _path (bytes) RLP-encoded transaction index of the relevant transaction that emitted the event being + consumed. If multiple proofs are required, multiple paths supplied must be RLP-encoded + and an extra (bool) parameter provided to denote multiple paths included. + param: _tx (bytes) RLP-encoded transaction object provided by proof generation. + param: _txNodes (bytes) RLP_encoded transaction nodes provided by proof generation. + param: _receipt (bytes) RLP-encoded receipt object provided by proof generation. + param: _receiptNodes (bytes) RLP-encoded receipt nodes provided by proof generation. + + Custom parameters for verification + param: _expectedAddress (bytes20) The expected address value in the event parameter being consumed. + + This is the only public function apart from the constructor and is the only interface to this contract. This + function wraps the verification and execution which only fires after a successful slew of verifications. As + noted, stack restrictions will make it harder to implement multiple event consumption. Suggestions made here may + not be the best way to achieve this but are possible methods. It may end up requiring separate functions for + each event and persisting the consumption state of each event per tx hash and using that to allow or prevent + verified execution. In our case, it is simple as we only consume a single event. + */ + function verifyAndExecute( + bytes32 _chainId, + bytes32 _blockHash, + bytes20 _contractEmittedAddress, + bytes _path, + bytes _tx, + bytes _txNodes, + bytes _receipt, + bytes _receiptNodes, + bytes20 _expectedAddress + ) public returns (bool) { + assert( ion.CheckRootsProof(_chainId, _blockHash, _txNodes, _receiptNodes) ); + assert( ion.CheckTxProof(_chainId, _blockHash, _tx, _txNodes, _path) ); + assert( ion.CheckReceiptProof(_chainId, _blockHash, _receipt, _receiptNodes, _path) ); + if (verifier.verify(_contractEmittedAddress, _receipt, _expectedAddress)) { + execute(); + return true; + } else { + return false; + } } } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 509f05e..27da0d2 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,11 +1,17 @@ const Ion = artifacts.require("Ion"); const PatriciaTrie = artifacts.require("PatriciaTrie"); +const Function = artifacts.require("Function"); +const EventVerifier = artifacts.require("EventVerifier"); module.exports = async (deployer) => { try { await deployer.deploy(PatriciaTrie); await deployer.link(PatriciaTrie, Ion); - deployer.deploy(Ion, "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") + await deployer.deploy(Ion, "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075"); + eventVerifier = await deployer.deploy(EventVerifier); + ion = await Ion.deployed(); + eventVerifier = await EventVerifier.deployed(); + deployer.deploy(Function, ion.address, eventVerifier.address); } catch(err) { console.log('ERROR on deploy:',err); diff --git a/test/ion.js b/test/ion.js index 97cee01..cd37a6d 100644 --- a/test/ion.js +++ b/test/ion.js @@ -14,6 +14,7 @@ const Web3 = require('web3'); const Ion = artifacts.require("Ion"); const PatriciaTrie = artifacts.require("PatriciaTrie"); +const EventVerifier = artifacts.require("EventVerifier"); const Function = artifacts.require("Function"); require('chai') @@ -122,8 +123,10 @@ const TEST_TX_NODES = "0xf90235f871a0804f9c841a6a1d3361d79980581c84e5b4d3e4c9bf3 const TEST_RECEIPT_VALUE = "0xf901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" const TEST_RECEIPT_NODES = "0xf90335f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" +const TRIG_DEPLOYED_RINKEBY_ADDR = "0x61621bcf02914668f8404c1f860e92fc1893f74c"; const TRIG_FIRED_RINKEBY_TXHASH = "0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e" const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 +const TRIG_CALLED_BY = "0x279884e133f9346f2fad9cc158222068221b613e"; contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { @@ -280,6 +283,58 @@ contract('Ion.js', (accounts) => { // Fail with wrong receipt nodes await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; }) + + it('Deploy Function Contract', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + const verifier = await EventVerifier.new(); + const functionContract = await Function.new(ion.address, verifier.address); + }) + + it('Verify Function Execution', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + const verifier = await EventVerifier.new(); + const functionContract = await Function.new(ion.address, verifier.address); + + // Register chain and submit block to Ion + await ion.RegisterChain(TESTCHAINID); + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); + + console.log("Gas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Function Execution', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + const verifier = await EventVerifier.new(); + const functionContract = await Function.new(ion.address, verifier.address); + + // Register chain and submit block to Ion + await ion.RegisterChain(TESTCHAINID); + await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await functionContract.verifyAndExecute(DEPLOYEDCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong block hash + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong deployed contract address + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_CALLED_BY, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong path + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, "0xff", TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong tx nodes + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong receipt nodes + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0", TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong expected value + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_DEPLOYED_RINKEBY_ADDR).should.be.rejected; + }) + }) async function verifyReceipts(eP, txHash) { From 1112dad69ea32e0e7ba42fd17201ecd1500a40c6 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 25 Jul 2018 11:47:41 +0100 Subject: [PATCH 076/203] Added ability to link libraries to the golang smart contract testing --- .travis.yml | 2 + abi/ECVerify.bin | 2 +- abi/Ion.bin | 2 +- abi/Migrations.abi | 1 + abi/Migrations.bin | 1 + abi/PatriciaTrie.bin | 2 +- abi/RLP.bin | 2 +- abi/Recover.abi | 1 + abi/Recover.bin | 1 + abi/SolUtils.bin | 2 +- abi/Validation.abi | 2 +- abi/Validation.bin | 2 +- ion-cli/cli/cli.go | 23 +++ ion-cli/contracts/ion.go | 30 ++++ ion-cli/contracts/ion_test.go | 263 +++++++++++++++++++++++----------- ion-cli/contracts/patricia.go | 200 ++++++++++++++++++++++++++ ion-cli/utils/helpers.go | 51 +++++++ ion-cli/utils/helpers_test.go | 40 ++++++ ion-cli/utils/rlp_test.go | 8 +- package.json | 4 +- test/validation.js | 2 +- 21 files changed, 540 insertions(+), 101 deletions(-) create mode 100644 abi/Migrations.abi create mode 100644 abi/Migrations.bin create mode 100644 abi/Recover.abi create mode 100644 abi/Recover.bin create mode 100644 ion-cli/contracts/patricia.go create mode 100644 ion-cli/utils/helpers.go create mode 100644 ion-cli/utils/helpers_test.go diff --git a/.travis.yml b/.travis.yml index d1906cc..aef3362 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,10 +15,12 @@ matrix: go: 1.9.x script: - npm install + - npm depclique - npm run test - cd ./ion-cli - go get -t ./... - make test + - make integration-test notifications: slack: diff --git a/abi/ECVerify.bin b/abi/ECVerify.bin index 65f0298..00a99b8 100644 --- a/abi/ECVerify.bin +++ b/abi/ECVerify.bin @@ -1 +1 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a723058209b042e675a498ff3065c231b18babe7c1eda6630c62a5b46cf1b1e2d2f16a9590029 \ No newline at end of file +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a723058203848e9525cfafe47477ce5b2a3e1938d84ef6fbf2c7bed546cf353193efee3f70029 \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin index ce7bd09..eb52a59 100644 --- a/abi/Ion.bin +++ b/abi/Ion.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051602080611487833981018060405281019080805190602001909291905050508060008160001916905550506114398061004e6000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063550325b5146100a957806359349832146100f25780635a0235e4146101095780636b4f9b9d1461018e578063927a32e3146101fb5780639a8a0592146102665780639e43d86b14610299578063affd8be9146102ca578063e318df54146103f3578063fecc37c31461040a575b600080fd5b3480156100b557600080fd5b506100d460048036038101908080359060200190929190505050610461565b60405180826000191660001916815260200191505060405180910390f35b3480156100fe57600080fd5b50610107610484565b005b34801561011557600080fd5b5061018c60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610486565b005b34801561019a57600080fd5b506101bd60048036038101908080356000191690602001909291905050506106be565b6040518082600360200280838360005b838110156101e85780820151818401526020810190506101cd565b5050505090500191505060405180910390f35b34801561020757600080fd5b5061022a600480360381019080803560001916906020019092919050505061072d565b60405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b34801561027257600080fd5b5061027b610757565b60405180826000191660001916815260200191505060405180910390f35b3480156102a557600080fd5b506102c8600480360381019080803560001916906020019092919050505061075d565b005b3480156102d657600080fd5b506103d960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108f4565b604051808215151515815260200191505060405180910390f35b3480156103ff57600080fd5b50610408610d83565b005b34801561041657600080fd5b50610443600480360381019080803560001916906020019092919080359060200190929190505050610d85565b60405180826000191660001916815260200191505060405180910390f35b60018181548110151561047057fe5b906000526020600020016000915090505481565b565b60606000808560008060009150600090505b6001805490508110156104e4576001818154811015156104b457fe5b906000526020600020015460001916836000191614156104d757600191506104e4565b8080600101915050610498565b811515610559576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61056a61056588610db5565b610e10565b9550866040518082805190602001908083835b6020831015156105a2578051825260208201915060208101905060208303925061057d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209450876000191685600019161415156105e757600080fd5b600360008960001916600019168152602001908152602001600020935061062f61062887600081518110151561061957fe5b90602001906020020151610ecd565b6001610f32565b84600001816000191690555061066661065f87600481518110151561065057fe5b90602001906020020151610ecd565b6001610f32565b84600101816000191690555061069d61069687600581518110151561068757fe5b90602001906020020151610ecd565b6001610f32565b8460020181600019169055506106b38989611010565b505050505050505050565b6106c6611395565b6000600360008460001916600019168152602001908152602001600020905060606040519081016040528082600001546000191660001916815260200182600101546000191660001916815260200182600201546000191660001916815250915050919050565b60036020528060005260406000206000915090508060000154908060010154908060020154905083565b60005481565b6000805460001916826000191614151515610806576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600090505b6001805490508110156108be57816000191660018281548110151561082c57fe5b906000526020600020015460001916141515156108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b808060010191505061080b565b60018290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055505050565b6000808660008060009150600090505b6001805490508110156109505760018181548110151561092057fe5b906000526020600020015460001916836000191614156109435760019150610950565b8080600101915050610904565b8115156109c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8989600060606000809250600260008660001916600019168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610a3957602002820191906000526020600020905b81546000191681526020019060010190808311610a21575b50505050509150600090505b8151811015610a8b578181815181101515610a5c57fe5b906020019060200201516000191684600019161415610a7e5760019250610a8b565b8080600101915050610a45565b821515610b00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600360008f60001916600019168152602001908152602001600020985073__./contracts/libraries/PatriciaTrie.s__634f7142ad8e8e8e8d600101546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610bc0578082015181840152602081019050610ba5565b50505050905090810190601f168015610bed5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610c26578082015181840152602081019050610c0b565b50505050905090810190601f168015610c535780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610c8c578082015181840152602081019050610c71565b50505050905090810190601f168015610cb95780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610cdb57600080fd5b505af4158015610cef573d6000803e3d6000fd5b505050506040513d6020811015610d0557600080fd5b81019080805190602001909291905050501515610d1e57fe5b7f202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a18f8f60405180836000191660001916815260200182600019166000191681526020019250505060405180910390a16001995050505050505050505095945050505050565b565b600260205281600052604060002081815481101515610da057fe5b90600052602060002001600091509150505481565b610dbd6113b8565b600080835191506000821415610deb5760408051908101604052806000815260200160008152509250610e09565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e1c6113d2565b6000610e27856110b4565b1515610e3257600080fd5b610e3b856110e6565b925082604051908082528060200260200182016040528015610e7757816020015b610e646113f3565b815260200190600190039081610e5c5790505b509350610e8385611160565b91505b610e8f826111a8565b15610ec557610e9d826111d2565b8482815181101515610eab57fe5b906020019060200201819052508080600101915050610e86565b505050919050565b60606000826020015190506000811415610ee657610f2c565b806040519080825280601f01601f191660200182016040528015610f195781602001602082028038833980820191505090505b509150610f2b8360000151838361122e565b5b50919050565b60008060008090505b6020811015611005576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610f7c57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610f3b565b819250505092915050565b6000806002600085600019166000191681526020019081526020016000209150600090505b818054905081101561107d578260001916828281548110151561105457fe5b9060005260206000200154600019161415151561107057600080fd5b8080600101915050611035565b8183908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555050505050565b6000806000836020015114156110cd57600091506110e0565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806110f8876110b4565b15156111075760009550611156565b86600001519350835160001a945061111e8761126f565b840192506001876020015185010391505b818311151561115257611141836112fb565b83019250808060010191505061112f565b8095505b5050505050919050565b6111686113d2565b6000611173836110b4565b151561117e57600080fd5b6111878361126f565b83600001510190508282600001819052508082602001818152505050919050565b60006111b26113b8565b826000015190508060200151816000015101836020015110915050919050565b6111da6113b8565b6000806111e6846111a8565b1561122257836020015191506111fb826112fb565b90508183600001818152505080836020018181525050808201846020018181525050611227565b600080fd5b5050919050565b60006020601f83010484602085015b82841461125c576020840280830151818301526001850194505061123d565b6000865160200187015250505050505050565b6000806000808460200151141561128957600092506112f4565b83600001519050805160001a915060808210156112a957600092506112f4565b60b88210806112c5575060c082101580156112c4575060f882105b5b156112d357600192506112f4565b60c08210156112ea57600160b783030192506112f4565b600160f783030192505b5050919050565b600080825160001a90506080811015611317576001915061138f565b60b881101561132e5760016080820301915061138e565b60c08110156113585760b78103806020036101000a6001850151048082016001019350505061138d565b60f881101561136f57600160c0820301915061138c565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b606060405190810160405280600390602082028038833980820191505090505090565b604080519081016040528060008152602001600081525090565b6060604051908101604052806113e66113f3565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582092fe2217ce4fc7e2c1df216da8d39cd9ccf25c15d607088915e2dede2778065d0029 \ No newline at end of file +608060405234801561001057600080fd5b5060405160208061101a8339810160405251600055610fe6806100346000396000f3006080604052600436106100a35763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663550325b581146100a857806359349832146100d25780635a0235e4146100e95780636b4f9b9d14610149578063927a32e3146101995780639a8a0592146101cf5780639e43d86b146101e4578063affd8be9146101fc578063e318df54146100d2578063fecc37c3146102ec575b600080fd5b3480156100b457600080fd5b506100c0600435610307565b60408051918252519081900360200190f35b3480156100de57600080fd5b506100e7610326565b005b3480156100f557600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526100e79482359460248035953695946064949201919081908401838280828437509497506103289650505050505050565b34801561015557600080fd5b506101616004356104bf565b6040518082606080838360005b8381101561018657818101518382015260200161016e565b5050505090500191505060405180910390f35b3480156101a557600080fd5b506101b1600435610506565b60408051938452602084019290925282820152519081900360600190f35b3480156101db57600080fd5b506100c0610527565b3480156101f057600080fd5b506100e760043561052d565b34801561020857600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102d894823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061066c9650505050505050565b604080519115158252519081900360200190f35b3480156102f857600080fd5b506100c0600435602435610a68565b600180548290811061031557fe5b600091825260209091200154905081565b565b60606000808581805b60015481101561036d57600180548290811061034957fe5b600091825260209091200154831415610365576001915061036d565b600101610331565b8115156103c4576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b6103d56103d088610a98565b610aeb565b9550866040518082805190602001908083835b602083106104075780518252601f1990920191602091820191016103e8565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060008e815260039092529281208b51939a509850610470945061046993508a92909150811061045a57fe5b90602001906020020151610ba0565b6001610bf4565b8455855161048990610469908890600490811061045a57fe5b600185015585516104a590610469908890600590811061045a57fe5b60028501556104b48989610c82565b505050505050505050565b6104c7610f63565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b600080548214156105ae576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106375760018054839190839081106105cd57fe5b600091825260209091200154141561062f576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b6001016105b2565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b6001548110156106af57600180548290811061068b57fe5b6000918252602090912001548314156106a757600191506106af565b600101610673565b811515610706576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a815260026020908152604080832080548251818502810185019093528083528e948e9490936060938593919290919083018282801561076857602002820191906000526020600020905b81548152600190910190602001808311610753575b50505050509150600090505b81518110156107ad57818181518110151561078b57fe5b602090810290910101518414156107a557600192506107ad565b600101610774565b821515610804576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f60001916600019168152602001908152602001600020985073__./contracts/libraries/PatriciaTrie.s__634f7142ad8e8e8e8d600101546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108c15781810151838201526020016108a9565b50505050905090810190601f1680156108ee5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610921578181015183820152602001610909565b50505050905090810190601f16801561094e5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610981578181015183820152602001610969565b50505050905090810190601f1680156109ae5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d60208110156109fa57600080fd5b50511515610a0457fe5b7f202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a18f8f60405180836000191660001916815260200182600019166000191681526020019250505060405180910390a15060019e9d5050505050505050505050505050565b600260205281600052604060002081815481101515610a8357fe5b90600052602060002001600091509150505481565b610aa0610f82565b81516000811515610ac65760408051808201909152600080825260208201529250610ae4565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610af7610f99565b6000610b0285610ce2565b1515610b0d57600080fd5b610b1685610d0c565b925082604051908082528060200260200182016040528015610b5257816020015b610b3f610f82565b815260200190600190039081610b375790505b509350610b5e85610d7c565b91505b610b6a82610db5565b15610b9857610b7882610dd4565b8482815181101515610b8657fe5b60209081029091010152600101610b61565b505050919050565b6020810151606090801515610bb457610500565b806040519080825280601f01601f191660200182016040528015610be2578160200160208202803883390190505b50915061050083600001518383610e16565b600080805b6020811015610c7a578060080285828601815181101515610c1657fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610bf9565b509392505050565b6000828152600260205260408120905b8154811015610cca5781548390839083908110610cab57fe5b6000918252602090912001541415610cc257600080fd5b600101610c92565b50805460018101825560009182526020909120015550565b600080826020015160001415610cfb5760009150610500565b5050515160c060009190911a101590565b600080600080600080610d1e87610ce2565b1515610d2d5760009550610d72565b8651805160001a95509350610d4187610e56565b840192506001876020015185010391505b818311610d6e57610d6283610ed6565b90920191600101610d52565b8095505b5050505050919050565b610d84610f99565b6000610d8f83610ce2565b1515610d9a57600080fd5b610da383610e56565b83519383529092016020820152919050565b6000610dbf610f82565b50508051602080820151915192015191011190565b610ddc610f82565b600080610de884610db5565b156100a35783602001519150610dfd82610ed6565b8284526020808501829052838201908601529050610ae4565b60006020601f83010484602085015b828414610e4357602084028281015190820152600190930192610e25565b6000865160200187015250505050505050565b6000806000836020015160001415610e715760009250610ae4565b50508151805160001a906080821015610e8d5760009250610ae4565b60b8821080610ea8575060c08210158015610ea8575060f882105b15610eb65760019250610ae4565b60c0821015610ecb5760b51982019250610ae4565b5060f5190192915050565b8051600090811a6080811015610eef5760019150610500565b60b8811015610f0457607e1981019150610500565b60c0811015610f2d57600183015160b76020839003016101000a9004810160b519019150610500565b60f8811015610f425760be1981019150610500565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280610fad610f82565b81526020016000815250905600a165627a7a723058206a4b9844b305800bce8a0a88fdcd6658383e8dd98c6de20e69edd6739e2e64e20029 \ No newline at end of file diff --git a/abi/Migrations.abi b/abi/Migrations.abi new file mode 100644 index 0000000..79cea67 --- /dev/null +++ b/abi/Migrations.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"new_address","type":"address"}],"name":"upgrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"last_completed_migration","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"completed","type":"uint256"}],"name":"setCompleted","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] \ No newline at end of file diff --git a/abi/Migrations.bin b/abi/Migrations.bin new file mode 100644 index 0000000..fa2aea7 --- /dev/null +++ b/abi/Migrations.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f8806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100aa5780638da5cb5b146100d5578063fdacd5761461012c575b600080fd5b34801561007357600080fd5b506100a8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610159565b005b3480156100b657600080fd5b506100bf610241565b6040518082815260200191505060405180910390f35b3480156100e157600080fd5b506100ea610247565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561013857600080fd5b506101576004803603810190808035906020019092919050505061026c565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023d578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561022457600080fd5b505af1158015610238573d6000803e3d6000fd5b505050505b5050565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102c957806001819055505b505600a165627a7a723058200a67aaa415eddfae294772076b091bbc158e31aab6b566bdf4b502ef8707113e0029 \ No newline at end of file diff --git a/abi/PatriciaTrie.bin b/abi/PatriciaTrie.bin index 6e3af0a..5735ee3 100644 --- a/abi/PatriciaTrie.bin +++ b/abi/PatriciaTrie.bin @@ -1 +1 @@ -611278610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634f7142ad1461005d575b600080fd5b610151600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803560001916906020019092919050505061016b565b604051808215151515815260200191505060405180910390f35b60006101756111d5565b606060006060806000606060008060608061018f8f61060f565b9a5061019a8b61066a565b99508c9850600095506101ae8e6000610727565b9450600093505b89518410156105fb576101de8a858151811015156101cf57fe5b90602001906020020151610ad7565b9750876040518082805190602001908083835b60208310151561021657805182526020820191506020810190506020830392506101f1565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916896000191614151561025c5760009b506105fc565b61027c8a8581518110151561026d57fe5b9060200190602002015161066a565b9650601187511415610446578451861415610397578f6040518082805190602001908083835b6020831015156102c757805182526020820191506020810190506020830392506102a2565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661031988601081518110151561030a57fe5b90602001906020020151610ad7565b6040518082805190602001908083835b60208310151561034e5780518252602082019150602081019050602083039250610329565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141561038e5760019b506105fc565b60009b506105fc565b84868151811015156103a557fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250610439878461ffff1681518110151561042a57fe5b90602001906020020151610b3c565b98506001860195506105ee565b6002875114156105e45761047187600081518110151561046257fe5b90602001906020020151610b51565b915061047e826001610727565b51860195508451861415610592578f6040518082805190602001908083835b6020831015156104c2578051825260208201915060208101905060208303925061049d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661051488600181518110151561050557fe5b90602001906020020151610b51565b6040518082805190602001908083835b6020831015156105495780518252602082019150602081019050602083039250610524565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614156105895760019b506105fc565b60009b506105fc565b600061059f836001610727565b5114156105af5760009b506105fc565b6105d08760018151811015156105c157fe5b90602001906020020151610b51565b90506105dd816000610bc3565b98506105ed565b60009b506105fc565b5b83806001019450506101b5565b5b5050505050505050505050949350505050565b6106176111d5565b6000808351915060008214156106455760408051908101604052806000815260200160008152509250610663565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006106766111ef565b600061068185610ca1565b151561068c57600080fd5b61069585610cd3565b9250826040519080825280602002602001820160405280156106d157816020015b6106be611210565b8152602001906001900390816106b65790505b5093506106dd85610d4d565b91505b6106e982610d95565b1561071f576106f782610dbf565b848281518110151561070557fe5b9060200190602002018190525080806001019150506106e0565b505050919050565b60608060008061073561122a565b6060600060ff6040519080825280601f01601f19166020018201604052801561076d5781602001602082028038833980820191505090505b50955060009450600093505b88518410156109db576107e3898581518110151561079357fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002610e1b565b92508780156107f25750600084145b1561091a5760017f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561082a57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108b4575060037f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561088b57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b15610915578260016002811015156108c857fe5b6020020151868660ff168151811015156108de57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001850194505b6109ce565b82600060028110151561092957fe5b6020020151868660ff1681518110151561093f57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535082600160028110151561097e57fe5b6020020151866001870160ff1681518110151561099757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506002850194505b8380600101945050610779565b8460ff166040519080825280601f01601f191660200182016040528015610a115781602001602082028038833980820191505090505b509150600090505b8460ff16811015610ac8578581815181101515610a3257fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028282815181101515610a8b57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050610a19565b81965050505050505092915050565b60606000826020015190506000811415610af057610b36565b806040519080825280601f01601f191660200182016040528015610b235781602001602082028038833980820191505090505b509150610b3583600001518383610f01565b5b50919050565b6000610b4782610f42565b6001029050919050565b6060600080610b5f84610f99565b1515610b6a57600080fd5b610b7384610fca565b8092508193505050806040519080825280601f01601f191660200182016040528015610bae5781602001602082028038833980820191505090505b509250610bbc828483610f01565b5050919050565b60008060008090505b6020811015610c96576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610c0d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610bcc565b819250505092915050565b600080600083602001511415610cba5760009150610ccd565b8260000151905060c0815160001a101591505b50919050565b600080600080600080610ce587610ca1565b1515610cf45760009550610d43565b86600001519350835160001a9450610d0b8761104b565b840192506001876020015185010391505b8183111515610d3f57610d2e836110d7565b830192508080600101915050610d1c565b8095505b5050505050919050565b610d556111ef565b6000610d6083610ca1565b1515610d6b57600080fd5b610d748361104b565b83600001510190508282600001819052508082602001818152505050919050565b6000610d9f6111d5565b826000015190508060200151816000015101836020015110915050919050565b610dc76111d5565b600080610dd384610d95565b15610e0f5783602001519150610de8826110d7565b90508183600001818152505080836020018181525050808201846020018181525050610e14565b600080fd5b5050919050565b610e2361122a565b600080610e31846004611171565b9150600f7f010000000000000000000000000000000000000000000000000000000000000002841690506040805190810160405280837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525092505050919050565b60006020601f83010484602085015b828414610f2f5760208402808301518183015260018501945050610f10565b6000865160200187015250505050505050565b6000806000610f5084610f99565b1515610f5b57600080fd5b610f6484610fca565b80925081935050506020811180610f7b5750600081145b15610f8557600080fd5b806020036101000a82510492505050919050565b600080600083602001511415610fb25760009150610fc4565b8260000151905060c0815160001a1091505b50919050565b6000806000806000610fdb86610f99565b1515610fe657600080fd5b85600001519150815160001a925060808310156110095781945060019350611043565b60b88310156110275760018660200151039350600182019450611042565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b6000806000808460200151141561106557600092506110d0565b83600001519050805160001a9150608082101561108557600092506110d0565b60b88210806110a1575060c082101580156110a0575060f882105b5b156110af57600192506110d0565b60c08210156110c657600160b783030192506110d0565b600160f783030192505b5050919050565b600080825160001a905060808110156110f3576001915061116b565b60b881101561110a5760016080820301915061116a565b60c08110156111345760b78103806020036101000a60018501510480820160010193505050611169565b60f881101561114b57600160c08203019150611168565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008160020a60ff16837f0100000000000000000000000000000000000000000000000000000000000000900460ff168115156111aa57fe5b047f010000000000000000000000000000000000000000000000000000000000000002905092915050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611203611210565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a7230582052aab7d1b534145ff43213168b77a7d3fc197b4648313c3c59c0b3f6cdee0bc00029 \ No newline at end of file +610d76610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600436106100575763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634f7142ad811461005c575b600080fd5b6040805160206004803580820135601f810184900484028501840190955284845261012694369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750509335945061013a9350505050565b604080519115158252519081900360200190f35b6000610144610cf7565b606060006060806000606060008060608061015e8f6104aa565b9a506101698b6104fd565b99508c98506000955061017d8e60006105b2565b9450600093505b8951841015610497576101ad8a8581518110151561019e57fe5b906020019060200201516107c9565b9750876040518082805190602001908083835b602083106101df5780518252601f1990920191602091820191016101c0565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091208c14925061021c9150505760009b50610497565b61023c8a8581518110151561022d57fe5b906020019060200201516104fd565b965086516011141561039757845186141561033c578f6040518082805190602001908083835b602083106102815780518252601f199092019160209182019101610262565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166102c488601081518110151561019e57fe5b6040518082805190602001908083835b602083106102f35780518252601f1990920191602091820191016102d4565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614156103335760019b50610497565b60009b50610497565b848681518110151561034a57fe5b90602001015160f860020a900460f860020a0260f860020a9004925061038a878461ffff1681518110151561037b57fe5b90602001906020020151610823565b985060018601955061048c565b865160021415610333576103c28760008151811015156103b357fe5b90602001906020020151610834565b91506103cf8260016105b2565b51855196019586141561044f578f6040518082805190602001908083835b6020831061040c5780518252601f1990920191602091820191016103ed565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166102c48860018151811015156103b357fe5b61045a8260016105b2565b51151561046a5760009b50610497565b61047c8760018151811015156103b357fe5b9050610489816000610897565b98505b600190930192610184565b5050505050505050505050949350505050565b6104b2610cf7565b815160008115156104d857604080518082019091526000808252602082015292506104f6565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610509610d0e565b6000610514856108f1565b151561051f57600080fd5b6105288561091b565b92508260405190808252806020026020018201604052801561056457816020015b610551610cf7565b8152602001906001900390816105495790505b5093506105708561098b565b91505b61057c826109c4565b156105aa5761058a826109e3565b848281518110151561059857fe5b60209081029091010152600101610573565b505050919050565b6060806000806105c0610d2f565b6040805160ff80825261012082019092526060916000919060208201611fe08038833901905050955060009450600093505b885184101561072a57610624898581518110151561060c57fe5b90602001015160f860020a900460f860020a02610a25565b9250878015610631575083155b156106bc578251600160f860020a03191660f860020a148061067d57508251600160f860020a0319167f0300000000000000000000000000000000000000000000000000000000000000145b156106b75760208301518651879060ff881690811061069857fe5b906020010190600160f860020a031916908160001a9053506001850194505b61071f565b82518651879060ff88169081106106cf57fe5b906020010190600160f860020a031916908160001a90535060208301518651879060ff600189011690811061070057fe5b906020010190600160f860020a031916908160001a9053506002850194505b6001909301926105f2565b8460ff166040519080825280601f01601f19166020018201604052801561075b578160200160208202803883390190505b509150600090505b8460ff168110156107bd57858181518110151561077c57fe5b90602001015160f860020a900460f860020a02828281518110151561079d57fe5b906020010190600160f860020a031916908160001a905350600101610763565b50979650505050505050565b60208101516060908015156107dd5761081d565b806040519080825280601f01601f19166020018201604052801561080b578160200160208202803883390190505b50915061081d83600001518383610a86565b50919050565b600061082e82610ac6565b92915050565b606060008061084284610b18565b151561084d57600080fd5b61085684610b41565b60408051828152601f19601f84011681016020019091529193509150818015610889578160200160208202803883390190505b5092506104f6828483610a86565b600080805b60208110156108e95780600802858286018151811015156108b957fe5b60209101015160029190910a60f860020a91829004909102600160f860020a03191604919091179060010161089c565b509392505050565b60008082602001516000141561090a576000915061081d565b5050515160c060009190911a101590565b60008060008060008061092d876108f1565b151561093c5760009550610981565b8651805160001a9550935061095087610bbe565b840192506001876020015185010391505b81831161097d5761097183610c3e565b90920191600101610961565b8095505b5050505050919050565b610993610d0e565b600061099e836108f1565b15156109a957600080fd5b6109b283610bbe565b83519383529092016020820152919050565b60006109ce610cf7565b50508051602080820151915192015191011190565b6109eb610cf7565b6000806109f7846109c4565b156100575783602001519150610a0c82610c3e565b82845260208085018290528382019086015290506104f6565b610a2d610d2f565b600080610a3b846004610ccb565b60408051808201909152600160f860020a03199190911681527f0f00000000000000000000000000000000000000000000000000000000000000949094166020850152509192915050565b60006020601f83010484602085015b828414610ab357602084028281015190820152600190930192610a95565b6000865160200187015250505050505050565b6000806000610ad484610b18565b1515610adf57600080fd5b610ae884610b41565b90925090506020811180610afa575080155b15610b0457600080fd5b806020036101000a82510492505050919050565b600080826020015160001415610b31576000915061081d565b5050515160c060009190911a1090565b6000806000806000610b5286610b18565b1515610b5d57600080fd5b8551805160001a935091506080831015610b7d5781945060019350610bb6565b60b8831015610b9b5760018660200151039350816001019450610bb6565b60b78303905080600187602001510303935080820160010194505b505050915091565b6000806000836020015160001415610bd957600092506104f6565b50508151805160001a906080821015610bf557600092506104f6565b60b8821080610c10575060c08210158015610c10575060f882105b15610c1e57600192506104f6565b60c0821015610c335760b519820192506104f6565b5060f5190192915050565b8051600090811a6080811015610c57576001915061081d565b60b8811015610c6c57607e198101915061081d565b60c0811015610c9557600183015160b76020839003016101000a9004810160b51901915061081d565b60f8811015610caa5760be198101915061081d565b6001929092015160f76020849003016101000a900490910160f51901919050565b60008160020a60ff168360f860020a900460ff16811515610ce857fe5b0460f860020a02905092915050565b604080518082019091526000808252602082015290565b606060405190810160405280610d22610cf7565b8152602001600081525090565b604080518082018252906002908290803883395091929150505600a165627a7a72305820acd21e373b0647728c7c4b49443ccc199017257ba462c48699cc1d28528f8b700029 \ No newline at end of file diff --git a/abi/RLP.bin b/abi/RLP.bin index bdc910d..1bc8155 100644 --- a/abi/RLP.bin +++ b/abi/RLP.bin @@ -1 +1 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820ce6cdb517493eee375e351c5f859db8319a6325d15ad79211273ad6e375c0d6c0029 \ No newline at end of file +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820c3ab6c04b83b440abb681106d8efa4dc64fdbfaa7cd538c013391b28f976a1590029 \ No newline at end of file diff --git a/abi/Recover.abi b/abi/Recover.abi new file mode 100644 index 0000000..49fac10 --- /dev/null +++ b/abi/Recover.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ExtractHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"sig","type":"bytes"}],"name":"VerifyBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"data","type":"bytes32"},{"name":"sig","type":"bytes"}],"name":"VerifyHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"}],"name":"test","type":"event"}] \ No newline at end of file diff --git a/abi/Recover.bin b/abi/Recover.bin new file mode 100644 index 0000000..4a249fb --- /dev/null +++ b/abi/Recover.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b11806100606000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b0e7308f1461005c578063d09ca90414610151578063fdace1be14610200575b600080fd5b34801561006857600080fd5b5061014f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610277565b005b34801561015d57600080fd5b506101fe600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061055e565b005b34801561020c57600080fd5b506102756004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610840565b005b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156102bf578051825260208201915060208101905060208303925061029a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156103635781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f19166020018201604052801561039a5781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156103d15781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156104085781602001602082028038833980820191505090505b509350610419878d60008a516108b6565b600260218801600260208e016004610bb8fa5061043c868d608c8c0389516108b6565b600160208701600160208d016004610bb8fa5061045f848d602a8c0387516108b6565b61046a878786610971565b9250826040518082805190602001908083835b6020831015156104a2578051825260208201915060208101905060208303925061047d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506104e1858d606b8c0388516108b6565b6104eb8286610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b600080606080856040518082805190602001908083835b60208310151561059a5780518252602082019150602081019050602083039250610575565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093506105d38486610a1d565b925060206040519080825280601f01601f1916602001820160405280156106095781602001602082028038833980820191505090505b50915060206040519080825280601f01601f1916602001820160405280156106405781602001602082028038833980820191505090505b5090506106518287600460206108b6565b61065f8187605b60206108b6565b7f8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c786838360405180806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106cb5780820151818401526020810190506106b0565b50505050905090810190601f1680156106f85780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b83811015610731578082015181840152602081019050610716565b50505050905090810190601f16801561075e5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b8381101561079757808201518184015260208101905061077c565b50505050905090810190601f1680156107c45780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a17fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a583604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b600061084c8383610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b60008090505b8181101561096a57838184018151811015156108d457fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561092d57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506108bc565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109d85781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a3357600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a5e57601b810190505b601b8160ff161480610a735750601c8160ff16145b1515610a7e57600080fd5b610a8a86828585610a95565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610ad857600080fd5b80925050509493505050505600a165627a7a72305820a11a9087d66f1111b554ccbcf88a2ff4ea9ae3f00754d8e38ca36404c16b46740029 \ No newline at end of file diff --git a/abi/SolUtils.bin b/abi/SolUtils.bin index 6a48b5e..fb34f75 100644 --- a/abi/SolUtils.bin +++ b/abi/SolUtils.bin @@ -1 +1 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a7230582076e5542a798eb77cf57188cde0bca45312e3955489de3675f7d6df18930bf9b20029 \ No newline at end of file +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820602c8fca3c4100237db35e105165edbc9431f78a5900fd59cd51162ef1d541010029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi index 41ce549..670dcf1 100644 --- a/abi/Validation.abi +++ b/abi/Validation.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"validators","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"blockNumber","type":"uint256"}],"name":"GetBlock","outputs":[{"name":"_blockHash","type":"bytes32"},{"name":"_prevBlockHash","type":"bytes32"},{"name":"_blockHeight","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"m_blockheaders","outputs":[{"name":"blockHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genesisHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes"}],"name":"broadcastHash2","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[{"name":"blockNumber","type":"uint256"}],"name":"GetBlock","outputs":[{"name":"_blockHash","type":"bytes32"},{"name":"_prevBlockHash","type":"bytes32"},{"name":"_blockHeight","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"m_blockheaders","outputs":[{"name":"blockHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genesisHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin index 84a4712..17b549d 100644 --- a/abi/Validation.bin +++ b/abi/Validation.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051610ca4380380610ca483398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816003816000191690555081600460008081526020019081526020016000206000018160001916905550505050610adf806101c56000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806335aa2e441461007d57806340ce4b6c146100ea5780639db7d9f714610149578063aae933e41461017c578063c4cf3ed614610271578063d405af3d146102c9575b600080fd5b34801561008957600080fd5b506100a860048036038101908080359060200190929190505050610335565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100f657600080fd5b5061011560048036038101908080359060200190929190505050610373565b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390f35b34801561015557600080fd5b5061015e6103b6565b60405180826000191660001916815260200191505060405180910390f35b34801561018857600080fd5b5061026f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506103c0565b005b34801561027d57600080fd5b5061029c60048036038101908080359060200190929190505050610857565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b3480156102d557600080fd5b506102de61087b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610321578082015181840152602081019050610306565b505050509050019250505060405180910390f35b60018181548110151561034457fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000600460008581526020019081526020016000206000015492506004600085815260200190815260200160002060010154915060025490509193909250565b6000600354905090565b600080600060608060608060606000806103db8d6004610909565b9950600354600019168a6000191614151561045e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b8c5198508c6040518082805190602001908083835b6020831015156104985780518252602082019150602081019050602083039250610473565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561053c5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105735781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156105aa5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156105e15781602001602082028038833980820191505090505b5093506105f0878e600061091d565b600260218801600260208f016004610bb8fa50610611868e608c8c0361091d565b600160208701600160208e016004610bb8fa50610632848e602a8c0361091d565b61063d87878661093f565b9250826040518082805190602001908083835b6020831015156106755780518252602082019150602081019050602083039250610650565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506106b2858e606b8c0361091d565b6106bc82866109eb565b905060011515600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515610786576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b87600381600019169055506002600081548092919060010191905055508760046000600254815260200190815260200160002060000181600019169055508960046000600254815260200190815260200160002060010181600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050505050505050505050565b60046020528060005260406000206000915090508060000154908060010154905082565b606060018054806020026020016040519081016040528092919081815260200182805480156108ff57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116108b5575b5050505050905090565b600060208201915081830151905092915050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109a65781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a0157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a2c57601b810190505b601b8160ff161480610a415750601c8160ff16145b1515610a4c57600080fd5b610a5886828585610a63565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610aa657600080fd5b80925050509493505050505600a165627a7a72305820cf83fdc91c1477a7ff4a9251338903b37b04c10ccb8538af298dd16fece5a0ba0029 \ No newline at end of file +608060405234801561001057600080fd5b50604051610b26380380610b2683398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816003816000191690555081600460008081526020019081526020016000206000018160001916905550505050610961806101c56000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806340ce4b6c146100725780639db7d9f7146100d1578063aae933e414610104578063c4cf3ed6146101f9578063d405af3d14610251575b600080fd5b34801561007e57600080fd5b5061009d600480360381019080803590602001909291905050506102bd565b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390f35b3480156100dd57600080fd5b506100e6610300565b60405180826000191660001916815260200191505060405180910390f35b34801561011057600080fd5b506101f7600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061030a565b005b34801561020557600080fd5b50610224600480360381019080803590602001909291905050506106d9565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b34801561025d57600080fd5b506102666106fd565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102a957808201518184015260208101905061028e565b505050509050019250505060405180910390f35b6000806000600460008581526020019081526020016000206000015492506004600085815260200190815260200160002060010154915060025490509193909250565b6000600354905090565b600080600060608060608060606000806103258d600461078b565b9950600354600019168a600019161415156103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b8c5198508c6040518082805190602001908083835b6020831015156103e257805182526020820191506020810190506020830392506103bd565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156104865781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156104bd5781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156104f45781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561052b5781602001602082028038833980820191505090505b50935061053a878e600061079f565b600260218801600260208f016004610bb8fa5061055b868e608c8c0361079f565b600160208701600160208e016004610bb8fa5061057c848e602a8c0361079f565b6105878787866107c1565b9250826040518082805190602001908083835b6020831015156105bf578051825260208201915060208101905060208303925061059a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506105fc858e606b8c0361079f565b610606828661086d565b905087600381600019169055506002600081548092919060010191905055508760046000600254815260200190815260200160002060000181600019169055508960046000600254815260200190815260200160002060010181600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050505050505050505050565b60046020528060005260406000206000915090508060000154908060010154905082565b6060600180548060200260200160405190810160405280929190818152602001828054801561078157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610737575b5050505050905090565b600060208201915081830151905092915050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156108285781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561088357600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff1610156108ae57601b810190505b601b8160ff1614806108c35750601c8160ff16145b15156108ce57600080fd5b6108da868285856108e5565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561092857600080fd5b80925050509493505050505600a165627a7a72305820973e5581400dbd7323a6c24b4d15a6562cc416ea892009c1044fe9318ebb62c90029 \ No newline at end of file diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 32d997c..c252ef5 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -171,6 +171,29 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra }, }) + //--------------------------------------------------------------------------------------------- + // Ion Specific Commands + // + //--------------------------------------------------------------------------------------------- + // shell.AddCmd(&ishell.Cmd{ + // Name: "ionRegisterChain", + // Help: "use: ionRegisterChain [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrTo) + // if len(c.Args) == 0 { + // c.Println("Select a block") + // } else if len(c.Args) > 2 { + // c.Println("Too many arguments entered.") + // } else { + // c.Println("RLP encode block: " + c.Args[0]) + // rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) + // c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) + // } + // c.Println("===============================================================") + // }, + // }) + // run shell shell.Run() } diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go index bcadb9b..d57d8ca 100644 --- a/ion-cli/contracts/ion.go +++ b/ion-cli/contracts/ion.go @@ -4,6 +4,7 @@ package contract import ( + "encoding/hex" "math/big" "strings" @@ -34,6 +35,35 @@ func DeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]by return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil } +func LinkDeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte, linkAddr common.Address, linkString string) (common.Address, *types.Transaction, *Ion, error) { + // Convert address to string and replace library reference in Bin + linkAddrStr := hex.EncodeToString(linkAddr.Bytes()) + NewIonBin := strings.Replace(IonBin, linkString, linkAddrStr, 1) + + parsed, err := abi.JSON(strings.NewReader(IonABI)) + if err != nil { + return common.Address{}, nil, nil, err + } + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(NewIonBin), backend, _id) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil +} + +// Deploy and Link Ion to libraries +// func LinkDeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte, linkAddr common.Address) (common.Address, *types.Transaction, *Ion, error) { +// parsed, err := abi.JSON(strings.NewReader(IonABI)) +// if err != nil { +// return common.Address{}, nil, nil, err +// } +// address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(IonBin), backend, _id) +// if err != nil { +// return common.Address{}, nil, nil, err +// } +// return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil +// } + // Ion is an auto generated Go binding around an Ethereum contract. type Ion struct { IonCaller // Read-only binding to the contract diff --git a/ion-cli/contracts/ion_test.go b/ion-cli/contracts/ion_test.go index 0a6a00e..6421190 100644 --- a/ion-cli/contracts/ion_test.go +++ b/ion-cli/contracts/ion_test.go @@ -1,161 +1,250 @@ package contract import ( - "context" + "encoding/hex" "encoding/json" "fmt" "log" "math/big" - "strings" "testing" "github.com/clearmatics/ion/ion-cli/utils" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" ) -var CLIENT = "http://127.0.0.1:8545" - -var DEPLOYEDCHAINID = "ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" -var TESTCHAINID = "22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" -var TESTBLOCK = `{"difficulty": "2","extraData": "0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00", "gasLimit": "5635559972940396", "gasUsed": "273138", "hash": "0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "miner":"0x0000000000000000000000000000000000000000","mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number": "5446","parentHash": "0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284","receiptsRoot": "0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size": "2027","stateRoot":"0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967","timestamp": "1531327572","totalDifficulty": "10893","transactions": [ "0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3","0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5","0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8","0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6","0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8","0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1","0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446","0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462","0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e","0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314","0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d","0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede","0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc"],"transactionsRoot": "0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35","uncles": []}` +var CLIENT = "http://127.0.0.1:8501" var KEY = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` var IONADDR = common.HexToAddress("0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613") -// NOTE: These tests are skipped if go test -short is called +var DEPLOYEDCHAINID = `ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075` +var TESTCHAINID = `22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254` +var TESTBLOCK = `{"difficulty": "2","extraData": "0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00", "gasLimit": "5635559972940396", "gasUsed": "273138", "hash": "0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "miner":"0x0000000000000000000000000000000000000000","mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number": "5446","parentHash": "0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284","receiptsRoot": "0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size": "2027","stateRoot":"0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967","timestamp": "1531327572","totalDifficulty": "10893","transactions": [ "0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3","0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5","0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8","0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6","0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8","0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1","0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446","0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462","0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e","0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314","0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d","0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede","0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc"],"transactionsRoot": "0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35","uncles": []}` +var TESTRLPENCODING = `f9025fa0aa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0b347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967a0cb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35a01d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002821546871405830e4c2a6c83042af2845b463454b861d88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000` +var TEST_NODE_VALUE = `0xf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a` +var TEST_PATH = `0x80` +var TEST_PARENT_NODES = `0xf8c3f851a0448f4ee6a987bf17a91096e25247c3d7d78dbd08afddb5cfd4186d6a9f36bbc080808080808080a0c47289442eb85e0ca1f12c5ac6168f15513036935879931655dadfad3586dcb78080808080808080f86e30b86bf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a` -// Test ion contract gets deployed correctly -func Test_IonDeployment(t *testing.T) { - if testing.Short() { - t.Skip("skipping testing in short mode") - } +// NOTE: These tests are skipped if go test -short is called - // Create an IPC based RPC connection to a remote node - conn, err := ethclient.Dial(CLIENT) +// Ensure that Ion is deployed as expected +func Test_IonDeployement(t *testing.T) { + // Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} + blockchain := backends.NewSimulatedBackend(alloc) + + patriciaAddress, _, _, err := DeployPatriciaTrie( + auth, + blockchain, + ) if err != nil { - log.Fatalf("Failed to connect to the Ethereum client: %v", err) + log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) } - ion, err := NewIon(IONADDR, conn) - if err != nil { - log.Fatalf("Failed to instantiate Ion contract: %v", err) - } - chainId, err := ion.ChainId(nil) + // Register id of another chain + deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) + + _, _, ion, err := LinkDeployIon( + auth, + blockchain, + deployedChainID, + patriciaAddress, + "__./contracts/libraries/PatriciaTrie.s__", + ) if err != nil { - log.Fatalf("Failed to retrieve chainId: %v", err) + log.Fatalf("Failed to link and deploy Ion: %v", err) } - // deployedChainId, err := hex.DecodeString(DEPLOYEDCHAINID) + + // commit all pending transactions + blockchain.Commit() + + chainID, err := ion.ChainId(nil) if err != nil { - log.Fatalf("Failed to retrieve chainId: %v", err) + log.Fatalf("Failed to retrieve chainID: %v", err) } // Transform into string - CHAINID := fmt.Sprintf("%x", chainId) + CHAINID := fmt.Sprintf("%x", chainID) assert.Equal(t, DEPLOYEDCHAINID, CHAINID) } -// Tests register chain is successful +// Ensure chains are registered correctly func Test_RegisterChain(t *testing.T) { - if testing.Short() { - t.Skip("skipping testing in short mode") - } - // Create an IPC based RPC connection to a remote node - conn, err := ethclient.Dial(CLIENT) + // Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} + blockchain := backends.NewSimulatedBackend(alloc) + + patriciaAddress, _, _, err := DeployPatriciaTrie( + auth, + blockchain, + ) if err != nil { - log.Fatalf("Failed to connect to the Ethereum client: %v", err) + log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) } - // Create new transactor - auth, err := bind.NewTransactor(strings.NewReader(KEY), "password1") - if err != nil { - log.Fatalf("Failed to create authorized transactor: %v", err) - } - // Get a suggested gas price - gasPrice, err := conn.SuggestGasPrice(context.Background()) + // Register id of another chain + deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) + + _, _, ion, err := LinkDeployIon( + auth, + blockchain, + deployedChainID, + patriciaAddress, + "__./contracts/libraries/PatriciaTrie.s__", + ) if err != nil { - log.Fatal(err) + log.Fatalf("Failed to link and deploy Ion: %v", err) } - auth.Value = big.NewInt(0) // in wei - auth.GasLimit = uint64(300000) // in units - auth.GasPrice = gasPrice - ion, err := NewIon(IONADDR, conn) + // commit all pending transactions + blockchain.Commit() + + testChainID, _ := utils.StringToBytes32(TESTCHAINID) + + // Register an alternate chain + _, err = ion.RegisterChain(auth, testChainID) if err != nil { - log.Fatalf("Failed to instantiate Ion contract: %v", err) + log.Fatalf("Failed to register chain: %v", err) } - testChainId := [32]byte{} - copy(testChainId[:], []byte(TESTCHAINID)) + // commit all pending transactions + blockchain.Commit() - // Register an alternate chain - _, err = ion.RegisterChain(auth, testChainId) + // Find deployed chainId + chain, err := ion.Chains(nil, big.NewInt(0)) if err != nil { - log.Fatalf("Failed to instantiate Ion contract: %v", err) + log.Fatalf("Failed to retrieve chainID: %v", err) } - // Register an alternate chain - _, err = ion.RegisterChain(auth, testChainId) - assert.NotEqual(t, nil, err) + // Transform into string + CHAIN := fmt.Sprintf("%x", chain) + assert.Equal(t, TESTCHAINID, CHAIN) + } -// Test the a Tx Proof is successfully validated -func Test_SubmitBlock(t *testing.T) { - if testing.Short() { - t.Skip("skipping testing in short mode") +// Fail if chain is registered more than once +func Test_FailRegisterChain(t *testing.T) { + // Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} + blockchain := backends.NewSimulatedBackend(alloc) + + patriciaAddress, _, _, err := DeployPatriciaTrie( + auth, + blockchain, + ) + if err != nil { + log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) } - // Create an IPC based RPC connection to a remote node - conn, err := ethclient.Dial(CLIENT) + // Register id of another chain + deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) + + _, _, ion, err := LinkDeployIon( + auth, + blockchain, + deployedChainID, + patriciaAddress, + "__./contracts/libraries/PatriciaTrie.s__", + ) if err != nil { - log.Fatalf("Failed to connect to the Ethereum client: %v", err) + log.Fatalf("Failed to link and deploy Ion: %v", err) } - // Create new transactor - auth, err := bind.NewTransactor(strings.NewReader(KEY), "password1") + // commit all pending transactions + blockchain.Commit() + + testChainID, _ := utils.StringToBytes32(TESTCHAINID) + + // Register an alternate chain + _, err = ion.RegisterChain(auth, testChainID) if err != nil { - log.Fatalf("Failed to create authorized transactor: %v", err) + log.Fatalf("Failed to register chain: %v", err) } - // Get a suggested gas price - gasPrice, err := conn.SuggestGasPrice(context.Background()) + + // commit all pending transactions + blockchain.Commit() + + // Register the same chain again + _, err = ion.RegisterChain(auth, testChainID) + assert.NotEqual(t, nil, err) +} + +// Ensure chains are registered correctly +func Test_SubmitBlock(t *testing.T) { + // Setup simulated block chain + key, _ := crypto.GenerateKey() + auth := bind.NewKeyedTransactor(key) + alloc := make(core.GenesisAlloc) + alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000000000000)} + auth.GasPrice = big.NewInt(1) + auth.GasLimit = uint64(1000000) + blockchain := backends.NewSimulatedBackend(alloc) + + patriciaAddress, _, _, err := DeployPatriciaTrie( + auth, + blockchain, + ) if err != nil { - log.Fatal(err) + log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) } - auth.Value = big.NewInt(0) // in wei - auth.GasLimit = uint64(300000) // in units - auth.GasPrice = gasPrice - // ion, err := NewIon(IONADDR, conn) - // if err != nil { - // log.Fatalf("Failed to instantiate Ion contract: %v", err) - // } + // Register id of another chain + deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - deployChainId := [32]byte{} - copy(deployChainId[:], []byte(DEPLOYEDCHAINID)) + _, _, ion, err := LinkDeployIon( + auth, + blockchain, + deployedChainID, + patriciaAddress, + "__./contracts/libraries/PatriciaTrie.s__", + ) + if err != nil { + log.Fatalf("Failed to link and deploy Ion: %v", err) + } - _, _, ion, err := DeployIon(auth, conn, deployChainId) + // commit all pending transactions + blockchain.Commit() - testChainId := [32]byte{} - copy(testChainId[:], []byte(TESTCHAINID)) + testChainID, _ := utils.StringToBytes32(TESTCHAINID) // Register an alternate chain - _, err = ion.RegisterChain(auth, testChainId) + _, err = ion.RegisterChain(auth, testChainID) if err != nil { - log.Fatalf("Failed to instantiate Ion contract: %v", err) + log.Fatalf("Failed to register chain: %v", err) } - fmt.Printf("\n%+s", TESTBLOCK) + // commit all pending transactions + blockchain.Commit() + + // Submit block var blockHeader utils.Header err = json.Unmarshal([]byte(TESTBLOCK), &blockHeader) if err != nil { log.Fatal("Unmarshal failed", err) } - fmt.Printf("\n%+s", blockHeader) + blockHash, _ := utils.StringToBytes32(blockHeader.Root) + // blockParentHash, _ := utils.StringToBytes32(blockHeader.ParentHash) + // blockTxHash, _ := utils.StringToBytes32(blockHeader.TxHash) + // blockReceiptHash, _ := utils.StringToBytes32(blockHeader.ReceiptHash) -} + rlpEncodingBytes, err := hex.DecodeString(TESTRLPENCODING) -// // Test the a Tx Proof is successfully validated -// func Test_TxProof(t *testing.T) { + _, err = ion.SubmitBlock(auth, testChainID, blockHash, rlpEncodingBytes) + if err != nil { + log.Fatalf("Failed to submit block: %v", err) + } -// } +} diff --git a/ion-cli/contracts/patricia.go b/ion-cli/contracts/patricia.go new file mode 100644 index 0000000..755c612 --- /dev/null +++ b/ion-cli/contracts/patricia.go @@ -0,0 +1,200 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contract + +import ( + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// PatriciaTrieABI is the input ABI used to generate the binding from. +const PatriciaTrieABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"},{\"name\":\"_root\",\"type\":\"bytes32\"}],\"name\":\"verifyProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" + +// PatriciaTrieBin is the compiled bytecode used for deploying new contracts. +const PatriciaTrieBin = `611278610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634f7142ad1461005d575b600080fd5b610151600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803560001916906020019092919050505061016b565b604051808215151515815260200191505060405180910390f35b60006101756111d5565b606060006060806000606060008060608061018f8f61060f565b9a5061019a8b61066a565b99508c9850600095506101ae8e6000610727565b9450600093505b89518410156105fb576101de8a858151811015156101cf57fe5b90602001906020020151610ad7565b9750876040518082805190602001908083835b60208310151561021657805182526020820191506020810190506020830392506101f1565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916896000191614151561025c5760009b506105fc565b61027c8a8581518110151561026d57fe5b9060200190602002015161066a565b9650601187511415610446578451861415610397578f6040518082805190602001908083835b6020831015156102c757805182526020820191506020810190506020830392506102a2565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661031988601081518110151561030a57fe5b90602001906020020151610ad7565b6040518082805190602001908083835b60208310151561034e5780518252602082019150602081019050602083039250610329565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141561038e5760019b506105fc565b60009b506105fc565b84868151811015156103a557fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250610439878461ffff1681518110151561042a57fe5b90602001906020020151610b3c565b98506001860195506105ee565b6002875114156105e45761047187600081518110151561046257fe5b90602001906020020151610b51565b915061047e826001610727565b51860195508451861415610592578f6040518082805190602001908083835b6020831015156104c2578051825260208201915060208101905060208303925061049d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661051488600181518110151561050557fe5b90602001906020020151610b51565b6040518082805190602001908083835b6020831015156105495780518252602082019150602081019050602083039250610524565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614156105895760019b506105fc565b60009b506105fc565b600061059f836001610727565b5114156105af5760009b506105fc565b6105d08760018151811015156105c157fe5b90602001906020020151610b51565b90506105dd816000610bc3565b98506105ed565b60009b506105fc565b5b83806001019450506101b5565b5b5050505050505050505050949350505050565b6106176111d5565b6000808351915060008214156106455760408051908101604052806000815260200160008152509250610663565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006106766111ef565b600061068185610ca1565b151561068c57600080fd5b61069585610cd3565b9250826040519080825280602002602001820160405280156106d157816020015b6106be611210565b8152602001906001900390816106b65790505b5093506106dd85610d4d565b91505b6106e982610d95565b1561071f576106f782610dbf565b848281518110151561070557fe5b9060200190602002018190525080806001019150506106e0565b505050919050565b60608060008061073561122a565b6060600060ff6040519080825280601f01601f19166020018201604052801561076d5781602001602082028038833980820191505090505b50955060009450600093505b88518410156109db576107e3898581518110151561079357fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002610e1b565b92508780156107f25750600084145b1561091a5760017f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561082a57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108b4575060037f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561088b57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b15610915578260016002811015156108c857fe5b6020020151868660ff168151811015156108de57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001850194505b6109ce565b82600060028110151561092957fe5b6020020151868660ff1681518110151561093f57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535082600160028110151561097e57fe5b6020020151866001870160ff1681518110151561099757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506002850194505b8380600101945050610779565b8460ff166040519080825280601f01601f191660200182016040528015610a115781602001602082028038833980820191505090505b509150600090505b8460ff16811015610ac8578581815181101515610a3257fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028282815181101515610a8b57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050610a19565b81965050505050505092915050565b60606000826020015190506000811415610af057610b36565b806040519080825280601f01601f191660200182016040528015610b235781602001602082028038833980820191505090505b509150610b3583600001518383610f01565b5b50919050565b6000610b4782610f42565b6001029050919050565b6060600080610b5f84610f99565b1515610b6a57600080fd5b610b7384610fca565b8092508193505050806040519080825280601f01601f191660200182016040528015610bae5781602001602082028038833980820191505090505b509250610bbc828483610f01565b5050919050565b60008060008090505b6020811015610c96576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610c0d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610bcc565b819250505092915050565b600080600083602001511415610cba5760009150610ccd565b8260000151905060c0815160001a101591505b50919050565b600080600080600080610ce587610ca1565b1515610cf45760009550610d43565b86600001519350835160001a9450610d0b8761104b565b840192506001876020015185010391505b8183111515610d3f57610d2e836110d7565b830192508080600101915050610d1c565b8095505b5050505050919050565b610d556111ef565b6000610d6083610ca1565b1515610d6b57600080fd5b610d748361104b565b83600001510190508282600001819052508082602001818152505050919050565b6000610d9f6111d5565b826000015190508060200151816000015101836020015110915050919050565b610dc76111d5565b600080610dd384610d95565b15610e0f5783602001519150610de8826110d7565b90508183600001818152505080836020018181525050808201846020018181525050610e14565b600080fd5b5050919050565b610e2361122a565b600080610e31846004611171565b9150600f7f010000000000000000000000000000000000000000000000000000000000000002841690506040805190810160405280837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525092505050919050565b60006020601f83010484602085015b828414610f2f5760208402808301518183015260018501945050610f10565b6000865160200187015250505050505050565b6000806000610f5084610f99565b1515610f5b57600080fd5b610f6484610fca565b80925081935050506020811180610f7b5750600081145b15610f8557600080fd5b806020036101000a82510492505050919050565b600080600083602001511415610fb25760009150610fc4565b8260000151905060c0815160001a1091505b50919050565b6000806000806000610fdb86610f99565b1515610fe657600080fd5b85600001519150815160001a925060808310156110095781945060019350611043565b60b88310156110275760018660200151039350600182019450611042565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b6000806000808460200151141561106557600092506110d0565b83600001519050805160001a9150608082101561108557600092506110d0565b60b88210806110a1575060c082101580156110a0575060f882105b5b156110af57600192506110d0565b60c08210156110c657600160b783030192506110d0565b600160f783030192505b5050919050565b600080825160001a905060808110156110f3576001915061116b565b60b881101561110a5760016080820301915061116a565b60c08110156111345760b78103806020036101000a60018501510480820160010193505050611169565b60f881101561114b57600160c08203019150611168565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008160020a60ff16837f0100000000000000000000000000000000000000000000000000000000000000900460ff168115156111aa57fe5b047f010000000000000000000000000000000000000000000000000000000000000002905092915050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611203611210565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a7230582027380a33dbfdf1a14b565c857047780931c383048b159e2e7117549db774476a0029` + +// DeployPatriciaTrie deploys a new Ethereum contract, binding an instance of PatriciaTrie to it. +func DeployPatriciaTrie(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *PatriciaTrie, error) { + parsed, err := abi.JSON(strings.NewReader(PatriciaTrieABI)) + if err != nil { + return common.Address{}, nil, nil, err + } + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(PatriciaTrieBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &PatriciaTrie{PatriciaTrieCaller: PatriciaTrieCaller{contract: contract}, PatriciaTrieTransactor: PatriciaTrieTransactor{contract: contract}, PatriciaTrieFilterer: PatriciaTrieFilterer{contract: contract}}, nil +} + +// PatriciaTrie is an auto generated Go binding around an Ethereum contract. +type PatriciaTrie struct { + PatriciaTrieCaller // Read-only binding to the contract + PatriciaTrieTransactor // Write-only binding to the contract + PatriciaTrieFilterer // Log filterer for contract events +} + +// PatriciaTrieCaller is an auto generated read-only Go binding around an Ethereum contract. +type PatriciaTrieCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PatriciaTrieTransactor is an auto generated write-only Go binding around an Ethereum contract. +type PatriciaTrieTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PatriciaTrieFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type PatriciaTrieFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PatriciaTrieSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type PatriciaTrieSession struct { + Contract *PatriciaTrie // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PatriciaTrieCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type PatriciaTrieCallerSession struct { + Contract *PatriciaTrieCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// PatriciaTrieTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type PatriciaTrieTransactorSession struct { + Contract *PatriciaTrieTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PatriciaTrieRaw is an auto generated low-level Go binding around an Ethereum contract. +type PatriciaTrieRaw struct { + Contract *PatriciaTrie // Generic contract binding to access the raw methods on +} + +// PatriciaTrieCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type PatriciaTrieCallerRaw struct { + Contract *PatriciaTrieCaller // Generic read-only contract binding to access the raw methods on +} + +// PatriciaTrieTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type PatriciaTrieTransactorRaw struct { + Contract *PatriciaTrieTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewPatriciaTrie creates a new instance of PatriciaTrie, bound to a specific deployed contract. +func NewPatriciaTrie(address common.Address, backend bind.ContractBackend) (*PatriciaTrie, error) { + contract, err := bindPatriciaTrie(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &PatriciaTrie{PatriciaTrieCaller: PatriciaTrieCaller{contract: contract}, PatriciaTrieTransactor: PatriciaTrieTransactor{contract: contract}, PatriciaTrieFilterer: PatriciaTrieFilterer{contract: contract}}, nil +} + +// NewPatriciaTrieCaller creates a new read-only instance of PatriciaTrie, bound to a specific deployed contract. +func NewPatriciaTrieCaller(address common.Address, caller bind.ContractCaller) (*PatriciaTrieCaller, error) { + contract, err := bindPatriciaTrie(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PatriciaTrieCaller{contract: contract}, nil +} + +// NewPatriciaTrieTransactor creates a new write-only instance of PatriciaTrie, bound to a specific deployed contract. +func NewPatriciaTrieTransactor(address common.Address, transactor bind.ContractTransactor) (*PatriciaTrieTransactor, error) { + contract, err := bindPatriciaTrie(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PatriciaTrieTransactor{contract: contract}, nil +} + +// NewPatriciaTrieFilterer creates a new log filterer instance of PatriciaTrie, bound to a specific deployed contract. +func NewPatriciaTrieFilterer(address common.Address, filterer bind.ContractFilterer) (*PatriciaTrieFilterer, error) { + contract, err := bindPatriciaTrie(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PatriciaTrieFilterer{contract: contract}, nil +} + +// bindPatriciaTrie binds a generic wrapper to an already deployed contract. +func bindPatriciaTrie(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(PatriciaTrieABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_PatriciaTrie *PatriciaTrieRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _PatriciaTrie.Contract.PatriciaTrieCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_PatriciaTrie *PatriciaTrieRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _PatriciaTrie.Contract.PatriciaTrieTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_PatriciaTrie *PatriciaTrieRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _PatriciaTrie.Contract.PatriciaTrieTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_PatriciaTrie *PatriciaTrieCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _PatriciaTrie.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_PatriciaTrie *PatriciaTrieTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _PatriciaTrie.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_PatriciaTrie *PatriciaTrieTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _PatriciaTrie.Contract.contract.Transact(opts, method, params...) +} + +// VerifyProof is a free data retrieval call binding the contract method 0x4f7142ad. +// +// Solidity: function verifyProof(_value bytes, _parentNodes bytes, _path bytes, _root bytes32) constant returns(bool) +func (_PatriciaTrie *PatriciaTrieCaller) VerifyProof(opts *bind.CallOpts, _value []byte, _parentNodes []byte, _path []byte, _root [32]byte) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _PatriciaTrie.contract.Call(opts, out, "verifyProof", _value, _parentNodes, _path, _root) + return *ret0, err +} + +// VerifyProof is a free data retrieval call binding the contract method 0x4f7142ad. +// +// Solidity: function verifyProof(_value bytes, _parentNodes bytes, _path bytes, _root bytes32) constant returns(bool) +func (_PatriciaTrie *PatriciaTrieSession) VerifyProof(_value []byte, _parentNodes []byte, _path []byte, _root [32]byte) (bool, error) { + return _PatriciaTrie.Contract.VerifyProof(&_PatriciaTrie.CallOpts, _value, _parentNodes, _path, _root) +} + +// VerifyProof is a free data retrieval call binding the contract method 0x4f7142ad. +// +// Solidity: function verifyProof(_value bytes, _parentNodes bytes, _path bytes, _root bytes32) constant returns(bool) +func (_PatriciaTrie *PatriciaTrieCallerSession) VerifyProof(_value []byte, _parentNodes []byte, _path []byte, _root [32]byte) (bool, error) { + return _PatriciaTrie.Contract.VerifyProof(&_PatriciaTrie.CallOpts, _value, _parentNodes, _path, _root) +} diff --git a/ion-cli/utils/helpers.go b/ion-cli/utils/helpers.go new file mode 100644 index 0000000..76c47bd --- /dev/null +++ b/ion-cli/utils/helpers.go @@ -0,0 +1,51 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package utils + +import ( + "context" + "encoding/hex" + "fmt" + "log" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/ethclient" +) + +func GetNonce(client *ethclient.Client, auth *bind.TransactOpts) { + // Find the correct tx nonce + nonce, err := client.PendingNonceAt(context.Background(), auth.From) + if err != nil { + log.Fatalf("Failed to calculate nonce: %v", err) + } + + auth.Nonce = big.NewInt(int64(nonce)) +} + +// Needed to convert transaction strings into the correct format +func StringToBytes32(input string) (output [32]byte, err error) { + // Check string length is correct 64 + if len(input) == 64 { + inputBytes, err := hex.DecodeString(input) + if err != nil { + log.Fatalf("Failed to encode string as bytes: %v", err) + } + + copy(output[:], inputBytes[:len(output)]) + + return output, nil + } else if len(input) == 66 && input[:2] == "0x" { + inputBytes, err := hex.DecodeString(input[2:]) + if err != nil { + log.Fatalf("Failed to encode string as bytes: %v", err) + } + + copy(output[:], inputBytes[:len(output)]) + + return output, nil + } else { + return [32]byte{}, fmt.Errorf("Failed to encode string as bytes32, incorrect string input") + } + +} diff --git a/ion-cli/utils/helpers_test.go b/ion-cli/utils/helpers_test.go new file mode 100644 index 0000000..dae2ebe --- /dev/null +++ b/ion-cli/utils/helpers_test.go @@ -0,0 +1,40 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package utils_test + +import ( + "fmt" + "testing" + + "github.com/clearmatics/ion/ion-cli/utils" + "github.com/stretchr/testify/assert" +) + +var TESTSTRING = "aa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284" +var TESTSTRINGPREFIX = "0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284" +var TESTSTRINGFAIL = "0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff628432" + +// Encodes a hex string as bytes array specifically Bytes32 +func Test_StringToBytes32(t *testing.T) { + result, _ := utils.StringToBytes32(TESTSTRING) + + // Transform bytes back into string + stringResult := fmt.Sprintf("%x", result) + assert.Equal(t, TESTSTRING, stringResult) +} + +// Encodes a hex string with prefix as bytes array specifically Bytes32 +func Test_StringToBytes32_Prefix(t *testing.T) { + result, _ := utils.StringToBytes32(TESTSTRINGPREFIX[2:]) + + // Transform bytes back into string + stringResult := fmt.Sprintf("%x", result) + assert.Equal(t, TESTSTRING, stringResult) +} + +// Encodes a hex string with prefix as bytes array specifically Bytes32 +func Test_StringToBytes32_IncorrectInput(t *testing.T) { + _, err := utils.StringToBytes32(TESTSTRINGFAIL) + + assert.NotEqual(t, nil, err) +} diff --git a/ion-cli/utils/rlp_test.go b/ion-cli/utils/rlp_test.go index 275329f..758a78a 100644 --- a/ion-cli/utils/rlp_test.go +++ b/ion-cli/utils/rlp_test.go @@ -16,12 +16,12 @@ var EXPECTEDINTERFACE = "[6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37 var EXPECTEDRLPBLOCK = "f90256a06341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a053580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002018347c94c008458ee45dab861d783010600846765746887676f312e372e33856c696e757800000000000000009f1efa1efa72af138c915966c639544a0255e6288e188c22ce9168c10dbe46da3d88b4aa065930119fb886210bf01a084fde5d3bc48d8aa38bca92e4fcc5215100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" -var block = `{"parentHash": "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177", "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "miner": "0x0000000000000000000000000000000000000000","stateRoot": "0x53580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2d","transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "difficulty": "0x2", "number": "0x1","gasLimit": "0x47c94c", "gasUsed": "0x0", "timestamp": "0x58ee45da", "extraData": "0xd783010600846765746887676f312e372e33856c696e757800000000000000009f1efa1efa72af138c915966c639544a0255e6288e188c22ce9168c10dbe46da3d88b4aa065930119fb886210bf01a084fde5d3bc48d8aa38bca92e4fcc5215100", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","nonce": "0x0000000000000000"}` +var TESTBLOCK = `{"parentHash": "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177", "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "miner": "0x0000000000000000000000000000000000000000","stateRoot": "0x53580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2d","transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "difficulty": "0x2", "number": "0x1","gasLimit": "0x47c94c", "gasUsed": "0x0", "timestamp": "0x58ee45da", "extraData": "0xd783010600846765746887676f312e372e33856c696e757800000000000000009f1efa1efa72af138c915966c639544a0255e6288e188c22ce9168c10dbe46da3d88b4aa065930119fb886210bf01a084fde5d3bc48d8aa38bca92e4fcc5215100", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","nonce": "0x0000000000000000"}` // EncodePrefix calculate prefix of the entire signed block func Test_EncodePrefix(t *testing.T) { var blockHeader utils.Header - err := json.Unmarshal([]byte(block), &blockHeader) + err := json.Unmarshal([]byte(TESTBLOCK), &blockHeader) if err != nil { log.Fatal("Unmarshal failed", err) } @@ -33,7 +33,7 @@ func Test_EncodePrefix(t *testing.T) { // EncodeExtraData calculate prefix of the extraData field without the signatures func Test_EncodeExtraData(t *testing.T) { var blockHeader utils.Header - err := json.Unmarshal([]byte(block), &blockHeader) + err := json.Unmarshal([]byte(TESTBLOCK), &blockHeader) if err != nil { log.Fatal("Unmarshal failed", err) } @@ -45,7 +45,7 @@ func Test_EncodeExtraData(t *testing.T) { // EncodeBlock rlp encodes the martialled JSON struct func Test_EncodeBlock(t *testing.T) { var blockHeader utils.Header - err := json.Unmarshal([]byte(block), &blockHeader) + err := json.Unmarshal([]byte(TESTBLOCK), &blockHeader) if err != nil { log.Fatal("Unmarshal failed", err) } diff --git a/package.json b/package.json index a760d5b..e07b9b2 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "test": "truffle test --network clique", "coverage": "solidity-coverage", "lint": "solhint contracts/**/*.sol", - "genbin": "solc --overwrite --bin ./contracts/* -o abi", - "genabi": "solc --overwrite --abi ./contracts/* -o abi", + "genbin": "solc --overwrite --bin ./contracts/*.sol -o abi", + "genabi": "solc --overwrite --abi ./contracts/*.sol -o abi", "abigen": "abigen --bin=abi/Validation.bin --abi=abi/Validation.abi --pkg=validation --out=validation.go" } } diff --git a/test/validation.js b/test/validation.js index cfe8d81..13599a8 100644 --- a/test/validation.js +++ b/test/validation.js @@ -59,7 +59,7 @@ signHeader = (headerHash, privateKey, extraData) => { -contract.only('Validation.js', (accounts) => { +contract('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From 4cefb58f5b5a88c17f116989f4ed18097f5e59f9 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 25 Jul 2018 15:10:38 +0100 Subject: [PATCH 077/203] Rewrote the verification stack. Optimised and simplified the architecture of the way verifiers would be written and used to be more general. Tests updated for verification stack and now explicitly checks for the event that is executed after consumption. --- contracts/EventVerifier.sol | 98 +++++++++++++----------------- contracts/Function.sol | 9 ++- contracts/TriggerEventVerifier.sol | 58 ++++++++++++++++++ test/ion.js | 17 ++++-- 4 files changed, 118 insertions(+), 64 deletions(-) create mode 100644 contracts/TriggerEventVerifier.sol diff --git a/contracts/EventVerifier.sol b/contracts/EventVerifier.sol index f61242c..dea8698 100644 --- a/contracts/EventVerifier.sol +++ b/contracts/EventVerifier.sol @@ -2,76 +2,64 @@ pragma solidity ^0.4.23; import "./RLP.sol"; -contract EventVerifier { - function verify(bytes20 _contractEmittedAddress, bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool) { +/* + EventVerifier + + This contract is the basic global EventVerifier interface that all specific event verifiers must inherit from. + + It supplies a function `retrieveLog` that will output the relevant log for a specified event signature from the + provided receipts. Each specific verifier that inherits this contract must hold knowledge of the event signature it + intends to consume which will be passed to the retrieval function for log separation. +*/ - /* Here we decode the receipt into it's consituents and grab the logs as we know it's position in the receipt - object and proceed to decode the logs also. +contract EventVerifier { + /* + retrieveLog + param: _eventSignature (bytes32) Hash representing the event signature of the event type to be consumed + param: _contractEmittedAddress (bytes20) Address of the contract expected to have emitted the event + param: _rlpReceipt (bytes) RLP-encoded receipt containing the relevant logs + + returns: log (RLP.RLPItem[]) Decoded log object in the form [ contractAddress, topics, data ] + + This decodes an RLP-encoded receipt and trawls through the logs to find the event that matches the event + signature required and checks if the event was emitted from the correct source. If no log could be found with + the relevant signature or emitted from the expected source the execution fails with an assert. + + If a log is not found, an `assert(false)` consumes all the gas and fails the transaction in order to incentivise + submission of proper data. + */ + function retrieveLog(bytes32 _eventSignature, bytes20 _contractEmittedAddress, bytes _rlpReceipt) + internal returns (RLP.RLPItem[]) + { + /* Decode the receipt into it's consituents and grab the logs with it's known position in the receipt + object and proceed to decode the logs also. */ RLP.RLPItem[] memory receipt = RLP.toList(RLP.toRLPItem(_rlpReceipt)); RLP.RLPItem[] memory logs = RLP.toList(receipt[3]); - - /* - In this example there should be only one set of logs but in other cases there may be multiple sets of logs, - one set per event emitted per transaction. It will be the writer of the event verifier to locate the correct - log in the receipts through iteration. + /* The receipts could contain multiple event logs if a single transaction emitted multiple events. We need to + separate them and locate the relevant event by signature. */ - assert( logs.length == 1 ); - - - // The log decoded into a list: log = [ contractAddress (bytes32), topics (array), data (bytes) ] - RLP.RLPItem[] memory log = RLP.toList(logs[0]); - - - /* - In the case where there are multiple logs, the below code should iterate through them to find the correct one: - - bytes32 expectedEventSignature = 0xsomespecifichash - RLP.RLPItem[] memory log; for (uint i = 0; i < logs.length; i++) { - log = RLP.toList(logs[i]); + RLP.RLPItem[] memory log = RLP.toList(logs[i]); RLP.RLPItem[] memory topics = RLP.toList(log[1]); - bytes32 eventSignature = RLP.toBytes32(topics[0]); - if (eventSignature == expectedEventSignature) { - break; + + bytes32 containedEventSignature = RLP.toBytes32(topics[0]); + if (containedEventSignature == _eventSignature) { + // If event signature is found, check the contract address it was emitted from + bytes20 b20_emissionSource = bytesToBytes20(RLP.toData(log[0]), 0); + assert( b20_emissionSource == _contractEmittedAddress); + return log; } } - - And then separated into it's constituents for processing below: - */ - bytes memory contractEmittedEvent = RLP.toData(log[0]); - RLP.RLPItem[] memory topics = RLP.toList(log[1]); - bytes memory data = RLP.toData(log[2]); - - bytes20 emissionSource = bytesToBytes20(contractEmittedEvent, 0); - assert( emissionSource == _contractEmittedAddress); - - /* - This section below is specific to this event and checks the relevant data. - In this event we only expect a single un-indexed address parameter which will be present in the data field. - The data field pads it's contents if they are less than 32 bytes. Therefore we know that our address parameter - exists in the 20 least significant bytes of the data field. - - We copy the last 20 bytes of our data field to a bytes20 variable to compare against the supplied expected - parameter in the event from our function call. This acts as our conditional check that the event called is what - the user expects. - */ - bytes20 b20_address = bytesToBytes20(data, data.length - 20); - assert( b20_address == _expectedAddress ); - - /* - Once verified, the logs of this specific event are proven as true and returns as such. Else, the execution - reverts. - */ - return true; + assert( false ); } - function bytesToBytes20(bytes _b, uint _offset) private pure returns (bytes20) { + function bytesToBytes20(bytes b, uint _offset) private pure returns (bytes20) { bytes20 out; for (uint i = 0; i < 20; i++) { - out |= bytes20(_b[_offset + i] & 0xFF) >> (i * 8); + out |= bytes20(b[_offset + i] & 0xFF) >> (i * 8); } return out; } diff --git a/contracts/Function.sol b/contracts/Function.sol index f592734..bf0bafe 100644 --- a/contracts/Function.sol +++ b/contracts/Function.sol @@ -1,8 +1,11 @@ pragma solidity ^0.4.23; -import "./EventVerifier.sol"; import "./Ion.sol"; +contract TriggerEventVerifier { + function verify(bytes20 _contractEmittedAddress, bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool); +} + /* This function contract is the consumer of an event and performs some execution thereafter. In practice, this would be written by a contract designer that intends to consume specific events from another chain. As such all behaviour @@ -25,7 +28,7 @@ contract Function { /* The event verifier for the specific event being consumed. Each event would require a different event verifier to be deployed and each consumer would reference the relevant verifier to prove logs. */ - EventVerifier verifier; + TriggerEventVerifier verifier; /* Custom event that fires when execution is performed successfully. */ event Executed(); @@ -34,7 +37,7 @@ contract Function { use one verifier. */ constructor(address _ionAddr, address _verifierAddr) public { ion = Ion(_ionAddr); - verifier = EventVerifier(_verifierAddr); + verifier = TriggerEventVerifier(_verifierAddr); } /* This is the function that is intended to be executed upon successful verification of proofs */ diff --git a/contracts/TriggerEventVerifier.sol b/contracts/TriggerEventVerifier.sol new file mode 100644 index 0000000..92e587c --- /dev/null +++ b/contracts/TriggerEventVerifier.sol @@ -0,0 +1,58 @@ +pragma solidity ^0.4.23; + +import "./RLP.sol"; +import "./EventVerifier.sol"; + +/* + TriggerEventVerifier + + Inherits from `EventVerifier` and verifies `Triggered` events. + + From the provided logs, we separate the data and define checks to assert certain information in the event and + returns `true` if successful. + + Contracts similar to this that verify specific events should be designed only to verify the data inside the + supplied events with similarly supplied expected outcomes. It is only meant to serve as a utility to perform defined + checks against specific events. +*/ +contract TriggerEventVerifier is EventVerifier { + bytes32 eventSignature = keccak256("Triggered(address)"); + + function verify(bytes20 _contractEmittedAddress, bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool) { + // Retrieve specific log for given event signature + RLP.RLPItem[] memory log = retrieveLog(eventSignature, _contractEmittedAddress, _rlpReceipt); + + // Split logs into constituents. Not all constituents are used here + bytes memory contractEmittedEvent = RLP.toData(log[0]); + RLP.RLPItem[] memory topics = RLP.toList(log[1]); + bytes memory data = RLP.toData(log[2]); + + /* + This section below is specific to this event verifier and checks the relevant data. + In this event we only expect a single un-indexed address parameter which will be present in the data field. + The data field pads it's contents if they are less than 32 bytes. Therefore we know that our address parameter + exists in the 20 least significant bytes of the data field. + + We copy the last 20 bytes of our data field to a bytes20 variable to compare against the supplied expected + parameter in the event from our function call. This acts as our conditional check that the event called is what + the user expects. + */ + bytes20 b20_address = bytesToBytes20(data, data.length - 20); + assert( b20_address == _expectedAddress ); + + /* + Once verified, the logs of this specific event are proven as true and returns as such. Else, the execution + reverts. + */ + return true; + } + + function bytesToBytes20(bytes b, uint _offset) private pure returns (bytes20) { + bytes20 out; + + for (uint i = 0; i < 20; i++) { + out |= bytes20(b[_offset + i] & 0xFF) >> (i * 8); + } + return out; + } +} diff --git a/test/ion.js b/test/ion.js index cd37a6d..9b27624 100644 --- a/test/ion.js +++ b/test/ion.js @@ -14,7 +14,7 @@ const Web3 = require('web3'); const Ion = artifacts.require("Ion"); const PatriciaTrie = artifacts.require("PatriciaTrie"); -const EventVerifier = artifacts.require("EventVerifier"); +const TriggerEventVerifier = artifacts.require("TriggerEventVerifier"); const Function = artifacts.require("Function"); require('chai') @@ -278,21 +278,21 @@ contract('Ion.js', (accounts) => { await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; // Fail with wrong tx nodes - await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_NODES).should.be.rejected; + await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_NODES).should.be.rejected; // Fail with wrong receipt nodes - await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; + await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; }) it('Deploy Function Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const verifier = await EventVerifier.new(); + const verifier = await TriggerEventVerifier.new(); const functionContract = await Function.new(ion.address, verifier.address); }) it('Verify Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const verifier = await EventVerifier.new(); + const verifier = await TriggerEventVerifier.new(); const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion @@ -301,12 +301,17 @@ contract('Ion.js', (accounts) => { let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); + executeEventFound = tx.logs.some(l => { return l.event == "Executed" }); + assert.ok(executeEventFound, "Function did not execute"); + console.log("Gas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); + + }) it('Fail Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const verifier = await EventVerifier.new(); + const verifier = await TriggerEventVerifier.new(); const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion From 55d516fbe14124cd5d69d86ee164976ec9cc7cf1 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 25 Jul 2018 15:33:13 +0100 Subject: [PATCH 078/203] Function contract now inherits IonCompatible. Trigger contract updated with comments re deployment information on Rinkeby. --- contracts/ECVerify.sol | 106 ---------------------------------- contracts/ERC20Interface.sol | 17 ------ contracts/ERC223Interface.sol | 21 ------- contracts/Function.sol | 9 +-- contracts/IonCompatible.sol | 4 +- contracts/Merkle.sol | 52 ----------------- contracts/SafeMath.sol | 65 --------------------- contracts/Trigger.sol | 15 +++++ 8 files changed, 21 insertions(+), 268 deletions(-) delete mode 100644 contracts/ECVerify.sol delete mode 100644 contracts/ERC20Interface.sol delete mode 100644 contracts/ERC223Interface.sol delete mode 100644 contracts/Merkle.sol delete mode 100644 contracts/SafeMath.sol diff --git a/contracts/ECVerify.sol b/contracts/ECVerify.sol deleted file mode 100644 index 622dd6b..0000000 --- a/contracts/ECVerify.sol +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -// -// The new assembly support in Solidity makes writing helpers easy. -// Many have complained how complex it is to use `ecrecover`, especially in conjunction -// with the `eth_sign` RPC call. Here is a helper, which makes that a matter of a single call. -// -// Sample input parameters: -// (with v=0) -// "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad", -// "0xaca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf200", -// "0x0e5cb767cce09a7f3ca594df118aa519be5e2b5a" -// -// (with v=1) -// "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad", -// "0xdebaaa0cddb321b2dcaaf846d39605de7b97e77ba6106587855b9106cb10421561a22d94fa8b8a687ff9c911c844d1c016d1a685a9166858f9c7c1bc85128aca01", -// "0x8743523d96a1b2cbe0c6909653a56da18ed484af" -// -// (The hash is a hash of "hello world".) -// -// Written by Alex Beregszaszi (@axic), use it under the terms of the MIT license. -// - -library ECVerify { - // Duplicate Solidity's ecrecover, but catching the CALL return value - function safer_ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) - constant - internal - returns (address) - { - // We do our own memory management here. Solidity uses memory offset - // 0x40 to store the current end of memory. We write past it (as - // writes are memory extensions), but don't update the offset so - // Solidity will reuse it. The memory used here is only needed for - // this context. - - // FIXME: inline assembly can't access return values - bool ret; - address addr; - - assembly { - let size := mload(0x40) - mstore(size, hash) - mstore(add(size, 32), v) - mstore(add(size, 64), r) - mstore(add(size, 96), s) - - // NOTE: we can reuse the request memory because we deal with - // the return code - ret := call(3000, 1, 0, size, 128, size, 32) - addr := mload(size) - } - - require( ret == true ); - - return addr; - } - - function ecrecovery(bytes32 hash, bytes sig) internal constant returns (address) { - bytes32 r; - bytes32 s; - uint8 v; - - require (sig.length == 65); - - // The signature format is a compact form of: - // {bytes32 r}{bytes32 s}{uint8 v} - // Compact means, uint8 is not padded to 32 bytes. - assembly { - r := mload(add(sig, 32)) - s := mload(add(sig, 64)) - - // Here we are loading the last 32 bytes. We exploit the fact that - // 'mload' will pad with zeroes if we overread. - // There is no 'mload8' to do this, but that would be nicer. - /* v := byte(0, mload(add(sig, 96))) */ - - // Alternative solution: - // 'byte' is not working due to the Solidity parser, so lets - // use the second best option, 'and' - v := and(mload(add(sig, 65)), 255) - } - - // albeit non-transactional signatures are not specified by the YP, one would expect it - // to match the YP range of [27, 28] - // - // geth uses [0, 1] and some clients have followed. This might change, see: - // https://github.com/ethereum/go-ethereum/issues/2053 - if (v < 27) - v += 27; - - require (v == 27 || v == 28); - - /* prefix might be needed for geth only - * https://github.com/ethereum/go-ethereum/issues/3731 - */ - bytes memory prefix = "\x19Ethereum Signed Message:\n32"; - hash = keccak256(prefix, hash); - /* hash = sha3(prefix, hash); */ - - return safer_ecrecover(hash, v, r, s); - /* return ecrecover(hash, v, r, s); */ - } -} diff --git a/contracts/ERC20Interface.sol b/contracts/ERC20Interface.sol deleted file mode 100644 index 0b5487e..0000000 --- a/contracts/ERC20Interface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2017-2018 Clearmatics Technologies Ltd - -// SPDX-License-Identifier: LGPL-3.0+ - -pragma solidity 0.4.23; - - -contract ERC20Interface { - function transferFrom(address from, address to, uint256 value) public returns (bool); - function approve(address spender, uint256 value) public returns (bool); - function increaseApproval(address spender, uint addedValue) public returns (bool); - function decreaseApproval(address spender, uint subtractedValue) public returns (bool); - function allowance(address owner, address spender) public view returns (uint256); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint256 value); -} diff --git a/contracts/ERC223Interface.sol b/contracts/ERC223Interface.sol deleted file mode 100644 index a935759..0000000 --- a/contracts/ERC223Interface.sol +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2017-2018 Clearmatics Technologies Ltd - -// SPDX-License-Identifier: LGPL-3.0+ - -pragma solidity 0.4.23; - - -contract ERC223Interface { - function name() public view returns (string); - function symbol() public view returns (string); - function decimals() public view returns (uint8); - function totalSupply() public view returns (uint256); - function balanceOf(address addr) public view returns (uint); - - function transfer(address to, uint value) public returns (bool); - function transfer(address to, uint value, bytes data) public returns (bool); - function transfer(address to, uint value, bytes data, string customFallback) public returns (bool); - - // solhint-disable-next-line no-simple-event-func-name - event Transfer(address from, address to, uint value, bytes data); -} diff --git a/contracts/Function.sol b/contracts/Function.sol index bf0bafe..1a679a5 100644 --- a/contracts/Function.sol +++ b/contracts/Function.sol @@ -1,6 +1,7 @@ pragma solidity ^0.4.23; import "./Ion.sol"; +import "./IonCompatible.sol"; contract TriggerEventVerifier { function verify(bytes20 _contractEmittedAddress, bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool); @@ -21,10 +22,7 @@ contract TriggerEventVerifier { This would also bloat the local scope which is prone to 'stack too deep' issues which would require custom workarounds. */ -contract Function { - /* The Ion contract that proofs would be made to. Ensure that prior to verification attempts that the relevant - blocks have been submitted to the Ion contract. */ - Ion ion; +contract Function is IonCompatible { /* The event verifier for the specific event being consumed. Each event would require a different event verifier to be deployed and each consumer would reference the relevant verifier to prove logs. */ @@ -35,8 +33,7 @@ contract Function { /* Constructor. Requires Ion contract address and all used event verifier contract addresses. In this case we only use one verifier. */ - constructor(address _ionAddr, address _verifierAddr) public { - ion = Ion(_ionAddr); + constructor(address _ionAddr, address _verifierAddr) IonCompatible(_ionAddr) public { verifier = TriggerEventVerifier(_verifierAddr); } diff --git a/contracts/IonCompatible.sol b/contracts/IonCompatible.sol index 3a67d63..9daeac3 100644 --- a/contracts/IonCompatible.sol +++ b/contracts/IonCompatible.sol @@ -2,7 +2,9 @@ pragma solidity ^0.4.0; import "./Ion.sol"; contract IonCompatible { - Ion ion; + /* The Ion contract that proofs would be made to. Ensure that prior to verification attempts that the relevant + blocks have been submitted to the Ion contract. */ + Ion internal ion; constructor(address ionAddr) public { ion = Ion(ionAddr); diff --git a/contracts/Merkle.sol b/contracts/Merkle.sol deleted file mode 100644 index bae7d10..0000000 --- a/contracts/Merkle.sol +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - -library Merkle { - //uint256 constant ONE_SHL_255 = 57896044618658097711785492504343953926634992332820282019728792003956564819968; - uint256 constant ONE_SHL_255 = 28948022309329048855892746252171976963317496166410141009864396001978282409984; - - function Hash( uint256 a, uint256 b ) - internal pure - returns (uint256) - { - uint256 x = uint256(keccak256(a, b)); - - // Clears highest bit from result - // left/right of node is stored there - if( x & ONE_SHL_255 > 0 ) - return x ^ ONE_SHL_255; - return x; - } - - /* - * Test case: - * "0x1a792cf089bfa56eae57ffe87e9b22f9c9bfe52c1ac300ea1f43f4ab53b4b794","0x2584db4a68aa8b172f70bc04e2e74541617c003374de6eb4b295e823e5beab01",["0x1ab0c6948a275349ae45a06aad66a8bd65ac18074615d53676c09b67809099e0","0x093fd25755220b8f497d65d2538c01ed279c131f63e42b2942867f2bd6622486","0xb1d101d9a9d27c3a8ed9d1b6548626eacf3d19546306117eb8af547d1e97189e","0xcb431dd627bc8dcfd858eae9304dc71a8d3f34a8de783c093188bb598eeafd04"] - */ - - function Verify( uint256 root, uint256 leaf_hash, uint256[] path ) - internal pure returns (bool) { - if( leaf_hash & ONE_SHL_255 > 0 ) - leaf_hash ^= ONE_SHL_255; - - if( path.length == 0 ) - return leaf_hash == root; - - uint256 node = leaf_hash; - uint256 item; - - for( uint256 i = 0; i < path.length; i++ ) - { - item = path[i]; - - if( (item & ONE_SHL_255) > 0 ) { - node = Hash(node, item ^ ONE_SHL_255); - } - else { - node = Hash(item, node); - } - } - - return node == root; - } -} diff --git a/contracts/SafeMath.sol b/contracts/SafeMath.sol deleted file mode 100644 index 3094245..0000000 --- a/contracts/SafeMath.sol +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; - - -/** - * Math operations with safety checks - */ -library SafeMath { - function mul(uint a, uint b) - internal pure returns (uint) - { - uint c = a * b; - assert(a == 0 || c / a == b); - return c; - } - - function div(uint a, uint b) - internal pure returns (uint) - { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - uint c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return c; - } - - function sub(uint a, uint b) - internal pure returns (uint) - { - assert(b <= a); - return a - b; - } - - function add(uint a, uint b) - internal pure returns (uint) - { - uint c = a + b; - assert(c >= a); - return c; - } - - function max64(uint64 a, uint64 b) - internal pure returns (uint64) - { - return a >= b ? a : b; - } - - function min64(uint64 a, uint64 b) - internal pure returns (uint64) - { - return a < b ? a : b; - } - - function max256(uint256 a, uint256 b) - internal pure returns (uint256) - { - return a >= b ? a : b; - } - - function min256(uint256 a, uint256 b) - internal pure returns (uint256) - { - return a < b ? a : b; - } -} diff --git a/contracts/Trigger.sol b/contracts/Trigger.sol index ece8548..66958e3 100644 --- a/contracts/Trigger.sol +++ b/contracts/Trigger.sol @@ -1,5 +1,20 @@ pragma solidity ^0.4.23; +/* + Trigger + + Example contract that emits an event to be consumed. + + Currently an instance deployed to: + Rinkeby @: 0x61621bcf02914668f8404c1f860e92fc1893f74c + Deployment Tx Hash: 0xc9500e84af2394e1d91b43e40c9c89f105636748f95ae05c11c73f2fd755795e + Deployed Block Number: 2657325 + `fire()` call Tx Hash 0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e + + The current tests are running against generated proofs from Rinkeby for the above data and consumes the event + emitted in the transaction executed. +*/ + contract Trigger { event Triggered(address caller); From 941c43ae401a7e0594c49089c8dc330c3740d894 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 25 Jul 2018 17:34:45 +0100 Subject: [PATCH 079/203] Added validation to the Ion contract in future we can deprecate the validation.sol --- .travis.yml | 2 +- contracts/Ion.sol | 142 +++++++++++++++++++++++++++++++-------- contracts/Validation.sol | 2 +- test/helpers/utils.js | 49 +++++++++----- test/ion.js | 136 +++++++++++++++++++++++++++++++++---- 5 files changed, 271 insertions(+), 60 deletions(-) diff --git a/.travis.yml b/.travis.yml index aef3362..a868acc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ matrix: go: 1.9.x script: - npm install - - npm depclique + - npm run depclique - npm run test - cd ./ion-cli - go get -t ./... diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 14e6c79..6478366 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; +import "./libraries/ECVerify.sol"; import "./libraries/RLP.sol"; import "./libraries/PatriciaTrie.sol"; @@ -11,15 +12,26 @@ contract Ion { using RLP for bytes; struct BlockHeader { + uint256 blockHeight; bytes32 prevBlockHash; bytes32 txRootHash; bytes32 receiptRootHash; } + + address[] public validators; + bytes32 public blockHash; bytes32 public chainId; bytes32[] public chains; - mapping (bytes32 => bytes32[]) public m_blockhashes; - mapping (bytes32 => BlockHeader) public m_blockheaders; + uint256 public blockHeight; + + mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; + // XXX: @shirikatsu this has changed from bytes32 to uint256 to allow block ordering + mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; + + // input chainId to validators address returning bool + mapping (bytes32 => mapping (address => bool)) public m_validators; + /* * Constructor @@ -34,6 +46,9 @@ contract Ion { } event VerifiedTxProof(bytes32 chainId, bytes32 blockHash); + event broadcastSignature(address signer); + event broadcastHash(bytes32 blockHash); + /* ======================================================================================================================== @@ -61,15 +76,7 @@ contract Ion { } modifier onlyExistingBlocks(bytes32 _id, bytes32 _hash) { - bool blockExists = false; - bytes32[] memory hashes = m_blockhashes[_id]; - for (uint i = 0; i < hashes.length; i++) { - if (_hash == hashes[i]) { - blockExists = true; - break; - } - } - require(blockExists, "Block does not exist for chain"); + require(m_blockhashes[_id][_hash], "Block does not exist for chain"); _; } @@ -88,12 +95,20 @@ contract Ion { * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. */ - function RegisterChain(bytes32 _id) public { + function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { require( _id != chainId, "Cannot add this chain id to chain register" ); for (uint i = 0; i < chains.length; i++) { require( chains[i] != _id, "Chain already exists" ); } chains.push(_id); + + for (i = 0; i < _validators.length; i++) { + m_validators[_id][_validators[i]] = true; + } + + // blockHash = _genesisHash; + m_blockhashes[_id][_genesisHash] = true; + m_blockheaders[_id][_genesisHash].blockHeight = 0; } /* @@ -111,7 +126,7 @@ contract Ion { bytes32 hashedHeader = keccak256(_rlpBlockHeader); require( hashedHeader == _blockHash ); - BlockHeader storage blockHeader = m_blockheaders[_blockHash]; + BlockHeader storage blockHeader = m_blockheaders[_id][_blockHash]; blockHeader.prevBlockHash = bytesToBytes32(header[0].toBytes(), 1); blockHeader.txRootHash = bytesToBytes32(header[4].toBytes(), 1); blockHeader.receiptRootHash = bytesToBytes32(header[5].toBytes(), 1); @@ -119,6 +134,53 @@ contract Ion { addBlockHashToChain(_id, _blockHash); } + function ValidateBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { + RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); + RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); + + // Check header and signedHeader contain the same data + for (uint256 i=0; i> (i * 8); - } - return out; - } + // for (uint i = 0; i < 32; i++) { + // out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); + // } + // return out; + // } + + /* + * @description copies 32 bytes from input into the output + * @param output memory allocation for the data you need to extract + * @param input array from which the data should be extracted + * @param buf index which the data starts within the byte array needs to have 32 bytes appended + */ + function bytesToBytes32(bytes input, uint256 buf) internal pure returns (bytes32 output) { + buf = buf + 32; + assembly { + output := mload(add(input, buf)) + } + } + + /* + * @description copies output.length bytes from the input into the output + * @param output memory allocation for the data you need to extract + * @param input array from which the data should be extracted + * @param buf index which the data starts within the byte array + */ + function bytesToBytes(bytes output, bytes input, uint256 buf) constant internal { + uint256 outputLength = output.length; + buf = buf + 32; // Append 32 as we need to point past the variable type definition + assembly { + let ret := staticcall(3000, 4, add(input, buf), outputLength, add(output, 32), outputLength) + } + } } diff --git a/contracts/Validation.sol b/contracts/Validation.sol index bd9d6e5..749f221 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -107,7 +107,7 @@ contract Validation { SolUtils.BytesToBytes(extraDataSig, header, length-107); address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); - // require(m_validators[sig_addr]==true, "Signer not a validator!"); + require(m_validators[sig_addr]==true, "Signer not a validator!"); // Append the new block to the struct blockHash = _blockHash; diff --git a/test/helpers/utils.js b/test/helpers/utils.js index fbaf181..5f742bd 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -3,27 +3,41 @@ const crypto = require('crypto') -// Format required for sending bytes through eth client: -// - hex string representation -// - prefixed with 0x -const bufToStr = b => '0x' + b.toString('hex') +const utils = {}; + // Format required for sending bytes through eth client: + // - hex string representation + // - prefixed with 0x +utils.bufToStr = b => '0x' + b.toString('hex') -const gasPrice = 100000000000 // truffle fixed gas price -const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join('') -const oneFinney = web3.toWei(1, 'finney') +utils.gasPrice = 100000000000 // truffle fixed gas price +utils.joinHex = arr => '0x' + arr.map(el => el.slice(2)).join('') +utils.oneFinney = web3.toWei(1, 'finney') +utils.hexToBytes = (hex) => { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + +utils.bytesToHex = (bytes) => { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(""); +} -const sha256 = x => +utils.sha256 = x => crypto .createHash('sha256') .update(x) .digest() -const random32 = () => crypto.randomBytes(32) +utils.random32 = () => crypto.randomBytes(32) -const randomHex = () => crypto.randomBytes(32).toString('hex'); +utils.randomHex = () => crypto.randomBytes(32).toString('hex'); -const randomArr = () => { +utils.randomArr = () => { const result = [] const size =(Math.floor(Math.random() * 10) + 1); for(let i = size; 0 < i; i-- ) @@ -31,7 +45,7 @@ const randomArr = () => { return result } -const isSha256Hash = hashStr => /^0x[0-9a-f]{64}$/i.test(hashStr) +utils.isSha256Hash = hashStr => /^0x[0-9a-f]{64}$/i.test(hashStr) const newSecretHashPair = () => { const secret = random32() @@ -42,12 +56,13 @@ const newSecretHashPair = () => { } } -const sleep = ms => { +utils.sleep = ms => { return new Promise(resolve => setTimeout(resolve, ms)); } -const txGas = txReceipt => txReceipt.receipt.gasUsed * gasPrice -const txLoggedArgs = txReceipt => txReceipt.logs[0].args -const txContractId = txReceipt => txLoggedArgs(txReceipt).contractId +utils.txGas = txReceipt => txReceipt.receipt.gasUsed * gasPrice +utils.txLoggedArgs = txReceipt => txReceipt.logs[0].args +utils.txContractId = txReceipt => txLoggedArgs(txReceipt).contractId -module.exports = {bufToStr, joinHex, newSecretHashPair, oneFinney, random32, randomArr, randomHex, sha256, sleep, txGas, txLoggedArgs} +// bufToStr, joinHex, newSecretHashPair, oneFinney, random32, randomArr, randomHex, sha256, sleep, txGas, txLoggedArgs} +module.exports = utils; \ No newline at end of file diff --git a/test/ion.js b/test/ion.js index 5a38239..f6cc817 100644 --- a/test/ion.js +++ b/test/ion.js @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0+ const Web3Utils = require('web3-utils'); +const utils = require('./helpers/utils.js'); const BN = require('bignumber.js') const merkle = require('./helpers/merkle.js') const encoder = require('./helpers/encoder.js') @@ -14,7 +15,10 @@ const levelup = require('levelup'); const sha3 = require('js-sha3').keccak_256 const EP = require('eth-proof'); +// Connect to the Test RPC running const Web3 = require('web3'); +const web3 = new Web3(); +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); const Ion = artifacts.require("Ion"); const PatriciaTrie = artifacts.require("PatriciaTrie"); @@ -67,6 +71,10 @@ const TEST_NODE_VALUE = "0xf86982093f85174876e80083015f909407340652d03d131cd5737 const TEST_PATH = "0x80" const TEST_PARENT_NODES = "0xf8c3f851a0448f4ee6a987bf17a91096e25247c3d7d78dbd08afddb5cfd4186d6a9f36bbc080808080808080a0c47289442eb85e0ca1f12c5ac6168f15513036935879931655dadfad3586dcb78080808080808080f86e30b86bf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a" +const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; +const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; + + contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); @@ -79,28 +87,51 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID); + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); let chain = await ion.chains.call(0); assert.equal(chain, TESTCHAINID); // Fail adding id of this chain - await ion.RegisterChain(DEPLOYEDCHAINID).should.be.rejected; + await ion.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already registered - await ion.RegisterChain(TESTCHAINID).should.be.rejected; + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + }) + + it('Register Chain - Check Genesis Hash', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + // Successfully add id of another chain + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + let header = await ion.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); + let blockHeight = header[0]; + + assert.equal(0, blockHeight); +; }) + it('Register Chain - Check Validators', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + // Successfully add id of another chain + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + let validators = await ion.m_validators.call(TESTCHAINID, VALIDATORS[0]); + assert.equal(validators, true); + }) + it('Submit Block', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID); + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Submit block should succeed await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) - let blockHash = await ion.m_blockhashes(TESTCHAINID, 0); - let header = await ion.getBlockHeader.call(blockHash); + let blockHash = await ion.m_blockhashes(TESTCHAINID, TESTBLOCK.hash); + let header = await ion.getBlockHeader.call(TESTCHAINID, TESTBLOCK.hash); // Separate fetched header info parentHash = header[0]; @@ -108,7 +139,7 @@ contract('Ion.js', (accounts) => { receiptRootHash = header[2]; // Assert that block was persisted correctly - assert.equal(blockHash, TESTBLOCK.hash); + assert.equal(blockHash, true); assert.equal(parentHash, TESTBLOCK.parentHash); assert.equal(txRootHash, TESTBLOCK.transactionsRoot); assert.equal(receiptRootHash, TESTBLOCK.receiptsRoot); @@ -117,7 +148,7 @@ contract('Ion.js', (accounts) => { it('Fail Submit Block from unknown chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID); + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", "0xe40cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000").should.be.rejected; }) @@ -125,7 +156,7 @@ contract('Ion.js', (accounts) => { it('Fail Submit Block with wrong block hash', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID); + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, "0xe4" + "1" + "cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000").should.be.rejected; }) @@ -133,15 +164,96 @@ contract('Ion.js', (accounts) => { it('Check Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID); + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_NODE_VALUE, TEST_PARENT_NODES, TEST_PATH); }) + it('Validate Block', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; + + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; + + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + assert.equal(block.hash, signedHeaderHash); + + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + + // Submit block should succeed + const validationReceipt = await ion.ValidateBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); + const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; + assert.equal(signedHeaderHash, recoveredBlockHash); + + + + let blockHash = await ion.m_blockhashes(TESTCHAINID, block.hash); + assert.equal(blockHash, true); + + let header = await ion.getBlockHeader.call(TESTCHAINID, block.hash); + + // Separate fetched header info + parentHash = header[0]; + txRootHash = header[1]; + receiptRootHash = header[2]; + + // Assert that block was persisted correctly + assert.equal(parentHash, block.parentHash); + assert.equal(txRootHash, block.transactionsRoot); + assert.equal(receiptRootHash, block.receiptsRoot); + }) + + // it('Check EP Proofs', async () => { -// const ion = await Ion.new(DEPLOYEDCHAINID); +// const ion = await Ion.new(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH); // // // Building transactions in a block for better trie constructions // for (let i = 0; i < 10; i++) { @@ -208,7 +320,7 @@ contract('Ion.js', (accounts) => { it('Fail Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID); + await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); From 91e8dfa1c2a587107086d28013467f3cb7ab3fa7 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 25 Jul 2018 17:49:37 +0100 Subject: [PATCH 080/203] Added a description of the ValidateBlock function --- contracts/Ion.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 6478366..d5b8a74 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -134,6 +134,15 @@ contract Ion { addBlockHashToChain(_id, _blockHash); } + /* + * ValidateBlock + * param: _id (bytes32) Unique id of chain submitting block from + * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain without the signature in extraData + * param: _rlpSignedBlockHeader (bytes) RLP-encoded byte array of the block header from other chain with the signature in extraData + * + * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered + * and if valid the block is persisted as BlockHeader structs defined above. + */ function ValidateBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); From ea9eea5dbd1380c58f58c4fe1a7e2580f72af95e Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 26 Jul 2018 13:35:18 +0100 Subject: [PATCH 081/203] Added testing for nested node patricia proof verifications. Tests are done via a separate contract for standalone library testing. Removed all other redundant files. Updated some tooling files. --- contracts/PatriciaTrie.sol | 8 +- migrations/2_deploy_contracts.js | 3 +- test/PatriciaTrieTest.sol | 81 +++++++++++++++++++ test/helpers/encoder.js | 78 ------------------- test/helpers/merkle.js | 130 ------------------------------- test/helpers/trie.js | 0 test/ion.js | 36 ++++++++- test/merkle.js | 92 ---------------------- test/rinkeby.js | 128 ------------------------------ test/trie.js | 77 ------------------ tooling/__main__.py | 9 ++- tooling/trie.py | 70 +++++++++++++++++ 12 files changed, 199 insertions(+), 513 deletions(-) create mode 100644 test/PatriciaTrieTest.sol delete mode 100644 test/helpers/encoder.js delete mode 100644 test/helpers/merkle.js delete mode 100644 test/helpers/trie.js delete mode 100644 test/merkle.js delete mode 100644 test/rinkeby.js delete mode 100644 test/trie.js diff --git a/contracts/PatriciaTrie.sol b/contracts/PatriciaTrie.sol index 105cf6f..e4c3a19 100644 --- a/contracts/PatriciaTrie.sol +++ b/contracts/PatriciaTrie.sol @@ -44,7 +44,7 @@ library PatriciaTrie { processExtensionLeafNode returns (bytes32 currentNodeKey, uint traversedNibbles) Due to the dual nature of how a branch node may be processed where the next node in the path could be either - referenced by hash or nested in the branch node is the total RLP-encoded node is less than 32 bytes (vestigial node), + referenced by hash or nested in the branch node is the total RLP-encoded node is less than 32 bytes (nested node), we required separation of logic due to "stack-too-deep" issues and opted for a messy returning of reused variables. These returned variables now hold two purposes: @@ -69,8 +69,8 @@ library PatriciaTrie { bytes32 currentNodeKey; if (RLP.toBytes(nextNode).length < 32) { - //Vestigial 'Node' - (currentNodeKey, _traversedNibbles) = processVestigialNode(nextNode, _traversedNibbles, _path, _value); + //Nested 'Node' + (currentNodeKey, _traversedNibbles) = processNestedNode(nextNode, _traversedNibbles, _path, _value); } else { currentNodeKey = RLP.toBytes32(_currentNode[nextPathNibble]); } @@ -96,7 +96,7 @@ library PatriciaTrie { return (currentNodeKey, _traversedNibbles); } - function processVestigialNode(RLP.RLPItem memory _nextNode, uint _traversedNibbles, bytes memory _path, bytes _value) private returns (bytes32, uint) { + function processNestedNode(RLP.RLPItem memory _nextNode, uint _traversedNibbles, bytes memory _path, bytes _value) private returns (bytes32, uint) { RLP.RLPItem[] memory currentNode = RLP.toList(_nextNode); if (currentNode.length == 17) { // Extension Node diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 27da0d2..7afafa0 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,5 +1,6 @@ const Ion = artifacts.require("Ion"); const PatriciaTrie = artifacts.require("PatriciaTrie"); +const PatriciaTrieTest = artifacts.require("PatriciaTrieTest"); const Function = artifacts.require("Function"); const EventVerifier = artifacts.require("EventVerifier"); @@ -11,7 +12,7 @@ module.exports = async (deployer) => { eventVerifier = await deployer.deploy(EventVerifier); ion = await Ion.deployed(); eventVerifier = await EventVerifier.deployed(); - deployer.deploy(Function, ion.address, eventVerifier.address); + await deployer.deploy(Function, ion.address, eventVerifier.address); } catch(err) { console.log('ERROR on deploy:',err); diff --git a/test/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol new file mode 100644 index 0000000..498555e --- /dev/null +++ b/test/PatriciaTrieTest.sol @@ -0,0 +1,81 @@ +pragma solidity ^0.4.23; + +import "truffle/Assert.sol"; +import "truffle/DeployedAddresses.sol"; +import "../contracts/PatriciaTrie.sol"; + +contract PatriciaTrieTest { + PatriciaTrie instance; + + constructor() public { + instance = PatriciaTrie(DeployedAddresses.PatriciaTrie()); + } + + function testVerifyNestedNodes() returns (bool) { + bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; + + bytes memory path = hex"61"; + bytes memory value = hex"857465737431"; + bytes memory nodes = hex"f83bf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080"; + + Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"826162"; + value = hex"74"; + nodes = hex"f87ff839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080"; + + Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"83616263"; + value = hex"857465737433"; + nodes = hex"f87ff839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080"; + + Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"8461626564"; + value = hex"857465737435"; + nodes = hex"f8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808080"; + + Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"8461626364"; + value = hex"857465737434"; + nodes = hex"f8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808080"; + + Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + } + + function failVerifyNestedNodes() returns (bool) { + bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; + + bytes memory path = hex"62"; + bytes memory value = hex"857465737431"; + bytes memory nodes = hex"f83bf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080"; + + Assert.isFalse( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"826163"; + value = hex"75"; + nodes = hex"f87ff839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080"; + + Assert.isFalse( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"83616263"; + value = hex"857465737434"; + nodes = hex"f87ff839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080"; + + Assert.isFalse( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"8461626564"; + value = hex"857465737435"; + nodes = hex"f8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808085"; + + Assert.isFalse( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + + path = hex"8461626364"; + value = hex"857465737435"; + nodes = hex"f8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808080"; + + Assert.isFalse( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); + } +} diff --git a/test/helpers/encoder.js b/test/helpers/encoder.js deleted file mode 100644 index 188e10b..0000000 --- a/test/helpers/encoder.js +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3 = require('web3'); -const Web3Utils = require('web3-utils'); -const Web3Abi = require('web3-eth-abi'); -const rlp = require('rlp'); - -const web3 = new Web3(); - -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); - -function hexToBytes(hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; -} - -function bytesToHex(bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(""); -} - - -const block = web3.eth.getBlock(7); -console.log("\n\n\n\nBlock = " + JSON.stringify(block)) -// Decompose the values in the block to hash -const parentHash = block.parentHash; -const sha3Uncles = block.sha3Uncles; -const coinbase = block.miner; -const root = block.stateRoot; -const txHash = block.transactionsRoot; -const receiptHash = block.receiptsRoot; -const logsBloom = block.logsBloom; -const difficulty = Web3Utils.toBN(block.difficulty); -const number = Web3Utils.toBN(block.number); -const gasLimit = block.gasLimit; -const gasUsed = block.gasUsed; -const timestamp = Web3Utils.toBN(block.timestamp); -const extraData = block.extraData; -const mixHash = block.mixHash; -const nonce = block.nonce; - -// Remove last 65 Bytes of extraData -const extraBytes = hexToBytes(extraData); -const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); -const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); -const extraDataShort = '0x' + bytesToHex(extraBytesShort); - -const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraData, - mixHash, - nonce -]; - -const encodedHeader = rlp.encode(header); - -const headerHash = Web3Utils.sha3(encodedHeader); - -console.log("\n\n\nRLP-encoded header: " +bytesToHex(encodedHeader)); -console.log("\n\n\nHashed header: " +headerHash) -console.log("\n\n\nExpected hash: " +block.hash) -console.log("\n\n\n" + ((rlp.encode(parentHash)))) \ No newline at end of file diff --git a/test/helpers/merkle.js b/test/helpers/merkle.js deleted file mode 100644 index be2ded3..0000000 --- a/test/helpers/merkle.js +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3Utils = require('web3-utils'); -const BN = require('bignumber.js') - -/* -const bnjs = require('bn.js') -const bitTest = (n,b) => (new bnjs(n.toString(16),16)).testn(b) -const bitClear = (n,b) => bitTest(n,b) ? new BN((new bnjs(n.toString(16),16)).xor((new bnjs(1)).bincn(b))) : n -const bitSet = (n,b) => new BN((new bnjs(n.toString(16),16)).setn(b)) -*/ - -const toggleBit = (n,b,bitValue) => { - //b += 1 - let resStr = n.toString(2).padStart(b,'0') - const idx = resStr.length - b - resStr = resStr.substr(0,idx) + bitValue + resStr.substr(idx+1) - const bnRes = new BN(resStr,2) - return bnRes -} - - -const bitTest = (n,b) => { - //b += 1 - const resStr = n.toString(2).padStart(b,'0') - const idx = resStr.length - b - return Number(resStr[idx]) === 1 -} - - -const bitClear = (n,b) => toggleBit(n,b,'0') - - -const bitSet = (n,b) => toggleBit(n,b,'1') - - -const toHex = n => { - let nHex = n.toString(16) - if(nHex.length <= 64) - nHex = '0x' + nHex.padStart(64,'0') - else - nHex = '0x' + nHex.padStart(64*2,'0') - return nHex -} - - -const joinHex2BN = (a,b) => new BN('0x' + toHex(a) + toHex(b).substring(2)) - - -const hash = n => new BN(Web3Utils.sha3(Web3Utils.isBigNumber(n) ? toHex(n) : n)) - - -const merkleHash = n => bitClear(hash(n), 0xFF) - - -const treeLevel = items => items.reduce((prev,el, idx, arr) => { - if(idx % 2) - return prev.concat(merkleHash(joinHex2BN(arr[idx-1],el))) - return prev -} , []) - - -const createMerkle = (items) => { - const extraHash = merkleHash('merkle-tree-extra') - const leafHash = items - .map((leaf) => merkleHash(leaf)) - .sort((a,b) => (new BN(a)) - (new BN(b))) - if(leafHash.length % 2 !== 0) leafHash.push(extraHash) - const tree = [ leafHash ] - while (tree[0].length !== 1) { - const level = treeLevel(tree[0]) - if(level.length !== 1 && level.length % 2 !== 0) level.push(extraHash) //levels need to be pair - tree.unshift(level) - } - const root = tree[0]; - return [tree.sort(l => 1)].concat(root) -} - - -const pathMerkle = (leaf,tree) => { - const leafHash = merkleHash(leaf) - let idx = tree[0].findIndex(h => h.equals(leafHash)) - //console.log(tree.map(l => l.map(b=>(b||'0x0').toString(16)))) - - const result = tree - .slice(0,-1) - .reduce((path,level) => { - const hash = (idx % 2) ? level[idx-1] : bitSet(level[idx+1],0xFF) - idx = idx >> 1 // divide by 2 - return path.concat(hash) - },[]) - - return result -} - - -const proofMerkle = (leaf, path, root, hashLeaf,debug) => { - const leafHash = hashLeaf ? leaf : merkleHash(leaf) - const result = path - .reduce((prev,item) => { - const bitSide = bitTest(item, 0xFF) - const h1 = bitSide ? prev : item - const h2 = bitSide ? bitClear(item, 0xFF) : prev - const hashValue = merkleHash(joinHex2BN(h1,h2)) - if(debug) { - console.log(bitSide) - console.log(h1.toString(16).length,h2.toString(16).length, h1.toString(16),h2.toString(16)) - console.log(joinHex2BN(h1,h2).toString(16).length) - console.log(hashValue.toString(16).length,hashValue.toString(16)) - console.log('=======================================================') - } - return hashValue - }, leafHash) - return (result.equals(root)) -} - - -const merkle = { - createMerkle, - treeLevel, - hash, - merkleHash, - bitClear, - bitSet, - pathMerkle, - proofMerkle, - bitTest, -} -module.exports = merkle diff --git a/test/helpers/trie.js b/test/helpers/trie.js deleted file mode 100644 index e69de29..0000000 diff --git a/test/ion.js b/test/ion.js index 9b27624..fc9bb7f 100644 --- a/test/ion.js +++ b/test/ion.js @@ -14,6 +14,7 @@ const Web3 = require('web3'); const Ion = artifacts.require("Ion"); const PatriciaTrie = artifacts.require("PatriciaTrie"); +const PatriciaTrieTest = artifacts.require("PatriciaTrieTest"); const TriggerEventVerifier = artifacts.require("TriggerEventVerifier"); const Function = artifacts.require("Function"); @@ -305,8 +306,6 @@ contract('Ion.js', (accounts) => { assert.ok(executeEventFound, "Function did not execute"); console.log("Gas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); - - }) it('Fail Function Execution', async () => { @@ -340,6 +339,39 @@ contract('Ion.js', (accounts) => { await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_DEPLOYED_RINKEBY_ADDR).should.be.rejected; }) +// it('Verify Nested Nodes Verification', async () => { +// const patricia = await PatriciaTrieTest.new(); +// +// path = "0x8461626364"; +// value = "0x857465737434"; +// nodes = "0xf8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808080" +// rootHash = "0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c"; +// +// verified = await patricia.verifyProof.call(value, nodes, path, rootHash); +// assert.ok(verified, "Patricia proof failed."); +// }) +// +// it('Fail Nested Nodes Verification', async () => { +// const patricia = await PatriciaTrieTest.new(); +// +// path = "0x8461626364"; +// value = "0x857465737434"; +// nodes = "0xf8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808080" +// rootHash = "0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c"; +// +// // Fail with incorrect node value +// await patricia.verifyProof.call(value.slice(0,-2) + "f", nodes, path, rootHash).should.be.rejected; +// +// // Fail with incorrect RLP-encoded nodes +// await patricia.verifyProof.call(value, nodes.slice(0, -2) + "f", path, rootHash).should.be.rejected; +// +// // Fail with incorrect path +// await patricia.verifyProof.call(value, nodes, path.slice(0, -2) + "f", rootHash).should.be.rejected; +// +// // Fail with incorrect root node hash +// await patricia.verifyProof.call(value, nodes, path, rootHash.slice(0, -2) + "f").should.be.rejected; +// }) + }) async function verifyReceipts(eP, txHash) { diff --git a/test/merkle.js b/test/merkle.js deleted file mode 100644 index adc2a0a..0000000 --- a/test/merkle.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3Utils = require('web3-utils'); -const BN = require('bignumber.js') -const merkle = require('./helpers/merkle.js') - -contract('Merkle.js', () => { - it('test JS Merkle', () => { - - const testData = ["1","2","3","4","5","6","7"] - - const tree = merkle.createMerkle(testData) - - const expectedTree = [ - [ - [ - '8568612641526826488487436752726739043287191320122540356069953783894380777505', - '8763638472773768691201326883407021568462294246273894496415427229083082408032', - '19224855404247632006917173431419498680506051063941070371722880450128577361118', - '61795459977501490647348212754130855970016313872340374962921336716751708851142', - '64645341593328157176709656265449880868558868673380425455960412802858937540801', - '74330811247603495249613868516695563873247293176611122272199330092769797099053', - '78469846343542442363028680824980501212021332975324075417961003849793346933925', - '75317570447191171753008806478868650352148013528306361601609880810432714200529' - ], - [ - '6560824545851281876686151142367952893930617484325436481370811303698242675212', - '14094329272021934754728783365468382816047630355461653340632553426278198853241', - '25919299780512511508061958642305261009583198324725036212440752482930702519878', - '11791415309425995046749154607832041856871129882141188736462372751874115368248' - ], - [ - '22114525030336665972036957912787127870644756898138077124815002206627656645846', - '74561778027252859083209130121920474961655350982938755244738788717578708084930' - ], - [ - '5587813875922595628752214729735723034111050560116231646359963981668986135460' - ] - ], - '5587813875922595628752214729735723034111050560116231646359963981668986135460' - ] - - const treeStr = [tree[0].map(i => i.map(j => j.toString(10))),tree[1].toString(10)] - assert.deepEqual(treeStr,expectedTree) - - const expectedPaths = [ - [ - '19224855404247632006917173431419498680506051063941070371722880450128577361118', - '6560824545851281876686151142367952893930617484325436481370811303698242675212', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ], - [ - '104265592756520220608901552731040627315465509694716502611474276812410996610513', - '25919299780512511508061958642305261009583198324725036212440752482930702519878', - '22114525030336665972036957912787127870644756898138077124815002206627656645846' - ], - [ - '90743482286830539503240959006302832933333810038750515972785732718729991261126', - '6560824545851281876686151142367952893930617484325436481370811303698242675212', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ], - [ - '8568612641526826488487436752726739043287191320122540356069953783894380777505', - '43042351581350983610621529617640359779365126521871794350496949428256481263225', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ], - [ - '103278833556932544105506614768867540836564789343021263282063726094748079509037', - '40739437618755043902641900860004018820188626048551329746326768753852397778232', - '22114525030336665972036957912787127870644756898138077124815002206627656645846' - ], - [ - '64645341593328157176709656265449880868558868673380425455960412802858937540801', - '40739437618755043902641900860004018820188626048551329746326768753852397778232', - '22114525030336665972036957912787127870644756898138077124815002206627656645846' - ], - [ - '37711660782102817547094073135578998531779790412684035506279823231061364818016', - '43042351581350983610621529617640359779365126521871794350496949428256481263225', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ] - ] - - const path = testData.map(value => merkle.pathMerkle(value,tree[0])) - assert.deepEqual(path.map(i => i.map(j => j.toString(10))),expectedPaths, 'paths badly created') - - const proof = testData.reduce((prev,leaf,idx) => (merkle.proofMerkle(leaf,path[idx],tree[1]) && prev), true) - const negProof = testData.reduce((prev,leaf,idx) => !(merkle.proofMerkle('10',path[idx],tree[1]) && prev),true) - assert(proof && negProof,'proof failed') - }) -}) diff --git a/test/rinkeby.js b/test/rinkeby.js deleted file mode 100644 index 2b42ce5..0000000 --- a/test/rinkeby.js +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3Utils = require('web3-utils'); -const HDWalletProvider = require('truffle-hdwallet-provider'); -const mnemonic = "select they inform invite result believe equal daughter front arrest wagon miss same menu twenty"; -const addr = "0x279884e133f9346f2fad9cc158222068221b613e"; - -const rlp = require('rlp'); -const Web3 = require('web3'); -const EP = require('eth-proof'); -const deployedTrig = "0x61621bcf02914668f8404c1f860e92fc1893f74c"; -const trigAbi = [{"anonymous":false,"inputs":[{"indexed":false,"name":"caller","type":"address"}],"name":"Triggered","type":"event"},{"constant":false,"inputs":[],"name":"fire","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]; - -const TRIG_FIRED_RINKEBY_TXHASH = "0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e" -const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 - -function fireTrigger() { - web3 = new Web3(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); - trig = new web3.eth.Contract(trigAbi, deployedTrig); - - trig.methods.fire().send({from: addr}).on('transactionHash', function(hash) { console.log(hash) }); -} - -async function getTxProof() { - var eP = new EP(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); - - await eP.getTransactionTrieRoot(TRIG_FIRED_RINKEBY_TXHASH).then( (root) => { - console.log("EP TX Root hash = 0x" + root.toString('hex')) - }) - - var txValue; - var txPath; - var txParentNodes; - await eP.getTransactionProof(TRIG_FIRED_RINKEBY_TXHASH).then( (proof) => { - verified = EP.transaction(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); - - txValue = rlp.encode(proof.value); - txPath = proof.path; - txParentNodes = rlp.encode(proof.parentNodes); - }) - console.log("EP TX VALUE = 0x" + txValue.toString('hex')); - console.log("EP TX PATH = 0x" + txPath.toString('hex')); - console.log("EP TX PARENT NODES = 0x" + txParentNodes.toString('hex')); - -} - -async function getReceiptProof() { - var eP = new EP(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); - web3 = new Web3(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); -// receipt = await web3.eth.getTransactionReceipt(TRIG_FIRED_RINKEBY_TXHASH); -// console.log(receipt); - - await eP.getReceiptTrieRoot(TRIG_FIRED_RINKEBY_TXHASH).then( (root) => { - console.log("EP RECEIPT Root hash = 0x" + root.toString('hex')) - }) - - var txValue; - var txPath; - var txParentNodes; - await eP.getReceiptProof(TRIG_FIRED_RINKEBY_TXHASH).then( (proof) => { - verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); - console.log("VERIFIED: " + verified) - - txValue = rlp.encode(proof.value); - txPath = proof.path; - txParentNodes = rlp.encode(proof.parentNodes); - }) - console.log("EP RECEIPT VALUE = 0x" + txValue.toString('hex')); - console.log("EP RECEIPT PATH = 0x" + txPath.toString('hex')); - console.log("EP RECEIPT PARENT NODES = 0x" + txParentNodes.toString('hex')); - -} - -function rlpEncodeReceipt(receipt) { - let fields = [receipt.] -} - - -receipt = { blockHash: '0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7', - - blockNumber: 2657422, - - contractAddress: null, - - cumulativeGasUsed: 2435175, - - from: '0x279884e133f9346f2fad9cc158222068221b613e', - - gasUsed: 22467, - - logs: - - [ { address: '0x61621BCf02914668F8404C1f860E92fC1893F74c', - - topics: [Array], - - data: '0x000000000000000000000000279884e133f9346f2fad9cc158222068221b613e', - - blockNumber: 2657422, - - transactionHash: '0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e', - - transactionIndex: 19, - - blockHash: '0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7', - - logIndex: 25, - - removed: false, - - id: 'log_ad29b82c' } ], - - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000', - - status: true, - - to: '0x61621bcf02914668f8404c1f860e92fc1893f74c', - - transactionHash: '0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e', - - transactionIndex: 19 } - -console.log(rlpEncodeReceipt(receipt)); -//getTxProof(); -//getReceiptProof(); - -//console.log(rlp.decode("0xf902780182ab33b9010000000000020000080000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000008000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000010000000020020000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000020000010010000000000000000002000000000000000000000000000000000000000000000000000000000000000000000400000000000000000022000000000000000000000000000000f9016ef89b949edcb9a9c4d34b5d6a082c86cb4f117a1394f831f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000001b31d19b6a9a942bbf3c197ca1e5efede3ff8ff2a0000000000000000000000000e05a6d421f1375864bc6e28567993e815eefec23a00000000000000000000000000000000000000000000000004563918244f40000f8cf941b31d19b6a9a942bbf3c197ca1e5efede3ff8ff2e1a0970a6f99f3b845055cfa2283651f03abd1202ee9ececa9ca4f034161dd02457bb896000000000000000000000000e05a6d421f1375864bc6e28567993e815eefec230000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001652657761726420666f72206461696c79206c6f67696e")); diff --git a/test/trie.js b/test/trie.js deleted file mode 100644 index 0932291..0000000 --- a/test/trie.js +++ /dev/null @@ -1,77 +0,0 @@ -var Trie = require('merkle-patricia-tree') -levelup = require('levelup') -const rlp = require('rlp'); -const HDWalletProvider = require('truffle-hdwallet-provider'); -const mnemonic = "select they inform invite result believe equal daughter front arrest wagon miss same menu twenty"; - -const Web3 = require('web3'); -const EP = require('eth-proof'); -web3 = new Web3(new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/973b00227ca84ced8266b2ab6d7592cb')); - -function processLogs(logs) { - var rlpLogs = []; - for (var i = 0; i < logs.length; i++) { - var address = Buffer.from(logs[i].address.slice(2), 'hex') - var topics = logs[i].topics.map(topic => Buffer.from(topic.slice(2), 'hex')) - var data = Buffer.from(logs[i].data.slice(2), 'hex') - rlpLogs.push([address, topics, data]); - } - return rlpLogs; -} - -async function getReceipt(txHash) { - receipt = await web3.eth.getTransactionReceipt(txHash); - - var cummulativeGas = Buffer.from(receipt.cumulativeGasUsed.toString('16'), 'hex') - var bloomFilter = Buffer.from(receipt.logsBloom.slice(2), 'hex') - var setOfLogs = processLogs(receipt.logs); - - if (receipt.status !== undefined && receipt.status != null){ - var status = receipt.status ? Buffer.from('01', 'hex') : Buffer.from('00', 'hex'); - var rawReceipt = rlp.encode([status,cummulativeGas,bloomFilter,setOfLogs]); - return rawReceipt; - } else { - var postTransactionState = strToBuf(receipt.root) - var rawReceipt = rlp.encode([postTransactionState, cummulativeGas,bloomFilter,setOfLogs]) - return rawReceipt; - } -} - -async function addReceiptToTrie(trie, txHash, prevTrieRoot) { - console.log("Inserting receipt for hash: " + txHash); - receipt = await getReceipt(txHash); - console.log("RECEIPT RLP:" + receipt.toString('hex')) - - tx = await web3.eth.getTransaction(txHash); - path = rlp.encode(tx.transactionIndex); - console.log("Key: " + path.toString('hex')); - - console.log(trie.root) - console.log(prevTrieRoot) - do { - await trie.put(path, receipt, (error) => {console.log("ERROR:" + error)}); - } while (trie.root == prevTrieRoot) -} - -async function generateReceiptProof(block) { - block = await web3.eth.getBlock(block); - - txs = block.transactions; - - var trie = new Trie(); - var lastTrieRoot = "" - for (let i = 0; i < 2; i++) { - await addReceiptToTrie(trie, txs[i], lastTrieRoot); - lastTrieRoot = trie.root; - } -} - -//generateReceiptProof("0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7"); - -let root = Buffer.from("f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080", 'hex') -let second = Buffer.from("f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e", 'hex') -let leaf = Buffer.from("f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080", 'hex') - -nodes = rlp.encode([root, second, leaf]); - -console.log(nodes.toString('hex')) \ No newline at end of file diff --git a/tooling/__main__.py b/tooling/__main__.py index b65e517..ccaebd0 100644 --- a/tooling/__main__.py +++ b/tooling/__main__.py @@ -1,4 +1,11 @@ -from .ion import commands +import click + +from .encoder import commands as encoder_commands +from .trie import commands as trie_commands + +commands = click.Group('commands') +commands.add_command(encoder_commands, 'encoder') +commands.add_command(trie_commands, 'trie') if __name__ == "__main__": commands.main() \ No newline at end of file diff --git a/tooling/trie.py b/tooling/trie.py index e69de29..1f62c1e 100644 --- a/tooling/trie.py +++ b/tooling/trie.py @@ -0,0 +1,70 @@ +from patricia import trie +import rlp +from .ethrpc import EthJsonRpc +from ethereum.utils import sha3 +from ethereum.transactions import Transaction + +import click + + +class Trie(object): + def __init__(self, host, port, tls=False): + self.rpc = EthJsonRpc(host, port, tls) + + def construct_tx_trie_from_block(self, n): + try: + n = int(n) + block = self.rpc.eth_getBlockByNumber(n) + except ValueError: + block = self.rpc.eth_getBlockByNumber() + + transactions = block['transactions'] + + for tx in transactions: + print(tx) + print(rlp.encode(tx['transactionIndex'])) + tx_data = [tx['nonce'], tx['gasPrice'], tx['gas'], tx['to'], tx['value'], tx['input']] + print(rlp.encode(tx_data)) + + def get_tx_root(self, n): + try: + n = int(n) + block = self.rpc.eth_getBlockByNumber(n) + except ValueError: + block = self.rpc.eth_getBlockByNumber() + + return block['transactionsRoot'] + +def instantiate_trie(rpc_host, rpc_port): + if rpc_port == 443: + t = Trie(rpc_host, rpc_port, True) + else: + t = Trie(rpc_host, rpc_port) + + return t + +@click.command(help="Returns a list of transaction hashes from a specified block") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.option('--number', nargs=1, default="LATEST", type=str) +def construct_tx_trie(rpc_host, rpc_port, number): + t = instantiate_trie(rpc_host, rpc_port) + + t.construct_tx_trie_from_block(number) + +@click.command(help="Returns TxTrie root of a specified block") +@click.argument('rpc-host', nargs=1, type=str) +@click.argument('rpc-port', nargs=1, type=int) +@click.option('--number', nargs=1, default="LATEST", type=str) +def get_tx_root(rpc_host, rpc_port, number): + t = instantiate_trie(rpc_host, rpc_port) + + root = t.get_tx_root(number) + click.echo(root) + +commands = click.Group('commands') +commands.add_command(construct_tx_trie, "tx") +commands.add_command(get_tx_root, "txroot") + +if __name__ == "__main__": + commands.main() From 35d6b9fc89fc8dc414a33b62192b7b2f3ab63f7b Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 26 Jul 2018 16:32:18 +0100 Subject: [PATCH 082/203] Tests work with updated ion --- contracts/Ion.sol | 30 +- contracts/Validation.sol | 239 ++++--- contracts/libraries/PatriciaTrie.sol | 2 + migrations/2_deploy_contracts.js | 2 +- test/ion.js | 296 ++++----- test/validation.js | 949 +++++++++++++++------------ 6 files changed, 773 insertions(+), 745 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index c5ec0b6..9c872d0 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -26,7 +26,6 @@ contract Ion { uint256 public blockHeight; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; - // XXX: @shirikatsu this has changed from bytes32 to uint256 to allow block ordering mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; // input chainId to validators address returning bool @@ -116,36 +115,13 @@ contract Ion { /* * SubmitBlock * param: _id (bytes32) Unique id of chain submitting block from - * param: _blockHash (bytes32) Block hash of block being submitted - * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain - * - * Submission of block headers from another chain, deconstructed and persisted as BlockHeader structs defined above - * and adds it to the list of known block hashes and headers of specified chain. - */ - function SubmitBlock(bytes32 _id, bytes32 _blockHash, bytes _rlpBlockHeader) onlyRegisteredChains(_id) public { - RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); - - bytes32 hashedHeader = keccak256(_rlpBlockHeader); - require( hashedHeader == _blockHash ); - - BlockHeader storage blockHeader = m_blockheaders[_id][_blockHash]; - blockHeader.prevBlockHash = bytesToBytes32(header[0].toBytes(), 1); - blockHeader.txRootHash = bytesToBytes32(header[4].toBytes(), 1); - blockHeader.receiptRootHash = bytesToBytes32(header[5].toBytes(), 1); - - addBlockHashToChain(_id, _blockHash); - } - - /* - * ValidateBlock - * param: _id (bytes32) Unique id of chain submitting block from * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain without the signature in extraData * param: _rlpSignedBlockHeader (bytes) RLP-encoded byte array of the block header from other chain with the signature in extraData * * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered * and if valid the block is persisted as BlockHeader structs defined above. */ - function ValidateBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { + function SubmitBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); @@ -187,7 +163,7 @@ contract Ion { // Recover the signature of address sigAddr = ECVerify.ecrecovery(keccak256(_rlpBlockHeader), extraDataSig); - // require(m_validators[_id][sigAddr]==true, "Signer not a validator!"); + require(m_validators[_id][sigAddr]==true, "Signer not a validator!"); emit broadcastSignature(sigAddr); } @@ -337,7 +313,7 @@ contract Ion { } } - /* + /* * @description copies output.length bytes from the input into the output * @param output memory allocation for the data you need to extract * @param input array from which the data should be extracted diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 749f221..0f4cd7f 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -3,152 +3,139 @@ pragma solidity ^0.4.23; import "./libraries/ECVerify.sol"; +import "./libraries/RLP.sol"; import "./libraries/SolidityUtils.sol"; contract Validation { - address owner; - address[] validators; + using RLP for RLP.RLPItem; + using RLP for RLP.Iterator; + using RLP for bytes; - uint256 blockHeight; - bytes32 blockHash; + address public owner; + bytes32 public chainId; + /* + * @description persists the last submitted block of a chain being validated + */ struct BlockHeader { - bytes32 blockHash; + uint256 blockHeight; + bytes32 latestHash; bytes32 prevBlockHash; } - mapping (uint256 => BlockHeader) public m_blockheaders; - mapping (address => bool) m_validators; + mapping (bytes32 => uint256) public blockHeight; + mapping (bytes32 => bool) public chains; + mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; + mapping (bytes32 => BlockHeader) public m_blockheaders; + mapping (bytes32 => mapping (address => bool)) public m_validators; - event broadcastSig(address owner); + event broadcastSignature(address signer); event broadcastHash(bytes32 blockHash); /* - * @param _validators list of validators at block 0 - * @param _genesisHash genesis block hash + * @param _id genesis block of the blockchain where the contract is deployed */ - constructor (address[] _validators, bytes32 genesisHash) public { + constructor (bytes32 _id) public { owner = msg.sender; - for (uint i = 0; i < _validators.length; i++) { - validators.push(_validators[i]); - m_validators[_validators[i]] = true; - } - - blockHash = genesisHash; - m_blockheaders[0].blockHash = genesisHash; - + chainId = _id; } - /* - * @description returns the validators array - */ - function GetValidators() public view returns (address[] _validators) { - return validators; - } - - /* - * @description returns the latest block submitted - */ - function LatestBlock() public view returns (bytes32 _latestBlock) { - return blockHash; - } - - /* - * @description returns information regarding specific block - * @param blockNumber specific block number - */ - function GetBlock(uint256 blockNumber) public view returns (bytes32 _blockHash, bytes32 _prevBlockHash, uint256 _blockHeight) { - _blockHash = m_blockheaders[blockNumber].blockHash; - _prevBlockHash = m_blockheaders[blockNumber].prevBlockHash; - _blockHeight = blockHeight; - } - - /* - * @param header header rlp encoded, with extraData signatures removed - * @param prefixHeader the new prefix for the signed hash header - * @param prefixExtraData the new prefix for the extraData field - */ - function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public { - // Check the parent hash is the same as the previous block submitted - bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header, 4); - require(_parentBlockHash==blockHash, "Not child of previous block!"); - - uint256 length = header.length; - bytes32 _blockHash = keccak256(header); - emit broadcastHash(_blockHash); - - bytes memory headerStart = new bytes(length - 141); - bytes memory extraData = new bytes(31); - bytes memory extraDataSig = new bytes(65); - bytes memory headerEnd = new bytes(42); - - // Extract the start of the header and replace the length - SolUtils.BytesToBytes(headerStart, header, 0); - assembly { - let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) - } - - // Extract the real extra data and create the signed hash - SolUtils.BytesToBytes(extraData, header, length-140); - assembly { - let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) - } - - // Extract the end of the header - SolUtils.BytesToBytes(headerEnd, header, length-42); - bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); - - // emit broadcastHash2(newHeader); - - bytes32 hashData = keccak256(newHeader); - - // Extract the signature of the hash create above - SolUtils.BytesToBytes(extraDataSig, header, length-107); - - address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); - require(m_validators[sig_addr]==true, "Signer not a validator!"); - - // Append the new block to the struct - blockHash = _blockHash; - blockHeight++; - m_blockheaders[blockHeight].blockHash = _blockHash; - m_blockheaders[blockHeight].prevBlockHash = _parentBlockHash; - - emit broadcastSig(sig_addr); - - } + /* + * InitChain + * param: chainId (bytes32) Unique id of another chain to interoperate with + * + * Supplied with an id of another chain, checks if this id already exists in the known set of ids + * and adds it to the list of known chains. + */ + function InitChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { + require( _id != chainId, "Cannot add this chain id to chain register" ); + require(!chains[_id], "Chain already exists" ); + chains[_id] = true; + + // Append validators + for (uint256 i = 0; i < _validators.length; i++) { + m_validators[_id][_validators[i]] = true; + } + // m_blockhashes[_id][_genesisHash] = true; + m_blockheaders[_id].blockHeight = 0; + m_blockheaders[_id].latestHash = _genesisHash; + } /* - * @description creates header from the original against which the signatures are recovered - * @param headerStart all block header fields until extraData field - * @param extraData extraData field minus signatures - * @param headerEnd all block header fields post extraData field - */ - function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { - // Get the lengths sorted because they're needed later... - uint256 headerStartLength = headerStart.length; - uint256 extraDataLength = extraData.length; - uint256 extraDataStart = headerStartLength + 32; - uint256 headerEndLength = headerEnd.length; - uint256 headerEndStart = extraDataLength + headerStartLength + 32 + 2; - uint256 newLength = headerStartLength + extraDataLength + headerEndLength + 2; // extra two is for the prefix - bytes memory header = new bytes(newLength); - - - // Add in the first part of the header - assembly { - let ret := staticcall(3000, 4, add(headerStart, 32), headerStartLength, add(header, 32), headerStartLength) - } - assembly { - let ret := staticcall(3000, 4, add(extraData, 32), extraDataLength, add(header, extraDataStart), extraDataLength) - } - assembly { - let ret := staticcall(3000, 4, add(headerEnd, 32), headerEndLength, add(header, headerEndStart), headerEndLength) - } - - output = header; - } + * ValidateBlock + * param: _id (bytes32) Unique id of chain submitting block from + * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain without the signature in extraData + * param: _rlpSignedBlockHeader (bytes) RLP-encoded byte array of the block header from other chain with the signature in extraData + * + * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered + * and if valid the block is persisted as BlockHeader structs defined above. + */ + function ValidateBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { + RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); + RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); + + // Check header and signedHeader contain the same data + for (uint256 i=0; i { // <<<<<<< HEAD deployer.deploy(Recover) .then(() => Recover.deployed) - .then(() => deployer.deploy(Validation, ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"], "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) + .then(() => deployer.deploy(Validation, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) .then(() => Validation.deployed) .then(() => deployer.deploy(PatriciaTrie)) .then(() => PatriciaTrie.deployed) diff --git a/test/ion.js b/test/ion.js index c9dde2e..b0d7ea2 100644 --- a/test/ion.js +++ b/test/ion.js @@ -30,44 +30,9 @@ const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" /* -MAIN NET TEST DATA -*/ - -//const TESTBLOCK = { -// difficulty: 12549329517745, -// extraData: "0xd783010303844765746887676f312e352e31856c696e7578", -// gasLimit: 3141592, -// gasUsed: 63000, -// hash: "0x95c3a05973fec7bf98f1131a72e607b4eba171d0576571cf83ee7162bbcdb7d9", -// logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -// miner: "0x95581ea0c5b362933f3523138f54d51eae817211", -// mixHash: "0xa01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6", -// nonce: "0x1c080c4ec6f2553b", -// number: 1000002, -// parentHash: "0xcb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4f", -// receiptsRoot: "0x97097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647", -// sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", -// size: 883, -// stateRoot: "0x643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5", -// timestamp: 1455404078, -// totalDifficulty: 7135227569124568698, -// transactions: ["0x2bd653c639c086ad1c6e468d2cbdba76fc144f747373be6d2db7854d0d0e36e7", "0x7e3abff232dd5fc72db441807bcd59d9f17311a960a8f6ff6d0e693c22fa1eb2", "0x07a911c87c6e656e2f83c30e0cbdac47789fd874c747337ad1776b7dd5238893"], -// transactionsRoot: "0xdbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2", -// uncles: [] -//} -// -//const TESTRLPENCODING = "0xf90217a0cb5cab7266694daa0d28cbf40496c08dd30bf732c41e0455e7ad389c10d79f4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495581ea0c5b362933f3523138f54d51eae817211a0643430d1afc3f02ce5249e4ba5979fb8601b1907a5923a4a74d36d66321a27e5a0dbdf7457111e50e435853974d5412c2151fde6e3c2e3f5aecc253aa4cb21fce2a097097902b6b4d6b695ef16b923e33b8780d95cf4bd54540ac450deb019d07647b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000860b69de53fcb1830f4242832fefd882f6188456bfb42e98d783010303844765746887676f312e352e31856c696e7578a0a01f9d00ac510a726f883459834e30cfe085f47b04e22f72207f5a9e9d652ca6881c080c4ec6f2553b" -//const TEST_PATH = "0x02" -// -//const TEST_TX_VALUE = "0xf8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" -//const TEST_TX_NODES = "0xf9011df851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084" -// -//const TEST_RECEIPT_VALUE = "0xf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" -//const TEST_RECEIPT_NODES = "0xf901d8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" - -/* -RINKEBY TEST DATA +TESTRPC TEST DATA */ +const block = web3.eth.getBlock(1); const TESTBLOCK = { difficulty: 2, @@ -118,6 +83,58 @@ const TESTBLOCK = { uncles: [] } +const TEST_VALIDATORS = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"] + +const signedHeader = [ + TESTBLOCK.parentHash, + TESTBLOCK.sha3Uncles, + TESTBLOCK.miner, + TESTBLOCK.stateRoot, + TESTBLOCK.transactionsRoot, + TESTBLOCK.receiptsRoot, + TESTBLOCK.logsBloom, + Web3Utils.toBN(TESTBLOCK.difficulty), + Web3Utils.toBN(TESTBLOCK.number), + TESTBLOCK.gasLimit, + TESTBLOCK.gasUsed, + Web3Utils.toBN(TESTBLOCK.timestamp), + TESTBLOCK.extraData, + TESTBLOCK.mixHash, + TESTBLOCK.nonce + ]; + + +// Remove last 65 Bytes of extraData +const extraBytes = utils.hexToBytes(TESTBLOCK.extraData); +const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); +const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + +const unsignedHeader = [ + TESTBLOCK.parentHash, + TESTBLOCK.sha3Uncles, + TESTBLOCK.miner, + TESTBLOCK.stateRoot, + TESTBLOCK.transactionsRoot, + TESTBLOCK.receiptsRoot, + TESTBLOCK.logsBloom, + Web3Utils.toBN(TESTBLOCK.difficulty), + Web3Utils.toBN(TESTBLOCK.number), + TESTBLOCK.gasLimit, + TESTBLOCK.gasUsed, + Web3Utils.toBN(TESTBLOCK.timestamp), + extraDataShort, // extraData minus the signature + TESTBLOCK.mixHash, + TESTBLOCK.nonce + ]; + +const TEST_SIGNED_HEADER = '0x' + rlp.encode(signedHeader).toString('hex'); +const signedHeaderHash = Web3Utils.sha3(TEST_SIGNED_HEADER); +// assert.equal(TESTBLOCK.hash, signedHeaderHash); + +const TEST_UNSIGNED_HEADER = '0x' + rlp.encode(unsignedHeader).toString('hex'); +const unsignedHeaderHash = Web3Utils.sha3(TEST_UNSIGNED_HEADER); + const TESTRLPENCODING = "0xf9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" const TEST_PATH = "0x13" @@ -133,7 +150,8 @@ const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 const TRIG_CALLED_BY = "0x279884e133f9346f2fad9cc158222068221b613e"; const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; -const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; +const GENESIS_HASH = TESTBLOCK.parentHash; +// const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; contract('Ion.js', (accounts) => { @@ -148,23 +166,23 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); let chain = await ion.chains.call(0); assert.equal(chain, TESTCHAINID); // Fail adding id of this chain - await ion.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await ion.RegisterChain(DEPLOYEDCHAINID, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already registered - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; }) it('Register Chain - Check Genesis Hash', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); let header = await ion.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); let blockHeight = header[0]; @@ -177,23 +195,49 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - let validators = await ion.m_validators.call(TESTCHAINID, VALIDATORS[0]); + let validators = await ion.m_validators.call(TESTCHAINID, TEST_VALIDATORS[0]); assert.equal(validators, true); }) + // it('Submit Block', async () => { + // const ion = await Ion.new(DEPLOYEDCHAINID); + + // await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // // Submit block should succeed + // let tx = await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) + + // console.log("Gas used to submit block header = " + tx.receipt.gasUsed.toString() + " gas"); + + // let blockHash = await ion.m_blockhashes(TESTCHAINID, TESTBLOCK.hash); + // let header = await ion.getBlockHeader.call(TESTCHAINID, TESTBLOCK.hash); + + // // Separate fetched header info + // parentHash = header[0]; + // txRootHash = header[1]; + // receiptRootHash = header[2]; + + // // Assert that block was persisted correctly + // assert.equal(blockHash, true); + // assert.equal(parentHash, TESTBLOCK.parentHash); + // assert.equal(txRootHash, TESTBLOCK.transactionsRoot); + // assert.equal(receiptRootHash, TESTBLOCK.receiptsRoot); + // }) + it('Submit Block', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); // Submit block should succeed - let tx = await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) - - console.log("Gas used to submit block header = " + tx.receipt.gasUsed.toString() + " gas"); + const validationReceipt = await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; let blockHash = await ion.m_blockhashes(TESTCHAINID, TESTBLOCK.hash); + assert.equal(blockHash, true); + let header = await ion.getBlockHeader.call(TESTCHAINID, TESTBLOCK.hash); // Separate fetched header info @@ -202,7 +246,6 @@ contract('Ion.js', (accounts) => { receiptRootHash = header[2]; // Assert that block was persisted correctly - assert.equal(blockHash, true); assert.equal(parentHash, TESTBLOCK.parentHash); assert.equal(txRootHash, TESTBLOCK.transactionsRoot); assert.equal(receiptRootHash, TESTBLOCK.receiptsRoot); @@ -211,117 +254,58 @@ contract('Ion.js', (accounts) => { it('Fail Submit Block from unknown chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", "0xe40cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000").should.be.rejected; + await ion.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; }) - it('Fail Submit Block with wrong block hash', async () => { + it('Fail Submit Block with wrong unsigned header', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - await ion.SubmitBlock(TESTCHAINID, "0xe4" + "1" + "cd510f5e415980a2a18ab97b1983c7da43ee56b299cf931c35d9c9ce435f2", "0xf9025ea0f4d7435eff2fcff295eca2c97a1299eeb1d2ce479b4c6e0e799f4a7bed6e4f72a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019ac400db348a4975008c6e75c537bce261d116bcd74d8b75a9d6992e3b161eda087c9f55218d8784fa39a773791633e9d007a99bef43c12233ebf980810d47464a05ad439bb61e71db83d139847424ac55990546a1b55cc5dd12a57850fd47af845b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281d2880d08334ef5308dff826928845b23c06eb861d88301080b846765746888676f312e31302e32856c696e757800000000000000461bc1df80fdafba4508e41ef01a570b7998fa0c64eaae65d62e57929afc232a0656a0a43e10387ffebcc8837d1c0d28ab801313e18775f574e73f119452b42e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000").should.be.rejected; + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + + const incorrectHeader = [ + TESTBLOCK.parentHash, + TESTBLOCK.sha3Uncles, + TESTBLOCK.miner, + TESTBLOCK.stateRoot, + TESTBLOCK.transactionsRoot, + TESTBLOCK.receiptsRoot.slice(0, -2) + "fa", + TESTBLOCK.logsBloom, + Web3Utils.toBN(TESTBLOCK.difficulty), + Web3Utils.toBN(TESTBLOCK.number), + TESTBLOCK.gasLimit, + TESTBLOCK.gasUsed, + Web3Utils.toBN(TESTBLOCK.timestamp), + extraDataShort, // extraData minus the signature + TESTBLOCK.mixHash, + TESTBLOCK.nonce + ]; + + + const TEST_INCORRECT_UNSIGNED_HEADER = '0x' + rlp.encode(incorrectHeader).toString('hex'); + + await ion.SubmitBlock(TESTCHAINID, TEST_INCORRECT_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; }) it('Check Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); - console.log("Gas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); - }) - - it('Validate Block', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - const signedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; - - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); - assert.equal(block.hash, signedHeaderHash); - - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); - - // Submit block should succeed - const validationReceipt = await ion.ValidateBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); - const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; - assert.equal(signedHeaderHash, recoveredBlockHash); - - - - let blockHash = await ion.m_blockhashes(TESTCHAINID, block.hash); - assert.equal(blockHash, true); - - let header = await ion.getBlockHeader.call(TESTCHAINID, block.hash); - - // Separate fetched header info - parentHash = header[0]; - txRootHash = header[1]; - receiptRootHash = header[2]; - - // Assert that block was persisted correctly - assert.equal(parentHash, block.parentHash); - assert.equal(txRootHash, block.transactionsRoot); - assert.equal(receiptRootHash, block.receiptsRoot); + console.log("\tGas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); }) it('Fail Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); // Fail with wrong chain ID await ion.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; @@ -336,22 +320,22 @@ contract('Ion.js', (accounts) => { it('Check Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); nodes = generateTestReceiptRLPNodes(); let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, "0x"+nodes.toString('hex'), TEST_PATH); - console.log("Gas used to submit check receipt proof = " + tx.receipt.gasUsed.toString() + " gas"); + console.log("\tGas used to submit check receipt proof = " + tx.receipt.gasUsed.toString() + " gas"); }) it('Fail Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); // Fail with wrong chain ID await ion.CheckReceiptProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; @@ -366,21 +350,21 @@ contract('Ion.js', (accounts) => { it('Check Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); let tx = await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); - console.log("Gas used to submit check roots proof = " + tx.receipt.gasUsed.toString() + " gas"); + console.log("\tGas used to submit check roots proof = " + tx.receipt.gasUsed.toString() + " gas"); }) it('Fail Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); // Fail with wrong chain ID await ion.CheckRootsProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected @@ -407,15 +391,16 @@ contract('Ion.js', (accounts) => { const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); executeEventFound = tx.logs.some(l => { return l.event == "Executed" }); assert.ok(executeEventFound, "Function did not execute"); - console.log("Gas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); + console.log("\tGas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); }) @@ -426,8 +411,9 @@ contract('Ion.js', (accounts) => { const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion - await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + + await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); // Fail with wrong chain ID await functionContract.verifyAndExecute(DEPLOYEDCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; diff --git a/test/validation.js b/test/validation.js index 13599a8..20587c0 100644 --- a/test/validation.js +++ b/test/validation.js @@ -1,7 +1,8 @@ // Copyright (c) 2016-2018 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ -const Util = require('ethereumjs-util'); +const eth_util = require('ethereumjs-util'); +const utils = require('./helpers/utils.js'); const Web3 = require('web3'); const Web3Utils = require('web3-utils'); const Web3Abi = require('web3-eth-abi'); @@ -15,36 +16,21 @@ const web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); -function hexToBytes(hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; -} - -function bytesToHex(bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(""); -} - - // Takes a header and private key returning the signed data // Needs extraData just to be sure of the final byte signHeader = (headerHash, privateKey, extraData) => { - const sig = Util.ecsign(headerHash, privateKey) + const sig = eth_util.ecsign(headerHash, privateKey) if (this._chainId > 0) { sig.v += this._chainId * 2 + 8 } - const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); - const addrBuf = Util.pubToAddress(pubKey); + const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = eth_util.pubToAddress(pubKey); const newSigBytes = Buffer.concat([sig.r, sig.s]); let newSig; - const bytes = hexToBytes(extraData) + const bytes = utils.hexToBytes(extraData) const finalByte = bytes.splice(bytes.length-1) if (finalByte.toString('hex')=="0") { newSig = newSigBytes.toString('hex') + '00'; @@ -56,7 +42,10 @@ signHeader = (headerHash, privateKey, extraData) => { return newSig; } - +const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" +const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" +const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; +const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; contract('Validation.js', (accounts) => { @@ -74,433 +63,521 @@ contract('Validation.js', (accounts) => { // Find the validator of block 1 as it is not known a priori const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; - it('Test: GetValidators()', async () => { - const validation = await Validation.new(validators, genHash); - const accounts = web3.eth.accounts; - const signer = validators[0]; + it('Test: Deploy Contract', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + let chainId = await validation.chainId(); - const validatorsReceipt = await validation.GetValidators(); - assert.equal(validators[0], validatorsReceipt[0]) + assert.equal(chainId, DEPLOYEDCHAINID); }) - // This test takes a block and makes no changes to the block and submits it to the contract - it('Test: Authentic Submission Happy Path - ValidateBlock()', async () => { - const validation = await Validation.new(validators, genHash); - const accounts = web3.eth.accounts; - const signer = validators[0]; - - // Get a single block - const block = web3.eth.getBlock(blockNum); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; + it('Test: Initialise Chain', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); - // Remove last 65 Bytes of extraData - const extraBytes = hexToBytes(extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - const blockHeader = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraData, - mixHash, - nonce - ]; - - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - const encodedBlockHeader = '0x' + rlp.encode(blockHeader).toString('hex'); - const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - assert.equal(block.hash, blockHeaderHash); - - const encodedHeader = '0x' + rlp.encode(header).toString('hex'); - const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); - const headerHash = Web3Utils.sha3(encodedHeader); + // Successfully add id of another chain + await validation.InitChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + let chain = await validation.chains(TESTCHAINID); - // Get Prefixes - const prefixHeader = '0x' + encodedHeader.substring(4, 8); - const prefixExtraData = '0x' + encodedExtraData.substring(2,4); + assert.equal(chain, true); - const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); - const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; - const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; - assert.equal(block.hash, recoveredBlockHash) - assert.notEqual(validators.indexOf(recoveredSignature), -1); + // Fail adding id of this chain + await validation.InitChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + // Fail adding id of chain already initialised + await validation.InitChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; }) - // Here the block header is signed off chain but by a whitelisted validator - it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { - const validation = await Validation.new(validators, genHash); - const accounts = web3.eth.accounts; - const signer = validators[0]; - - // Get a single block - const block = web3.eth.getBlock(blockNum); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - // Create new signed hash - const extraBytes = hexToBytes(extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - // Make some changes to the block - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - // Encode and sign the new header - const encodedHeader = '0x' + rlp.encode(header).toString('hex'); - const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); - const headerHash = Util.sha3(encodedHeader); - - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - - let signature = await signHeader(headerHash, privateKey, extraData); - - // Append signature to the end of extraData - const sigBytes = hexToBytes(signature.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + bytesToHex(newExtraDataBytes); - assert.equal(extraDataSignature, '0x'+signature.toString('hex')) - - const newBlockHeader = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - newExtraData, - mixHash, - nonce - ]; - - const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); - const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - assert.equal(block.hash, blockHeaderHash); - - // Get Prefixes - const prefixHeader = '0x' + encodedHeader.substring(4, 8); - const prefixExtraData = '0x' + encodedExtraData.substring(2,4); - - const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); - const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; - const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; - assert.equal(block.hash, recoveredBlockHash) - assert.equal(recoveredSignature, signer); - }) + it('Validate Block', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + await validation.InitChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; - it('Test: Inauthentic Block Submission - ValidateBlock()', async () => { - const validation = await Validation.new(validators, genHash); - const accounts = web3.eth.accounts; - const signer = validators[0]; - - // Get a single block - const block = web3.eth.getBlock(blockNum); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - // Create new signed hash - const extraBytes = hexToBytes(extraData); + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - // Make some changes to the block - const newTxHash = Web3Utils.sha3("Test Data"); - // console.log(txHash, newTxHash); - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - // txHash, - newTxHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - // Encode and sign the new header - const encodedHeader = '0x' + rlp.encode(header).toString('hex'); - const headerHash = Util.sha3(encodedHeader); - - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - - const sig = Util.ecsign(headerHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); - const addrBuf = Util.pubToAddress(pubKey); - assert.equal(signer, '0x'+addrBuf.toString('hex')); - - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig; - - // Need to understand why but signature requires different v than in others to recover correctly - if (sig.v=="27") { - newSig = newSigBytes.toString('hex') + '00'; - } - if (sig.v=="28") { - newSig = newSigBytes.toString('hex') + '01'; - } - - // Append signature to the end of extraData - const sigBytes = hexToBytes(newSig.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + bytesToHex(newExtraDataBytes); - - const newBlockHeader = [ - parentHash, - sha3Uncles, - coinbase, - root, - // txHash, - newTxHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - newExtraData, - mixHash, - nonce - ]; - - const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); - const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); - const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - - // Get Prefixes - const prefixHeader = '0x' + encodedHeader.substring(4, 8); - const prefixExtraData = '0x' + encodedExtraData.substring(2,4); - - const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); - const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; - const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; - assert.equal(recoveredBlockHash, blockHeaderHash); - assert.equal(recoveredSignature, signer); - + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; + + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + assert.equal(block.hash, signedHeaderHash); + + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + + // Submit block should succeed + const validationReceipt = await validation.ValidateBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); + const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; + assert.equal(signedHeaderHash, recoveredBlockHash); + + let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); + assert.equal(blockHash, true); + + let header = await validation.m_blockheaders(TESTCHAINID); + + // Separate fetched header info + parentHash = header[2]; + + // Assert that block was persisted correctly + assert.equal(parentHash, block.parentHash); }) - it('Test: Authentic Block Unkown Validator Submission - ValidateBlock()', async () => { - const validation = await Validation.new(validators, genHash); - const accounts = web3.eth.accounts; - const signer = validators[1]; - - // Get a single block - const block = web3.eth.getBlock(blockNum); - - // Decompose the values in the block to hash - const parentHash = block.parentHash; - const sha3Uncles = block.sha3Uncles; - const coinbase = block.miner; - const root = block.stateRoot; - const txHash = block.transactionsRoot; - const receiptHash = block.receiptsRoot; - const logsBloom = block.logsBloom; - const difficulty = Web3Utils.toBN(block.difficulty); - const number = Web3Utils.toBN(block.number); - const gasLimit = block.gasLimit; - const gasUsed = block.gasUsed; - const timestamp = Web3Utils.toBN(block.timestamp); - const extraData = block.extraData; - const mixHash = block.mixHash; - const nonce = block.nonce; - - // Create new signed hash - const extraBytes = hexToBytes(extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + bytesToHex(extraBytesShort); - - // Make some changes to the block - const newTxHash = Web3Utils.sha3("Test Data"); - const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - newTxHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraDataShort, - mixHash, - nonce - ]; - - // Encode and sign the new header - const encodedHeader = '0x' + rlp.encode(header).toString('hex'); - const headerHash = Util.sha3(encodedHeader); - - const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') - - const sig = Util.ecsign(headerHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = Util.ecrecover(headerHash, sig.v, sig.r, sig.s); - const addrBuf = Util.pubToAddress(pubKey); - const addr = Util.bufferToHex(addrBuf); - - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig; - - const bytes = hexToBytes(extraData) - const finalByte = bytes.splice(bytes.length-1) - if (finalByte.toString('hex')=="00") - newSig = newSigBytes.toString('hex') + '00'; - else (finalByte.toString('hex')=="01") - newSig = newSigBytes.toString('hex') + '01'; - - // Append signature to the end of extraData - const sigBytes = hexToBytes(newSig.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + bytesToHex(newExtraDataBytes); - - const newBlockHeader = [ - parentHash, - sha3Uncles, - coinbase, - root, - newTxHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - newExtraData, - mixHash, - nonce - ]; - - const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); - const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); - const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - - // Get Prefixes - const prefixHeader = '0x' + encodedHeader.substring(4, 8); - const prefixExtraData = '0x' + encodedExtraData.substring(2,4); - - try { - const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); - } catch (err) { - assert.isDefined(err, "transaction should have thrown"); - } - }) + // This test takes a block and makes no changes to the block and submits it to the contract +// it('Test: Authentic Submission Happy Path - ValidateBlock()', async () => { +// const validation = await Validation.new(validators, genHash); +// const accounts = web3.eth.accounts; +// const signer = validators[0]; + +// // Get a single block +// const block = web3.eth.getBlock(blockNum); + +// // Decompose the values in the block to hash +// const parentHash = block.parentHash; +// const sha3Uncles = block.sha3Uncles; +// const coinbase = block.miner; +// const root = block.stateRoot; +// const txHash = block.transactionsRoot; +// const receiptHash = block.receiptsRoot; +// const logsBloom = block.logsBloom; +// const difficulty = Web3Utils.toBN(block.difficulty); +// const number = Web3Utils.toBN(block.number); +// const gasLimit = block.gasLimit; +// const gasUsed = block.gasUsed; +// const timestamp = Web3Utils.toBN(block.timestamp); +// const extraData = block.extraData; +// const mixHash = block.mixHash; +// const nonce = block.nonce; + +// // Remove last 65 Bytes of extraData +// const extraBytes = utils.hexToBytes(extraData); +// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); +// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + +// const blockHeader = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// txHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// extraData, +// mixHash, +// nonce +// ]; + +// const header = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// txHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// extraDataShort, +// mixHash, +// nonce +// ]; + +// const encodedBlockHeader = '0x' + rlp.encode(blockHeader).toString('hex'); +// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); +// assert.equal(block.hash, blockHeaderHash); + +// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); +// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); +// const headerHash = Web3Utils.sha3(encodedHeader); + +// // Get Prefixes +// const prefixHeader = '0x' + encodedHeader.substring(4, 8); +// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); + +// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); +// const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; +// const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; +// assert.equal(block.hash, recoveredBlockHash) +// assert.notEqual(validators.indexOf(recoveredSignature), -1); + +// }) + +// // Here the block header is signed off chain but by a whitelisted validator +// it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { +// const validation = await Validation.new(validators, genHash); +// const accounts = web3.eth.accounts; +// const signer = validators[0]; + +// // Get a single block +// const block = web3.eth.getBlock(blockNum); + +// // Decompose the values in the block to hash +// const parentHash = block.parentHash; +// const sha3Uncles = block.sha3Uncles; +// const coinbase = block.miner; +// const root = block.stateRoot; +// const txHash = block.transactionsRoot; +// const receiptHash = block.receiptsRoot; +// const logsBloom = block.logsBloom; +// const difficulty = Web3Utils.toBN(block.difficulty); +// const number = Web3Utils.toBN(block.number); +// const gasLimit = block.gasLimit; +// const gasUsed = block.gasUsed; +// const timestamp = Web3Utils.toBN(block.timestamp); +// const extraData = block.extraData; +// const mixHash = block.mixHash; +// const nonce = block.nonce; + +// // Create new signed hash +// const extraBytes = hexToBytes(extraData); +// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); +// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + +// // Make some changes to the block +// const header = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// txHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// extraDataShort, +// mixHash, +// nonce +// ]; + +// // Encode and sign the new header +// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); +// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); +// const headerHash = eth_util.sha3(encodedHeader); + +// const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + +// let signature = await signHeader(headerHash, privateKey, extraData); + +// // Append signature to the end of extraData +// const sigBytes = hexToBytes(signature.toString('hex')); +// const newExtraDataBytes = extraBytesShort.concat(sigBytes); +// const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); +// assert.equal(extraDataSignature, '0x'+signature.toString('hex')) + +// const newBlockHeader = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// txHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// newExtraData, +// mixHash, +// nonce +// ]; + +// const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); +// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); +// assert.equal(block.hash, blockHeaderHash); + +// // Get Prefixes +// const prefixHeader = '0x' + encodedHeader.substring(4, 8); +// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); + +// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); +// const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; +// const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; +// assert.equal(block.hash, recoveredBlockHash) +// assert.equal(recoveredSignature, signer); +// }) + +// it('Test: Inauthentic Block Submission - ValidateBlock()', async () => { +// const validation = await Validation.new(validators, genHash); +// const accounts = web3.eth.accounts; +// const signer = validators[0]; + +// // Get a single block +// const block = web3.eth.getBlock(blockNum); + +// // Decompose the values in the block to hash +// const parentHash = block.parentHash; +// const sha3Uncles = block.sha3Uncles; +// const coinbase = block.miner; +// const root = block.stateRoot; +// const txHash = block.transactionsRoot; +// const receiptHash = block.receiptsRoot; +// const logsBloom = block.logsBloom; +// const difficulty = Web3Utils.toBN(block.difficulty); +// const number = Web3Utils.toBN(block.number); +// const gasLimit = block.gasLimit; +// const gasUsed = block.gasUsed; +// const timestamp = Web3Utils.toBN(block.timestamp); +// const extraData = block.extraData; +// const mixHash = block.mixHash; +// const nonce = block.nonce; + +// // Create new signed hash +// const extraBytes = hexToBytes(extraData); +// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); +// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + +// // Make some changes to the block +// const newTxHash = Web3Utils.sha3("Test Data"); +// // console.log(txHash, newTxHash); +// const header = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// // txHash, +// newTxHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// extraDataShort, +// mixHash, +// nonce +// ]; + +// // Encode and sign the new header +// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); +// const headerHash = eth_util.sha3(encodedHeader); + +// const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + +// const sig = eth_util.ecsign(headerHash, privateKey) +// if (this._chainId > 0) { +// sig.v += this._chainId * 2 + 8 +// } + +// const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); +// const addrBuf = eth_util.pubToAddress(pubKey); +// assert.equal(signer, '0x'+addrBuf.toString('hex')); + +// const newSigBytes = Buffer.concat([sig.r, sig.s]); +// let newSig; + +// // Need to understand why but signature requires different v than in others to recover correctly +// if (sig.v=="27") { +// newSig = newSigBytes.toString('hex') + '00'; +// } +// if (sig.v=="28") { +// newSig = newSigBytes.toString('hex') + '01'; +// } + +// // Append signature to the end of extraData +// const sigBytes = hexToBytes(newSig.toString('hex')); +// const newExtraDataBytes = extraBytesShort.concat(sigBytes); +// const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); + +// const newBlockHeader = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// // txHash, +// newTxHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// newExtraData, +// mixHash, +// nonce +// ]; + +// const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); +// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); +// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + +// // Get Prefixes +// const prefixHeader = '0x' + encodedHeader.substring(4, 8); +// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); + +// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); +// const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; +// const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; +// assert.equal(recoveredBlockHash, blockHeaderHash); +// assert.equal(recoveredSignature, signer); + +// }) + +// it('Test: Authentic Block Unkown Validator Submission - ValidateBlock()', async () => { +// const validation = await Validation.new(validators, genHash); +// const accounts = web3.eth.accounts; +// const signer = validators[1]; + +// // Get a single block +// const block = web3.eth.getBlock(blockNum); + +// // Decompose the values in the block to hash +// const parentHash = block.parentHash; +// const sha3Uncles = block.sha3Uncles; +// const coinbase = block.miner; +// const root = block.stateRoot; +// const txHash = block.transactionsRoot; +// const receiptHash = block.receiptsRoot; +// const logsBloom = block.logsBloom; +// const difficulty = Web3Utils.toBN(block.difficulty); +// const number = Web3Utils.toBN(block.number); +// const gasLimit = block.gasLimit; +// const gasUsed = block.gasUsed; +// const timestamp = Web3Utils.toBN(block.timestamp); +// const extraData = block.extraData; +// const mixHash = block.mixHash; +// const nonce = block.nonce; + +// // Create new signed hash +// const extraBytes = hexToBytes(extraData); +// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); +// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + +// // Make some changes to the block +// const newTxHash = Web3Utils.sha3("Test Data"); +// const header = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// newTxHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// extraDataShort, +// mixHash, +// nonce +// ]; + +// // Encode and sign the new header +// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); +// const headerHash = eth_util.sha3(encodedHeader); + +// const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') + +// const sig = eth_util.ecsign(headerHash, privateKey) +// if (this._chainId > 0) { +// sig.v += this._chainId * 2 + 8 +// } + +// const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); +// const addrBuf = eth_util.pubToAddress(pubKey); +// const addr = eth_util.bufferToHex(addrBuf); + +// const newSigBytes = Buffer.concat([sig.r, sig.s]); +// let newSig; + +// const bytes = hexToBytes(extraData) +// const finalByte = bytes.splice(bytes.length-1) +// if (finalByte.toString('hex')=="00") +// newSig = newSigBytes.toString('hex') + '00'; +// else (finalByte.toString('hex')=="01") +// newSig = newSigBytes.toString('hex') + '01'; + +// // Append signature to the end of extraData +// const sigBytes = hexToBytes(newSig.toString('hex')); +// const newExtraDataBytes = extraBytesShort.concat(sigBytes); +// const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); + +// const newBlockHeader = [ +// parentHash, +// sha3Uncles, +// coinbase, +// root, +// newTxHash, +// receiptHash, +// logsBloom, +// difficulty, +// number, +// gasLimit, +// gasUsed, +// timestamp, +// newExtraData, +// mixHash, +// nonce +// ]; + +// const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); +// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); +// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); + +// // Get Prefixes +// const prefixHeader = '0x' + encodedHeader.substring(4, 8); +// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); + +// try { +// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); +// } catch (err) { +// assert.isDefined(err, "transaction should have thrown"); +// } +// }) }); From 41926762a232b96eb00626eef7fc13ca082edd28 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 26 Jul 2018 17:14:16 +0100 Subject: [PATCH 083/203] shorted the modifier proof --- contracts/Ion.sol | 21 ++++++--------------- test/ion.js | 31 +++---------------------------- 2 files changed, 9 insertions(+), 43 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 9c872d0..2d9f497 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -22,9 +22,10 @@ contract Ion { address[] public validators; bytes32 public blockHash; bytes32 public chainId; - bytes32[] public chains; + // bytes32[] public chains; uint256 public blockHeight; + mapping (bytes32 => bool) public chains; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; @@ -65,14 +66,7 @@ contract Ion { * Modifier that checks if the provided chain id has been registered to this contract */ modifier onlyRegisteredChains(bytes32 _id) { - bool chainRegistered = false; - for (uint i = 0; i < chains.length; i++) { - if (_id == chains[i]) { - chainRegistered = true; - break; - } - } - require(chainRegistered, "Chain is not registered"); + require(chains[_id], "Chain is not registered"); _; } @@ -98,16 +92,13 @@ contract Ion { */ function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { require( _id != chainId, "Cannot add this chain id to chain register" ); - for (uint i = 0; i < chains.length; i++) { - require( chains[i] != _id, "Chain already exists" ); - } - chains.push(_id); + require(!chains[_id], "Chain already exists" ); + chains[_id] = true; - for (i = 0; i < _validators.length; i++) { + for (uint256 i = 0; i < _validators.length; i++) { m_validators[_id][_validators[i]] = true; } - // blockHash = _genesisHash; m_blockhashes[_id][_genesisHash] = true; m_blockheaders[_id][_genesisHash].blockHeight = 0; } diff --git a/test/ion.js b/test/ion.js index b0d7ea2..9851036 100644 --- a/test/ion.js +++ b/test/ion.js @@ -154,7 +154,7 @@ const GENESIS_HASH = TESTBLOCK.parentHash; // const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; -contract('Ion.js', (accounts) => { +contract.only('Ion.js', (accounts) => { it('Deploy Ion', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); let chainId = await ion.chainId(); @@ -167,9 +167,9 @@ contract('Ion.js', (accounts) => { // Successfully add id of another chain await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - let chain = await ion.chains.call(0); + let chain = await ion.chains(TESTCHAINID); - assert.equal(chain, TESTCHAINID); + assert.equal(chain, true); // Fail adding id of this chain await ion.RegisterChain(DEPLOYEDCHAINID, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; @@ -200,31 +200,6 @@ contract('Ion.js', (accounts) => { let validators = await ion.m_validators.call(TESTCHAINID, TEST_VALIDATORS[0]); assert.equal(validators, true); }) - - // it('Submit Block', async () => { - // const ion = await Ion.new(DEPLOYEDCHAINID); - - // await ion.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // // Submit block should succeed - // let tx = await ion.SubmitBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING) - - // console.log("Gas used to submit block header = " + tx.receipt.gasUsed.toString() + " gas"); - - // let blockHash = await ion.m_blockhashes(TESTCHAINID, TESTBLOCK.hash); - // let header = await ion.getBlockHeader.call(TESTCHAINID, TESTBLOCK.hash); - - // // Separate fetched header info - // parentHash = header[0]; - // txRootHash = header[1]; - // receiptRootHash = header[2]; - - // // Assert that block was persisted correctly - // assert.equal(blockHash, true); - // assert.equal(parentHash, TESTBLOCK.parentHash); - // assert.equal(txRootHash, TESTBLOCK.transactionsRoot); - // assert.equal(receiptRootHash, TESTBLOCK.receiptsRoot); - // }) it('Submit Block', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); From 30480b825c01021d6643286cb7b5588e1f37ac94 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 27 Jul 2018 08:38:54 +0100 Subject: [PATCH 084/203] ion and validaton contracts have been enhanced and structured ready for future modularisation --- contracts/Ion.sol | 87 ++++++++++++++++------------------------------- test/ion.js | 61 +++++++++++++++++++++------------ 2 files changed, 70 insertions(+), 78 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 2d9f497..bae09d3 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -5,6 +5,8 @@ pragma solidity ^0.4.23; import "./libraries/ECVerify.sol"; import "./libraries/RLP.sol"; import "./libraries/PatriciaTrie.sol"; +import "./libraries/SolidityUtils.sol"; +import "./Validation.sol"; contract Ion { using RLP for RLP.RLPItem; @@ -22,10 +24,10 @@ contract Ion { address[] public validators; bytes32 public blockHash; bytes32 public chainId; - // bytes32[] public chains; uint256 public blockHeight; mapping (bytes32 => bool) public chains; + mapping (bytes32 => address) public validation_addr; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; @@ -85,12 +87,15 @@ contract Ion { /* * RegisterChain - * param: chainId (bytes32) Unique id of another chain to interoperate with + * param: chainId Unique id of another chain to interoperate with + * param: validationAddr Address of the validation contract required to make modular validation + * param: _validators List of validators on the block chain + * param: _genesisHash Genesis blockhash of the interop block chain * * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. */ - function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { + function RegisterChain(bytes32 _id, address validationAddr, address[] _validators, bytes32 _genesisHash) public { require( _id != chainId, "Cannot add this chain id to chain register" ); require(!chains[_id], "Chain already exists" ); chains[_id] = true; @@ -101,6 +106,13 @@ contract Ion { m_blockhashes[_id][_genesisHash] = true; m_blockheaders[_id][_genesisHash].blockHeight = 0; + + // Instantiate validation + Validation validation = Validation(validationAddr); + validation.InitChain(_id, _validators, _genesisHash); + + // Create mapping of registered _id to the validation address + validation_addr[_id] = validationAddr; } /* @@ -116,32 +128,21 @@ contract Ion { RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); - // Check header and signedHeader contain the same data - for (uint256 i=0; i { +contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); let chainId = await ion.chainId(); @@ -164,25 +165,27 @@ contract.only('Ion.js', (accounts) => { it('Register Chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); let chain = await ion.chains(TESTCHAINID); assert.equal(chain, true); // Fail adding id of this chain - await ion.RegisterChain(DEPLOYEDCHAINID, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; + await ion.RegisterChain(DEPLOYEDCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already registered - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; }) it('Register Chain - Check Genesis Hash', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); let header = await ion.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); let blockHeight = header[0]; @@ -193,9 +196,10 @@ contract.only('Ion.js', (accounts) => { it('Register Chain - Check Validators', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); let validators = await ion.m_validators.call(TESTCHAINID, TEST_VALIDATORS[0]); assert.equal(validators, true); @@ -203,8 +207,9 @@ contract.only('Ion.js', (accounts) => { it('Submit Block', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); // Submit block should succeed const validationReceipt = await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -213,12 +218,12 @@ contract.only('Ion.js', (accounts) => { let blockHash = await ion.m_blockhashes(TESTCHAINID, TESTBLOCK.hash); assert.equal(blockHash, true); - let header = await ion.getBlockHeader.call(TESTCHAINID, TESTBLOCK.hash); + let header = await ion.m_blockheaders(TESTCHAINID, TESTBLOCK.hash); // Separate fetched header info - parentHash = header[0]; - txRootHash = header[1]; - receiptRootHash = header[2]; + parentHash = header[1]; + txRootHash = header[2]; + receiptRootHash = header[3]; // Assert that block was persisted correctly assert.equal(parentHash, TESTBLOCK.parentHash); @@ -228,16 +233,18 @@ contract.only('Ion.js', (accounts) => { it('Fail Submit Block from unknown chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; }) it('Fail Submit Block with wrong unsigned header', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); const incorrectHeader = [ TESTBLOCK.parentHash, @@ -265,8 +272,9 @@ contract.only('Ion.js', (accounts) => { it('Check Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -277,8 +285,9 @@ contract.only('Ion.js', (accounts) => { it('Fail Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -294,8 +303,9 @@ contract.only('Ion.js', (accounts) => { it('Check Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -307,8 +317,9 @@ contract.only('Ion.js', (accounts) => { it('Fail Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -324,8 +335,9 @@ contract.only('Ion.js', (accounts) => { it('Check Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -336,8 +348,9 @@ contract.only('Ion.js', (accounts) => { it('Fail Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -356,17 +369,21 @@ contract.only('Ion.js', (accounts) => { it('Deploy Function Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); + const verifier = await TriggerEventVerifier.new(); const functionContract = await Function.new(ion.address, verifier.address); }) it('Verify Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); + const verifier = await TriggerEventVerifier.new(); const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -382,11 +399,13 @@ contract.only('Ion.js', (accounts) => { it('Fail Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID); + const verifier = await TriggerEventVerifier.new(); const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion - await ion.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); From b33a996b0967eba56621b1708d339b4a369966ed Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 30 Jul 2018 17:11:10 +0100 Subject: [PATCH 085/203] Got all tests working though there is a problem with the deploy of function --- README.md | 9 +- abi/EventVerifier.abi | 1 + abi/EventVerifier.bin | 1 + abi/Function.abi | 1 + abi/Function.bin | 1 + abi/Ion.abi | 2 +- abi/Ion.bin | 2 +- abi/IonCompatible.abi | 1 + abi/IonCompatible.bin | 1 + abi/PatriciaTrie.abi | 2 +- abi/PatriciaTrie.bin | 2 +- abi/RLP.bin | 2 +- abi/Trigger.abi | 1 + abi/Trigger.bin | 1 + abi/Validation.abi | 2 +- abi/Validation.bin | 2 +- ...acts_Function_sol_TriggerEventVerifier.abi | 1 + ...acts_Function_sol_TriggerEventVerifier.bin | 0 ...EventVerifier_sol_TriggerEventVerifier.abi | 1 + ...EventVerifier_sol_TriggerEventVerifier.bin | 1 + contracts/Function.sol | 2 +- contracts/Ion.sol | 100 +- contracts/Validation.sol | 53 +- docs/TransactionVerification.md | 2 - ion-cli/cli/cli.go | 202 ++-- ion-cli/config/init.go | 4 +- ion-cli/contracts/ion.go | 647 ++++++++---- ion-cli/main.go | 4 +- ion-cli/rinkeby.json | 6 +- migrations/2_deploy_contracts.js | 11 - test/ion.js | 141 +-- test/validation.js | 917 +++++++++--------- 32 files changed, 1238 insertions(+), 885 deletions(-) create mode 100644 abi/EventVerifier.abi create mode 100644 abi/EventVerifier.bin create mode 100644 abi/Function.abi create mode 100644 abi/Function.bin create mode 100644 abi/IonCompatible.abi create mode 100644 abi/IonCompatible.bin create mode 100644 abi/Trigger.abi create mode 100644 abi/Trigger.bin create mode 100644 abi/__contracts_Function_sol_TriggerEventVerifier.abi create mode 100644 abi/__contracts_Function_sol_TriggerEventVerifier.bin create mode 100644 abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.abi create mode 100644 abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.bin delete mode 100644 docs/TransactionVerification.md diff --git a/README.md b/README.md index 39d1570..03803e4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # Ion Interoperability Protocol -The Ion Interoperability Protocol provides mechanisms to perform atomic swaps and currency transfers -across multiple turing-complete blockchains. +The Ion Interoperability Protocol provides mechanisms to perform atomic swaps and currency transfers across multiple turing-complete blockchains. + +## Ion State Verification Scheme ## Block Validation Scheme Block validation scheme is a set of smart contracts which ensures that block headers submitted to the contract are mined/sealed by an approved partie(s). The motivation behind this is to update the state of a blockchain onto another blockchain. To do this we first need to know which blocks are valid - dependent on the definition of a valid by the underlying consensus algorithm. As deterministic finality is a requirement we seek Clique PoA and Istanbul PBFT consensus is to be used on the chain from which the state is being taken. @@ -26,8 +27,8 @@ In order to use the smart contracts and run the tests it is necessary to first i ### Installing Ion Having cloned and entered the repo: ``` -$ git clone git@github.com:maxrobot/validation.git -$ cd /path/to/validation +$ git clone git@github.com:clearmatics/ion.git +$ cd /path/to/ion ``` Now run the command: diff --git a/abi/EventVerifier.abi b/abi/EventVerifier.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/abi/EventVerifier.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/abi/EventVerifier.bin b/abi/EventVerifier.bin new file mode 100644 index 0000000..deb27c6 --- /dev/null +++ b/abi/EventVerifier.bin @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a7230582081077b5b68a90044292efd144121aaf69798d3b9ae25e98d8a72dbb75066d7ad0029 \ No newline at end of file diff --git a/abi/Function.abi b/abi/Function.abi new file mode 100644 index 0000000..39b1f7d --- /dev/null +++ b/abi/Function.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"_chainId","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_contractEmittedAddress","type":"bytes20"},{"name":"_path","type":"bytes"},{"name":"_tx","type":"bytes"},{"name":"_txNodes","type":"bytes"},{"name":"_receipt","type":"bytes"},{"name":"_receiptNodes","type":"bytes"},{"name":"_expectedAddress","type":"bytes20"}],"name":"verifyAndExecute","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_ionAddr","type":"address"},{"name":"_verifierAddr","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"Executed","type":"event"}] \ No newline at end of file diff --git a/abi/Function.bin b/abi/Function.bin new file mode 100644 index 0000000..ba0272a --- /dev/null +++ b/abi/Function.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50604051604080610b28833981018060405281019080805190602001909291908051906020019092919050505081806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610a57806100d16000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d0fdb2b314610046575b600080fd5b34801561005257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff1916906020019092919050505061022d565b604051808215151515815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f484c1f78b8b88876040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180856000191660001916815260200184600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156102fb5780820151818401526020810190506102e0565b50505050905090810190601f1680156103285780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156103b157600080fd5b505af11580156103c5573d6000803e3d6000fd5b505050506040513d60208110156103db57600080fd5b810190808051906020019092919050505015156103f457fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663affd8be98b8b89898c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156104c55780820151818401526020810190506104aa565b50505050905090810190601f1680156104f25780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561052b578082015181840152602081019050610510565b50505050905090810190601f1680156105585780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015610591578082015181840152602081019050610576565b50505050905090810190601f1680156105be5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1580156105e357600080fd5b505af11580156105f7573d6000803e3d6000fd5b505050506040513d602081101561060d57600080fd5b8101908080519060200190929190505050151561062657fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bec205b98b8b87878c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106f75780820151818401526020810190506106dc565b50505050905090810190601f1680156107245780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561075d578082015181840152602081019050610742565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b838110156107c35780820151818401526020810190506107a8565b50505050905090810190601f1680156107f05780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b15801561081557600080fd5b505af1158015610829573d6000803e3d6000fd5b505050506040513d602081101561083f57600080fd5b8101908080519060200190929190505050151561085857fe5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357064c3d8986856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200180602001836bffffffffffffffffffffffff19166bffffffffffffffffffffffff19168152602001828103825284818151815260200191508051906020019080838360005b8381101561094c578082015181840152602081019050610931565b50505050905090810190601f1680156109795780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d60208110156109c457600080fd5b8101908080519060200190929190505050156109eb576109e26109fd565b600190506109f0565b600090505b9998505050505050505050565b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e60405160405180910390a15600a165627a7a72305820eedb1504d9ba40d675657ad3dd7079e897af70039718f2e02e76d9caedcfc3a50029 \ No newline at end of file diff --git a/abi/Ion.abi b/abi/Ion.abi index a70cf5d..a83cfb8 100644 --- a/abi/Ion.abi +++ b/abi/Ion.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"chains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CheckReceiptProof","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_blockHash","type":"bytes32"}],"name":"getBlockHeader","outputs":[{"name":"","type":"bytes32[3]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"CheckRootsProof","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"VerifiedTxProof","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"registeredChains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"validation_addr","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"validationAddr","type":"address"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckReceiptProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_txNodes","type":"bytes"},{"name":"_receiptNodes","type":"bytes"}],"name":"CheckRootsProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"},{"indexed":false,"name":"proofType","type":"uint256"}],"name":"VerifiedProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin index eb52a59..41354e3 100644 --- a/abi/Ion.bin +++ b/abi/Ion.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b5060405160208061101a8339810160405251600055610fe6806100346000396000f3006080604052600436106100a35763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663550325b581146100a857806359349832146100d25780635a0235e4146100e95780636b4f9b9d14610149578063927a32e3146101995780639a8a0592146101cf5780639e43d86b146101e4578063affd8be9146101fc578063e318df54146100d2578063fecc37c3146102ec575b600080fd5b3480156100b457600080fd5b506100c0600435610307565b60408051918252519081900360200190f35b3480156100de57600080fd5b506100e7610326565b005b3480156100f557600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526100e79482359460248035953695946064949201919081908401838280828437509497506103289650505050505050565b34801561015557600080fd5b506101616004356104bf565b6040518082606080838360005b8381101561018657818101518382015260200161016e565b5050505090500191505060405180910390f35b3480156101a557600080fd5b506101b1600435610506565b60408051938452602084019290925282820152519081900360600190f35b3480156101db57600080fd5b506100c0610527565b3480156101f057600080fd5b506100e760043561052d565b34801561020857600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102d894823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061066c9650505050505050565b604080519115158252519081900360200190f35b3480156102f857600080fd5b506100c0600435602435610a68565b600180548290811061031557fe5b600091825260209091200154905081565b565b60606000808581805b60015481101561036d57600180548290811061034957fe5b600091825260209091200154831415610365576001915061036d565b600101610331565b8115156103c4576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b6103d56103d088610a98565b610aeb565b9550866040518082805190602001908083835b602083106104075780518252601f1990920191602091820191016103e8565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060008e815260039092529281208b51939a509850610470945061046993508a92909150811061045a57fe5b90602001906020020151610ba0565b6001610bf4565b8455855161048990610469908890600490811061045a57fe5b600185015585516104a590610469908890600590811061045a57fe5b60028501556104b48989610c82565b505050505050505050565b6104c7610f63565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b600080548214156105ae576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106375760018054839190839081106105cd57fe5b600091825260209091200154141561062f576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b6001016105b2565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b6001548110156106af57600180548290811061068b57fe5b6000918252602090912001548314156106a757600191506106af565b600101610673565b811515610706576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a815260026020908152604080832080548251818502810185019093528083528e948e9490936060938593919290919083018282801561076857602002820191906000526020600020905b81548152600190910190602001808311610753575b50505050509150600090505b81518110156107ad57818181518110151561078b57fe5b602090810290910101518414156107a557600192506107ad565b600101610774565b821515610804576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f60001916600019168152602001908152602001600020985073__./contracts/libraries/PatriciaTrie.s__634f7142ad8e8e8e8d600101546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108c15781810151838201526020016108a9565b50505050905090810190601f1680156108ee5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610921578181015183820152602001610909565b50505050905090810190601f16801561094e5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610981578181015183820152602001610969565b50505050905090810190601f1680156109ae5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d60208110156109fa57600080fd5b50511515610a0457fe5b7f202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a18f8f60405180836000191660001916815260200182600019166000191681526020019250505060405180910390a15060019e9d5050505050505050505050505050565b600260205281600052604060002081815481101515610a8357fe5b90600052602060002001600091509150505481565b610aa0610f82565b81516000811515610ac65760408051808201909152600080825260208201529250610ae4565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610af7610f99565b6000610b0285610ce2565b1515610b0d57600080fd5b610b1685610d0c565b925082604051908082528060200260200182016040528015610b5257816020015b610b3f610f82565b815260200190600190039081610b375790505b509350610b5e85610d7c565b91505b610b6a82610db5565b15610b9857610b7882610dd4565b8482815181101515610b8657fe5b60209081029091010152600101610b61565b505050919050565b6020810151606090801515610bb457610500565b806040519080825280601f01601f191660200182016040528015610be2578160200160208202803883390190505b50915061050083600001518383610e16565b600080805b6020811015610c7a578060080285828601815181101515610c1657fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610bf9565b509392505050565b6000828152600260205260408120905b8154811015610cca5781548390839083908110610cab57fe5b6000918252602090912001541415610cc257600080fd5b600101610c92565b50805460018101825560009182526020909120015550565b600080826020015160001415610cfb5760009150610500565b5050515160c060009190911a101590565b600080600080600080610d1e87610ce2565b1515610d2d5760009550610d72565b8651805160001a95509350610d4187610e56565b840192506001876020015185010391505b818311610d6e57610d6283610ed6565b90920191600101610d52565b8095505b5050505050919050565b610d84610f99565b6000610d8f83610ce2565b1515610d9a57600080fd5b610da383610e56565b83519383529092016020820152919050565b6000610dbf610f82565b50508051602080820151915192015191011190565b610ddc610f82565b600080610de884610db5565b156100a35783602001519150610dfd82610ed6565b8284526020808501829052838201908601529050610ae4565b60006020601f83010484602085015b828414610e4357602084028281015190820152600190930192610e25565b6000865160200187015250505050505050565b6000806000836020015160001415610e715760009250610ae4565b50508151805160001a906080821015610e8d5760009250610ae4565b60b8821080610ea8575060c08210158015610ea8575060f882105b15610eb65760019250610ae4565b60c0821015610ecb5760b51982019250610ae4565b5060f5190192915050565b8051600090811a6080811015610eef5760019150610500565b60b8811015610f0457607e1981019150610500565b60c0811015610f2d57600183015160b76020839003016101000a9004810160b519019150610500565b60f8811015610f425760be1981019150610500565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280610fad610f82565b81526020016000815250905600a165627a7a723058206a4b9844b305800bce8a0a88fdcd6658383e8dd98c6de20e69edd6739e2e64e20029 \ No newline at end of file +608060405234801561001057600080fd5b5060405160208061221f833981018060405281019080805190602001909291905050508060018160001916905550506121d18061004e6000396000f3006080604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100d5578063261e50731461011e5780634b3550301461018f57806352824374146101e657806353fe62e6146102a35780637558a01a1461030c5780639a8a0592146103ae578063affd8be9146103e1578063bec205b91461050a578063c18de0ef14610633578063e79b136c1461067c578063f22a195e146106fc578063f44ff7121461072f578063f484c1f71461075a575b600080fd5b3480156100e157600080fd5b506101006004803603810190808035906020019092919050505061083d565b60405180826000191660001916815260200191505060405180910390f35b34801561012a57600080fd5b5061014d6004803603810190808035600019169060200190929190505050610860565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561019b57600080fd5b506101cc60048036038101908080356000191690602001909291908035600019169060200190929190505050610893565b604051808215151515815260200191505060405180910390f35b3480156101f257600080fd5b506102a16004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108c2565b005b3480156102af57600080fd5b506102f26004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d71565b604051808215151515815260200191505060405180910390f35b34801561031857600080fd5b506103ac6004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035600019169060200190929190505050610da0565b005b3480156103ba57600080fd5b506103c3611124565b60405180826000191660001916815260200191505060405180910390f35b3480156103ed57600080fd5b506104f060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061112a565b604051808215151515815260200191505060405180910390f35b34801561051657600080fd5b5061061960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061152e565b604051808215151515815260200191505060405180910390f35b34801561063f57600080fd5b506106626004803603810190808035600019169060200190929190505050611932565b604051808215151515815260200191505060405180910390f35b34801561068857600080fd5b506106b960048036038101908080356000191690602001909291908035600019169060200190929190505050611952565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b34801561070857600080fd5b5061071161198f565b60405180826000191660001916815260200191505060405180910390f35b34801561073b57600080fd5b50610744611995565b6040518082815260200191505060405180910390f35b34801561076657600080fd5b5061082360048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199b565b604051808215151515815260200191505060405180910390f35b60028181548110151561084c57fe5b906000526020600020016000915090505481565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008060008960046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561096b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61097c6109778b611bda565b611c35565b975061098f61098a8a611bda565b611c35565b9650600560008c6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508594508473ffffffffffffffffffffffffffffffffffffffff166309fbd5368c8c8c6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610a6e578082015181840152602081019050610a53565b50505050905090810190601f168015610a9b5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610ad4578082015181840152602081019050610ab9565b50505050905090810190601f168015610b015780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015610b2357600080fd5b505af1158015610b37573d6000803e3d6000fd5b50505050610b66610b5f896000815181101515610b5057fe5b90602001906020020151611cf2565b6001611d57565b9350886040518082805190602001908083835b602083101515610b9e5780518252602082019150602081019050602083039250610b79565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092506001600760008d60001916600019168152602001908152602001600020600086600019166000191681526020019081526020016000206000015401915081600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206000018190555083600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206001018160001916905550610cb1610caa896004815181101515610c9b57fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206002018160001916905550610d1b610d14896005815181101515610d0557fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206003018160001916905550610d648b84611d6b565b5050505050505050505050565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600060015460001916856000191614151515610e4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000866000191660001916815260200190815260200160002060009054906101000a900460ff16151515610ee8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000876000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600285908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555060016006600087600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600060076000876000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600001819055508390508073ffffffffffffffffffffffffffffffffffffffff16630b5abdd08685856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808460001916600019168152602001806020018360001916600019168152602001828103825284818151815260200191508051906020019060200280838360005b83811015611084578082015181840152602081019050611069565b50505050905001945050505050600060405180830381600087803b1580156110ab57600080fd5b505af11580156110bf573d6000803e3d6000fd5b505050508360056000876000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b60015481565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156111cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600201546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b8381101561135c578082015181840152602081019050611341565b50505050905090810190601f1680156113895780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156113c25780820151818401526020810190506113a7565b50505050905090810190601f1680156113ef5780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561142857808201518184015260208101905061140d565b50505050905090810190601f1680156114555780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561147757600080fd5b505af415801561148b573d6000803e3d6000fd5b505050506040513d60208110156114a157600080fd5b810190808051906020019092919050505015156114ba57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600060028111156114ea57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156115cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611687576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600301546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611760578082015181840152602081019050611745565b50505050905090810190601f16801561178d5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156117c65780820151818401526020810190506117ab565b50505050905090810190601f1680156117f35780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561182c578082015181840152602081019050611811565b50505050905090810190601f1680156118595780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561187b57600080fd5b505af415801561188f573d6000803e3d6000fd5b505050506040513d60208110156118a557600080fd5b810190808051906020019092919050505015156118be57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600160028111156118ee57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000808560046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611a3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b86866006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611af4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008a60001916600019168152602001908152602001600020600089600019166000191681526020019081526020016000209350611b3387611dbc565b60001916846002015460001916141515611b4957fe5b611b5286611dbc565b60001916846003015460001916141515611b6857fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468989600280811115611b9757fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001945050505050949350505050565b611be2612150565b600080835191506000821415611c105760408051908101604052806000815260200160008152509250611c2e565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611c4161216a565b6000611c4c85611e6f565b1515611c5757600080fd5b611c6085611ea1565b925082604051908082528060200260200182016040528015611c9c57816020015b611c8961218b565b815260200190600190039081611c815790505b509350611ca885611f1b565b91505b611cb482611f63565b15611cea57611cc282611f8d565b8482815181101515611cd057fe5b906020019060200201819052508080600101915050611cab565b505050919050565b60606000826020015190506000811415611d0b57611d51565b806040519080825280601f01601f191660200182016040528015611d3e5781602001602082028038833980820191505090505b509150611d5083600001518383611fe9565b5b50919050565b600060208201915081830151905092915050565b60016006600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000611dc6612150565b606080611dd285611bda565b9250611ddd83611c35565b9150611e00826000815181101515611df157fe5b90602001906020020151611cf2565b9050806040518082805190602001908083835b602083101515611e385780518252602082019150602081019050602083039250611e13565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b600080600083602001511415611e885760009150611e9b565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611eb387611e6f565b1515611ec25760009550611f11565b86600001519350835160001a9450611ed98761202a565b840192506001876020015185010391505b8183111515611f0d57611efc836120b6565b830192508080600101915050611eea565b8095505b5050505050919050565b611f2361216a565b6000611f2e83611e6f565b1515611f3957600080fd5b611f428361202a565b83600001510190508282600001819052508082602001818152505050919050565b6000611f6d612150565b826000015190508060200151816000015101836020015110915050919050565b611f95612150565b600080611fa184611f63565b15611fdd5783602001519150611fb6826120b6565b90508183600001818152505080836020018181525050808201846020018181525050611fe2565b600080fd5b5050919050565b60006020601f83010484602085015b8284146120175760208402808301518183015260018501945050611ff8565b6000865160200187015250505050505050565b6000806000808460200151141561204457600092506120af565b83600001519050805160001a9150608082101561206457600092506120af565b60b8821080612080575060c0821015801561207f575060f882105b5b1561208e57600192506120af565b60c08210156120a557600160b783030192506120af565b600160f783030192505b5050919050565b600080825160001a905060808110156120d2576001915061214a565b60b88110156120e957600160808203019150612149565b60c08110156121135760b78103806020036101000a60018501510480820160010193505050612148565b60f881101561212a57600160c08203019150612147565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b60606040519081016040528061217e61218b565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582063bd23fd4aba60ad5fe5003097cfeb975ac723f7e78172be2b48321603b5cabd0029 \ No newline at end of file diff --git a/abi/IonCompatible.abi b/abi/IonCompatible.abi new file mode 100644 index 0000000..4855f6c --- /dev/null +++ b/abi/IonCompatible.abi @@ -0,0 +1 @@ +[{"inputs":[{"name":"ionAddr","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] \ No newline at end of file diff --git a/abi/IonCompatible.bin b/abi/IonCompatible.bin new file mode 100644 index 0000000..93b6858 --- /dev/null +++ b/abi/IonCompatible.bin @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b5060405160208060b483398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050603580607f6000396000f3006080604052600080fd00a165627a7a72305820ff572c047d1000242abe0ad1fe67b1eca042830f56970a40a559eec0d77707de0029 \ No newline at end of file diff --git a/abi/PatriciaTrie.abi b/abi/PatriciaTrie.abi index faa17e8..b404658 100644 --- a/abi/PatriciaTrie.abi +++ b/abi/PatriciaTrie.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"},{"name":"_root","type":"bytes32"}],"name":"verifyProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"},{"name":"_root","type":"bytes32"}],"name":"verifyProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/abi/PatriciaTrie.bin b/abi/PatriciaTrie.bin index 5735ee3..9e0cab5 100644 --- a/abi/PatriciaTrie.bin +++ b/abi/PatriciaTrie.bin @@ -1 +1 @@ -610d76610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600436106100575763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634f7142ad811461005c575b600080fd5b6040805160206004803580820135601f810184900484028501840190955284845261012694369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750509335945061013a9350505050565b604080519115158252519081900360200190f35b6000610144610cf7565b606060006060806000606060008060608061015e8f6104aa565b9a506101698b6104fd565b99508c98506000955061017d8e60006105b2565b9450600093505b8951841015610497576101ad8a8581518110151561019e57fe5b906020019060200201516107c9565b9750876040518082805190602001908083835b602083106101df5780518252601f1990920191602091820191016101c0565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091208c14925061021c9150505760009b50610497565b61023c8a8581518110151561022d57fe5b906020019060200201516104fd565b965086516011141561039757845186141561033c578f6040518082805190602001908083835b602083106102815780518252601f199092019160209182019101610262565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166102c488601081518110151561019e57fe5b6040518082805190602001908083835b602083106102f35780518252601f1990920191602091820191016102d4565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614156103335760019b50610497565b60009b50610497565b848681518110151561034a57fe5b90602001015160f860020a900460f860020a0260f860020a9004925061038a878461ffff1681518110151561037b57fe5b90602001906020020151610823565b985060018601955061048c565b865160021415610333576103c28760008151811015156103b357fe5b90602001906020020151610834565b91506103cf8260016105b2565b51855196019586141561044f578f6040518082805190602001908083835b6020831061040c5780518252601f1990920191602091820191016103ed565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166102c48860018151811015156103b357fe5b61045a8260016105b2565b51151561046a5760009b50610497565b61047c8760018151811015156103b357fe5b9050610489816000610897565b98505b600190930192610184565b5050505050505050505050949350505050565b6104b2610cf7565b815160008115156104d857604080518082019091526000808252602082015292506104f6565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610509610d0e565b6000610514856108f1565b151561051f57600080fd5b6105288561091b565b92508260405190808252806020026020018201604052801561056457816020015b610551610cf7565b8152602001906001900390816105495790505b5093506105708561098b565b91505b61057c826109c4565b156105aa5761058a826109e3565b848281518110151561059857fe5b60209081029091010152600101610573565b505050919050565b6060806000806105c0610d2f565b6040805160ff80825261012082019092526060916000919060208201611fe08038833901905050955060009450600093505b885184101561072a57610624898581518110151561060c57fe5b90602001015160f860020a900460f860020a02610a25565b9250878015610631575083155b156106bc578251600160f860020a03191660f860020a148061067d57508251600160f860020a0319167f0300000000000000000000000000000000000000000000000000000000000000145b156106b75760208301518651879060ff881690811061069857fe5b906020010190600160f860020a031916908160001a9053506001850194505b61071f565b82518651879060ff88169081106106cf57fe5b906020010190600160f860020a031916908160001a90535060208301518651879060ff600189011690811061070057fe5b906020010190600160f860020a031916908160001a9053506002850194505b6001909301926105f2565b8460ff166040519080825280601f01601f19166020018201604052801561075b578160200160208202803883390190505b509150600090505b8460ff168110156107bd57858181518110151561077c57fe5b90602001015160f860020a900460f860020a02828281518110151561079d57fe5b906020010190600160f860020a031916908160001a905350600101610763565b50979650505050505050565b60208101516060908015156107dd5761081d565b806040519080825280601f01601f19166020018201604052801561080b578160200160208202803883390190505b50915061081d83600001518383610a86565b50919050565b600061082e82610ac6565b92915050565b606060008061084284610b18565b151561084d57600080fd5b61085684610b41565b60408051828152601f19601f84011681016020019091529193509150818015610889578160200160208202803883390190505b5092506104f6828483610a86565b600080805b60208110156108e95780600802858286018151811015156108b957fe5b60209101015160029190910a60f860020a91829004909102600160f860020a03191604919091179060010161089c565b509392505050565b60008082602001516000141561090a576000915061081d565b5050515160c060009190911a101590565b60008060008060008061092d876108f1565b151561093c5760009550610981565b8651805160001a9550935061095087610bbe565b840192506001876020015185010391505b81831161097d5761097183610c3e565b90920191600101610961565b8095505b5050505050919050565b610993610d0e565b600061099e836108f1565b15156109a957600080fd5b6109b283610bbe565b83519383529092016020820152919050565b60006109ce610cf7565b50508051602080820151915192015191011190565b6109eb610cf7565b6000806109f7846109c4565b156100575783602001519150610a0c82610c3e565b82845260208085018290528382019086015290506104f6565b610a2d610d2f565b600080610a3b846004610ccb565b60408051808201909152600160f860020a03199190911681527f0f00000000000000000000000000000000000000000000000000000000000000949094166020850152509192915050565b60006020601f83010484602085015b828414610ab357602084028281015190820152600190930192610a95565b6000865160200187015250505050505050565b6000806000610ad484610b18565b1515610adf57600080fd5b610ae884610b41565b90925090506020811180610afa575080155b15610b0457600080fd5b806020036101000a82510492505050919050565b600080826020015160001415610b31576000915061081d565b5050515160c060009190911a1090565b6000806000806000610b5286610b18565b1515610b5d57600080fd5b8551805160001a935091506080831015610b7d5781945060019350610bb6565b60b8831015610b9b5760018660200151039350816001019450610bb6565b60b78303905080600187602001510303935080820160010194505b505050915091565b6000806000836020015160001415610bd957600092506104f6565b50508151805160001a906080821015610bf557600092506104f6565b60b8821080610c10575060c08210158015610c10575060f882105b15610c1e57600192506104f6565b60c0821015610c335760b519820192506104f6565b5060f5190192915050565b8051600090811a6080811015610c57576001915061081d565b60b8811015610c6c57607e198101915061081d565b60c0811015610c9557600183015160b76020839003016101000a9004810160b51901915061081d565b60f8811015610caa5760be198101915061081d565b6001929092015160f76020849003016101000a900490910160f51901919050565b60008160020a60ff168360f860020a900460ff16811515610ce857fe5b0460f860020a02905092915050565b604080518082019091526000808252602082015290565b606060405190810160405280610d22610cf7565b8152602001600081525090565b604080518082018252906002908290803883395091929150505600a165627a7a72305820acd21e373b0647728c7c4b49443ccc199017257ba462c48699cc1d28528f8b700029 \ No newline at end of file +611322610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634f7142ad1461005d575b600080fd5b81801561006957600080fd5b5061015e600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035600019169060200190929190505050610178565b604051808215151515815260200191505060405180910390f35b600061018261127f565b60606000806060600060606101968b61030a565b96506101a187610365565b9550889450600093506101b58a6000610422565b9250600091505b85518210156102fa576101e586838151811015156101d657fe5b906020019060200201516107d2565b6040518082805190602001908083835b60208310151561021a57805182526020820191506020810190506020830392506101f5565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916856000191614151561026057600097506102fb565b610280868381518110151561027157fe5b90602001906020020151610365565b90506011815114156102a5576102988185858f610837565b80955081965050506102d2565b6002815114156102c8576102bb8185858f6109a5565b80955081965050506102d1565b600097506102fb565b5b6000600102856000191614156102ed576001841497506102fb565b81806001019250506101bc565b5b50505050505050949350505050565b61031261127f565b600080835191506000821415610340576040805190810160405280600081526020016000815250925061035e565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610371611299565b600061037c85610aa4565b151561038757600080fd5b61039085610ad6565b9250826040519080825280602002602001820160405280156103cc57816020015b6103b96112ba565b8152602001906001900390816103b15790505b5093506103d885610b50565b91505b6103e482610b98565b1561041a576103f282610bc2565b848281518110151561040057fe5b9060200190602002018190525080806001019150506103db565b505050919050565b6060806000806104306112d4565b6060600060ff6040519080825280601f01601f1916602001820160405280156104685781602001602082028038833980820191505090505b50955060009450600093505b88518410156106d6576104de898581518110151561048e57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002610c1e565b92508780156104ed5750600084145b156106155760017f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561052557fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105af575060037f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561058657fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b15610610578260016002811015156105c357fe5b6020020151868660ff168151811015156105d957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001850194505b6106c9565b82600060028110151561062457fe5b6020020151868660ff1681518110151561063a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535082600160028110151561067957fe5b6020020151866001870160ff1681518110151561069257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506002850194505b8380600101945050610474565b8460ff166040519080825280601f01601f19166020018201604052801561070c5781602001602082028038833980820191505090505b509150600090505b8460ff168110156107c357858181518110151561072d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002828281518110151561078657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050610714565b81965050505050505092915050565b606060008260200151905060008114156107eb57610831565b806040519080825280601f01601f19166020018201604052801561081e5781602001602082028038833980820191505090505b50915061083083600001518383610d04565b5b50919050565b600080600061084461127f565b6000865188141561089e57600061087b876108768c601081518110151561086757fe5b906020019060200201516107d2565b610d45565b610886576000610889565b60015b8160010291508060ff16905094509450610999565b86888151811015156108ac57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250888361ffff1681518110151561092e57fe5b906020019060200201519150600188019750602061094b836107d2565b51101561096b5761095e82898989610e1e565b8099508192505050610992565b61098f898461ffff1681518110151561098057fe5b90602001906020020151610e87565b90505b8088945094505b50505094509492505050565b60008060608060006109ce8960008151811015156109bf57fe5b90602001906020020151610e9c565b92506109db836001610422565b51880197508651881415610a38576000610a1587610a108c6001815181101515610a0157fe5b90602001906020020151610e9c565b610d45565b610a20576000610a23565b60015b8160010291508060ff16905094509450610a98565b6000610a45846001610422565b511415610a615760008081600102915080905094509450610a98565b610a82896001815181101515610a7357fe5b90602001906020020151610e9c565b9150610a8f826000610f0e565b90508088945094505b50505094509492505050565b600080600083602001511415610abd5760009150610ad0565b8260000151905060c0815160001a101591505b50919050565b600080600080600080610ae887610aa4565b1515610af75760009550610b46565b86600001519350835160001a9450610b0e87610fec565b840192506001876020015185010391505b8183111515610b4257610b3183611078565b830192508080600101915050610b1f565b8095505b5050505050919050565b610b58611299565b6000610b6383610aa4565b1515610b6e57600080fd5b610b7783610fec565b83600001510190508282600001819052508082602001818152505050919050565b6000610ba261127f565b826000015190508060200151816000015101836020015110915050919050565b610bca61127f565b600080610bd684610b98565b15610c125783602001519150610beb82611078565b90508183600001818152505080836020018181525050808201846020018181525050610c17565b600080fd5b5050919050565b610c266112d4565b600080610c34846004611112565b9150600f7f010000000000000000000000000000000000000000000000000000000000000002841690506040805190810160405280837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525092505050919050565b60006020601f83010484602085015b828414610d325760208402808301518183015260018501945050610d13565b6000865160200187015250505050505050565b6000816040518082805190602001908083835b602083101515610d7d5780518252602082019150602081019050602083039250610d58565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916836040518082805190602001908083835b602083101515610de45780518252602082019150602081019050602083039250610dbf565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614905092915050565b6000806060610e2c87610365565b9050601181511415610e4d57610e4481878787610837565b92509250610e7d565b600281511415610e6c57610e63818787876109a5565b92509250610e7d565b600080816001029150809050925092505b5094509492505050565b6000610e9282611176565b6001029050919050565b6060600080610eaa846111cd565b1515610eb557600080fd5b610ebe846111fe565b8092508193505050806040519080825280601f01601f191660200182016040528015610ef95781602001602082028038833980820191505090505b509250610f07828483610d04565b5050919050565b60008060008090505b6020811015610fe1576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610f5857fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610f17565b819250505092915050565b600080600080846020015114156110065760009250611071565b83600001519050805160001a915060808210156110265760009250611071565b60b8821080611042575060c08210158015611041575060f882105b5b156110505760019250611071565b60c082101561106757600160b78303019250611071565b600160f783030192505b5050919050565b600080825160001a90506080811015611094576001915061110c565b60b88110156110ab5760016080820301915061110b565b60c08110156110d55760b78103806020036101000a6001850151048082016001019350505061110a565b60f88110156110ec57600160c08203019150611109565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008160020a60ff16837f0100000000000000000000000000000000000000000000000000000000000000900460ff1681151561114b57fe5b047f010000000000000000000000000000000000000000000000000000000000000002905092915050565b6000806000611184846111cd565b151561118f57600080fd5b611198846111fe565b809250819350505060208111806111af5750600081145b156111b957600080fd5b806020036101000a82510492505050919050565b6000806000836020015114156111e657600091506111f8565b8260000151905060c0815160001a1091505b50919050565b600080600080600061120f866111cd565b151561121a57600080fd5b85600001519150815160001a9250608083101561123d5781945060019350611277565b60b883101561125b5760018660200151039350600182019450611276565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b604080519081016040528060008152602001600081525090565b6060604051908101604052806112ad6112ba565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a7230582062c120ac04d83a1f0be254ec010b3af455b1d08eca98fad20401929be7d7c8460029 \ No newline at end of file diff --git a/abi/RLP.bin b/abi/RLP.bin index 1bc8155..6c95efc 100644 --- a/abi/RLP.bin +++ b/abi/RLP.bin @@ -1 +1 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820c3ab6c04b83b440abb681106d8efa4dc64fdbfaa7cd538c013391b28f976a1590029 \ No newline at end of file +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820c40d98d896ee9b29853c2246ad4e5ee88c185c69ecf0fc78fe219e5160d984b00029 \ No newline at end of file diff --git a/abi/Trigger.abi b/abi/Trigger.abi new file mode 100644 index 0000000..c4fa541 --- /dev/null +++ b/abi/Trigger.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[],"name":"fire","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"caller","type":"address"}],"name":"Triggered","type":"event"}] \ No newline at end of file diff --git a/abi/Trigger.bin b/abi/Trigger.bin new file mode 100644 index 0000000..09b0634 --- /dev/null +++ b/abi/Trigger.bin @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b5060e98061001e6000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063457094cc146044575b600080fd5b348015604f57600080fd5b5060566058565b005b7f27a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc707839534033604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15600a165627a7a7230582075568de5f8b7f204723f17d5a21cd3d869649545ce604ea530188d50d270bca90029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi index 670dcf1..056ae8a 100644 --- a/abi/Validation.abi +++ b/abi/Validation.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"blockNumber","type":"uint256"}],"name":"GetBlock","outputs":[{"name":"_blockHash","type":"bytes32"},{"name":"_prevBlockHash","type":"bytes32"},{"name":"_blockHeight","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"m_blockheaders","outputs":[{"name":"blockHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genesisHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"InitChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin index 17b549d..bb18e92 100644 --- a/abi/Validation.bin +++ b/abi/Validation.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051610b26380380610b2683398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816003816000191690555081600460008081526020019081526020016000206000018160001916905550505050610961806101c56000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806340ce4b6c146100725780639db7d9f7146100d1578063aae933e414610104578063c4cf3ed6146101f9578063d405af3d14610251575b600080fd5b34801561007e57600080fd5b5061009d600480360381019080803590602001909291905050506102bd565b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390f35b3480156100dd57600080fd5b506100e6610300565b60405180826000191660001916815260200191505060405180910390f35b34801561011057600080fd5b506101f7600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061030a565b005b34801561020557600080fd5b50610224600480360381019080803590602001909291905050506106d9565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b34801561025d57600080fd5b506102666106fd565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102a957808201518184015260208101905061028e565b505050509050019250505060405180910390f35b6000806000600460008581526020019081526020016000206000015492506004600085815260200190815260200160002060010154915060025490509193909250565b6000600354905090565b600080600060608060608060606000806103258d600461078b565b9950600354600019168a600019161415156103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b8c5198508c6040518082805190602001908083835b6020831015156103e257805182526020820191506020810190506020830392506103bd565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156104865781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156104bd5781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156104f45781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561052b5781602001602082028038833980820191505090505b50935061053a878e600061079f565b600260218801600260208f016004610bb8fa5061055b868e608c8c0361079f565b600160208701600160208e016004610bb8fa5061057c848e602a8c0361079f565b6105878787866107c1565b9250826040518082805190602001908083835b6020831015156105bf578051825260208201915060208101905060208303925061059a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506105fc858e606b8c0361079f565b610606828661086d565b905087600381600019169055506002600081548092919060010191905055508760046000600254815260200190815260200160002060000181600019169055508960046000600254815260200190815260200160002060010181600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050505050505050505050565b60046020528060005260406000206000915090508060000154908060010154905082565b6060600180548060200260200160405190810160405280929190818152602001828054801561078157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610737575b5050505050905090565b600060208201915081830151905092915050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156108285781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561088357600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff1610156108ae57601b810190505b601b8160ff1614806108c35750601c8160ff16145b15156108ce57600080fd5b6108da868285856108e5565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561092857600080fd5b80925050509493505050505600a165627a7a72305820973e5581400dbd7323a6c24b4d15a6562cc416ea892009c1044fe9318ebb62c90029 \ No newline at end of file +608060405234801561001057600080fd5b506040516020806114d883398101806040528101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600181600019169055505061144a8061008e6000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806309fbd5361461009e5780630b5abdd01461015b5780634b355030146101dd57806353fe62e61461023457806359a533311461029d5780638da5cb5b146102e2578063927a32e3146103395780639a8a05921461039c578063c18de0ef146103cf575b600080fd5b3480156100aa57600080fd5b506101596004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610418565b005b34801561016757600080fd5b506101db60048036038101908080356000191690602001909291908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080356000191690602001909291905050506108b9565b005b3480156101e957600080fd5b5061021a60048036038101908080356000191690602001909291908035600019169060200190929190505050610b29565b604051808215151515815260200191505060405180910390f35b34801561024057600080fd5b506102836004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b58565b604051808215151515815260200191505060405180910390f35b3480156102a957600080fd5b506102cc6004803603810190808035600019169060200190929190505050610b87565b6040518082815260200191505060405180910390f35b3480156102ee57600080fd5b506102f7610b9f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561034557600080fd5b506103686004803603810190808035600019169060200190929190505050610bc4565b6040518084815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b3480156103a857600080fd5b506103b1610bee565b60405180826000191660001916815260200191505060405180910390f35b3480156103db57600080fd5b506103fe6004803603810190808035600019169060200190929190505050610bf4565b604051808215151515815260200191505060405180910390f35b60608060008060008760036000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156104be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b6104cf6104ca89610c14565b610c6f565b95506104e26104dd88610c14565b610c6f565b9450600093505b845184101561068f57600c84141561050057610682565b610520858581518110151561051157fe5b90602001906020020151610d2c565b6040518082805190602001908083835b6020831015156105555780518252602082019150602081019050602083039250610530565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166105a6878681518110151561059757fe5b90602001906020020151610d2c565b6040518082805190602001908083835b6020831015156105db57805182526020820191506020810190506020830392506105b6565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141515610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486561646572206461746120646f65736e2774206d617463682100000000000081525060200191505060405180910390fd5b5b83806001019450506104e9565b6106ba6106b38760008151811015156106a457fe5b90602001906020020151610d2c565b6001610d91565b92508260001916600560008b600019166000191681526020019081526020016000206001015460001916141515610759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b866040518082805190602001908083835b60208310151561078f578051825260208201915060208101905060208303925061076a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018260405180826000191660001916815260200191505060405180910390a16108288961082287600c81518110151561081357fe5b90602001906020020151610d2c565b8a610da5565b600560008a600019166000191681526020019081526020016000206000016000815480929190600101919050555081600560008b60001916600019168152602001908152602001600020600101816000191690555082600560008b6000191660001916815260200190815260200160002060020181600019169055506108ae8983610fad565b505050505050505050565b600060015460001916846000191614151515610963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60036000856000191660001916815260200190815260200160002060009054906101000a900460ff16151515610a01576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160036000866000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600090505b8251811015610ad857600160066000866000191660001916815260200190815260200160002060008584815181101515610a7057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610a3a565b60006005600086600019166000191681526020019081526020016000206000018190555081600560008660001916600019168152602001908152602001600020600101816000191690555050505050565b60046020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60026020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60056020528060005260406000206000915090508060000154908060010154908060020154905083565b60015481565b60036020528060005260406000206000915054906101000a900460ff1681565b610c1c6113c9565b600080835191506000821415610c4a5760408051908101604052806000815260200160008152509250610c68565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610c7b6113e3565b6000610c8685610ffe565b1515610c9157600080fd5b610c9a85611030565b925082604051908082528060200260200182016040528015610cd657816020015b610cc3611404565b815260200190600190039081610cbb5790505b509350610ce2856110aa565b91505b610cee826110f2565b15610d2457610cfc8261111c565b8482815181101515610d0a57fe5b906020019060200201819052508080600101915050610ce5565b505050919050565b60606000826020015190506000811415610d4557610d8b565b806040519080825280601f01601f191660200182016040528015610d785781602001602082028038833980820191505090505b509150610d8a83600001518383611178565b5b50919050565b600060208201915081830151905092915050565b606060008060416040519080825280601f01601f191660200182016040528015610dde5781602001602082028038833980820191505090505b50925084519150610df38386604185036111b9565b610e5f846040518082805190602001908083835b602083101515610e2c5780518252602082019150602081019050602083039250610e07565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020846111db565b90506001151560066000886000191660001916815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515610f42576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef4381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b60016004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600080600083602001511415611017576000915061102a565b8260000151905060c0815160001a101591505b50919050565b60008060008060008061104287610ffe565b151561105157600095506110a0565b86600001519350835160001a945061106887611253565b840192506001876020015185010391505b818311151561109c5761108b836112df565b830192508080600101915050611079565b8095505b5050505050919050565b6110b26113e3565b60006110bd83610ffe565b15156110c857600080fd5b6110d183611253565b83600001510190508282600001819052508082602001818152505050919050565b60006110fc6113c9565b826000015190508060200151816000015101836020015110915050919050565b6111246113c9565b600080611130846110f2565b1561116c5783602001519150611145826112df565b90508183600001818152505080836020018181525050808201846020018181525050611171565b600080fd5b5050919050565b60006020601f83010484602085015b8284146111a65760208402808301518183015260018501945050611187565b6000865160200187015250505050505050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b600080600080604185511415156111f157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561121c57601b810190505b601b8160ff1614806112315750601c8160ff16145b151561123c57600080fd5b61124886828585611379565b935050505092915050565b6000806000808460200151141561126d57600092506112d8565b83600001519050805160001a9150608082101561128d57600092506112d8565b60b88210806112a9575060c082101580156112a8575060f882105b5b156112b757600192506112d8565b60c08210156112ce57600160b783030192506112d8565b600160f783030192505b5050919050565b600080825160001a905060808110156112fb5760019150611373565b60b881101561131257600160808203019150611372565b60c081101561133c5760b78103806020036101000a60018501510480820160010193505050611371565b60f881101561135357600160c08203019150611370565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa92508051915050600115158215151415156113bc57600080fd5b8092505050949350505050565b604080519081016040528060008152602001600081525090565b6060604051908101604052806113f7611404565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820897cc24853981b569e808746bf0fedcd4e017d77e97cdb224a413d00378c0be20029 \ No newline at end of file diff --git a/abi/__contracts_Function_sol_TriggerEventVerifier.abi b/abi/__contracts_Function_sol_TriggerEventVerifier.abi new file mode 100644 index 0000000..b7c5835 --- /dev/null +++ b/abi/__contracts_Function_sol_TriggerEventVerifier.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"_contractEmittedAddress","type":"bytes20"},{"name":"_rlpReceipt","type":"bytes"},{"name":"_expectedAddress","type":"bytes20"}],"name":"verify","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/abi/__contracts_Function_sol_TriggerEventVerifier.bin b/abi/__contracts_Function_sol_TriggerEventVerifier.bin new file mode 100644 index 0000000..e69de29 diff --git a/abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.abi b/abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.abi new file mode 100644 index 0000000..b7c5835 --- /dev/null +++ b/abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"_contractEmittedAddress","type":"bytes20"},{"name":"_rlpReceipt","type":"bytes"},{"name":"_expectedAddress","type":"bytes20"}],"name":"verify","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.bin b/abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.bin new file mode 100644 index 0000000..53172f5 --- /dev/null +++ b/abi/__contracts_TriggerEventVerifier_sol_TriggerEventVerifier.bin @@ -0,0 +1 @@ +608060405260405180807f54726967676572656428616464726573732900000000000000000000000000008152506012019050604051809103902060009060001916905534801561004f57600080fd5b50610a048061005f6000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806357064c3d14610046575b600080fd5b34801561005257600080fd5b506100df60048036038101908080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff191690602001909291905050506100f9565b604051808215151515815260200191505060405180910390f35b600060608060608060006101106000548a8a6101c4565b945061013385600081518110151561012457fe5b90602001906020020151610311565b935061015685600181518110151561014757fe5b90602001906020020151610383565b925061017985600281518110151561016a57fe5b90602001906020020151610311565b9150610189826014845103610440565b9050866bffffffffffffffffffffffff1916816bffffffffffffffffffffffff19161415156101b457fe5b6001955050505050509392505050565b606080606060006060806000806101e26101dd8a610529565b610383565b96506102058760038151811015156101f657fe5b90602001906020020151610383565b9550600094505b85518510156102f857610235868681518110151561022657fe5b90602001906020020151610383565b935061025884600181518110151561024957fe5b90602001906020020151610383565b925061027b83600081518110151561026c57fe5b90602001906020020151610584565b91508a60001916826000191614156102eb576102b86102b18560008151811015156102a257fe5b90602001906020020151610311565b6000610440565b9050896bffffffffffffffffffffffff1916816bffffffffffffffffffffffff19161415156102e357fe5b839750610303565b848060010195505061020c565b6000151561030257fe5b5b505050505050509392505050565b606060008061031f84610599565b151561032a57600080fd5b610333846105ca565b8092508193505050806040519080825280601f01601f19166020018201604052801561036e5781602001602082028038833980820191505090505b50925061037c82848361064b565b5050919050565b6060600061038f610983565b600061039a8561068c565b15156103a557600080fd5b6103ae856106be565b9250826040519080825280602002602001820160405280156103ea57816020015b6103d76109a4565b8152602001906001900390816103cf5790505b5093506103f685610738565b91505b61040282610780565b1561043857610410826107aa565b848281518110151561041e57fe5b9060200190602002018190525080806001019150506103f9565b505050919050565b60008060008090505b601481101561051e576008810260ff7f0100000000000000000000000000000000000000000000000000000000000000028683870181518110151561048a57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166bffffffffffffffffffffffff19169060020a9004821791508080600101915050610449565b819250505092915050565b6105316109be565b60008083519150600082141561055f576040805190810160405280600081526020016000815250925061057d565b60208401905060408051908101604052808281526020018381525092505b5050919050565b600061058f82610806565b6001029050919050565b6000806000836020015114156105b257600091506105c4565b8260000151905060c0815160001a1091505b50919050565b60008060008060006105db86610599565b15156105e657600080fd5b85600001519150815160001a925060808310156106095781945060019350610643565b60b88310156106275760018660200151039350600182019450610642565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b60006020601f83010484602085015b828414610679576020840280830151818301526001850194505061065a565b6000865160200187015250505050505050565b6000806000836020015114156106a557600091506106b8565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806106d08761068c565b15156106df576000955061072e565b86600001519350835160001a94506106f68761085d565b840192506001876020015185010391505b818311151561072a57610719836108e9565b830192508080600101915050610707565b8095505b5050505050919050565b610740610983565b600061074b8361068c565b151561075657600080fd5b61075f8361085d565b83600001510190508282600001819052508082602001818152505050919050565b600061078a6109be565b826000015190508060200151816000015101836020015110915050919050565b6107b26109be565b6000806107be84610780565b156107fa57836020015191506107d3826108e9565b905081836000018181525050808360200181815250508082018460200181815250506107ff565b600080fd5b5050919050565b600080600061081484610599565b151561081f57600080fd5b610828846105ca565b8092508193505050602081118061083f5750600081145b1561084957600080fd5b806020036101000a82510492505050919050565b6000806000808460200151141561087757600092506108e2565b83600001519050805160001a9150608082101561089757600092506108e2565b60b88210806108b3575060c082101580156108b2575060f882105b5b156108c157600192506108e2565b60c08210156108d857600160b783030192506108e2565b600160f783030192505b5050919050565b600080825160001a90506080811015610905576001915061097d565b60b881101561091c5760016080820301915061097c565b60c08110156109465760b78103806020036101000a6001850151048082016001019350505061097b565b60f881101561095d57600160c0820301915061097a565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b6060604051908101604052806109976109a4565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820ae330ff4f4daf5371c9b66efc45e903b69b3f8105cbc27013d8036c6cdaf43fb0029 \ No newline at end of file diff --git a/contracts/Function.sol b/contracts/Function.sol index b9467f3..b8572c8 100644 --- a/contracts/Function.sol +++ b/contracts/Function.sol @@ -34,7 +34,7 @@ contract Function is IonCompatible { /* Constructor. Requires Ion contract address and all used event verifier contract addresses. In this case we only use one verifier. */ constructor(address _ionAddr, address _verifierAddr) IonCompatible(_ionAddr) public { - verifier = TriggerEventVerifier(_verifierAddr); + // verifier = TriggerEventVerifier(_verifierAddr); } /* This is the function that is intended to be executed upon successful verification of proofs */ diff --git a/contracts/Ion.sol b/contracts/Ion.sol index bae09d3..4d6e2a4 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -21,13 +21,14 @@ contract Ion { } - address[] public validators; + // address[] public validators; bytes32 public blockHash; bytes32 public chainId; + bytes32[] public registeredChains; uint256 public blockHeight; mapping (bytes32 => bool) public chains; - mapping (bytes32 => address) public validation_addr; + mapping (bytes32 => address) public m_validation; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; @@ -72,8 +73,16 @@ contract Ion { _; } + /* + * onlyExistingBlocks + * param: _id (bytes32) Unique id of chain supplied to function + * param: _hash (bytes32) Block hash which needs validation + * + * Modifier that checks if the provided block hash has been verified by the validation contract + */ modifier onlyExistingBlocks(bytes32 _id, bytes32 _hash) { - require(m_blockhashes[_id][_hash], "Block does not exist for chain"); + Validation validation = Validation(m_validation[_id]); + require(validation.m_blockhashes(_id, _hash), "Block does not exist for chain"); _; } @@ -95,24 +104,17 @@ contract Ion { * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. */ - function RegisterChain(bytes32 _id, address validationAddr, address[] _validators, bytes32 _genesisHash) public { + function RegisterChain(bytes32 _id, address validationAddr) public { require( _id != chainId, "Cannot add this chain id to chain register" ); require(!chains[_id], "Chain already exists" ); chains[_id] = true; + registeredChains.push(_id); - for (uint256 i = 0; i < _validators.length; i++) { - m_validators[_id][_validators[i]] = true; - } - - m_blockhashes[_id][_genesisHash] = true; - m_blockheaders[_id][_genesisHash].blockHeight = 0; - - // Instantiate validation - Validation validation = Validation(validationAddr); - validation.InitChain(_id, _validators, _genesisHash); + // m_blockhashes[_id][_genesisHash] = true; + // m_blockheaders[_id][_genesisHash].blockHeight = 0; // Create mapping of registered _id to the validation address - validation_addr[_id] = validationAddr; + m_validation[_id] = validationAddr; } /* @@ -124,41 +126,29 @@ contract Ion { * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered * and if valid the block is persisted as BlockHeader structs defined above. */ - function SubmitBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { - RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); - RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); + // function SubmitBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { + // RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); + // RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); - // Instantiate validation - address validationAddr = validation_addr[_id]; - Validation validation = Validation(validationAddr); - validation.ValidateBlock(_id, _rlpBlockHeader, _rlpSignedBlockHeader); + // // Instantiate validation + // address validationAddr = validation_addr[_id]; + // Validation validation = Validation(validationAddr); + // validation.ValidateBlock(_id, _rlpBlockHeader, _rlpSignedBlockHeader); - // Append the new block to the struct - bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header[0].toBytes(), 1); - bytes32 _blockHash = keccak256(_rlpSignedBlockHeader); - uint256 blockHeight = m_blockheaders[_id][_parentBlockHash].blockHeight + 1; + // // Append the new block to the struct + // bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header[0].toBytes(), 1); + // bytes32 _blockHash = keccak256(_rlpSignedBlockHeader); + // uint256 blockHeight = m_blockheaders[_id][_parentBlockHash].blockHeight + 1; - // Add the updates to the m_blockheaders - m_blockheaders[_id][_blockHash].blockHeight = blockHeight; - m_blockheaders[_id][_blockHash].prevBlockHash = _parentBlockHash; - m_blockheaders[_id][_blockHash].txRootHash = SolUtils.BytesToBytes32(header[4].toBytes(), 1); - m_blockheaders[_id][_blockHash].receiptRootHash = SolUtils.BytesToBytes32(header[5].toBytes(), 1); + // // Add the updates to the m_blockheaders + // m_blockheaders[_id][_blockHash].blockHeight = blockHeight; + // m_blockheaders[_id][_blockHash].prevBlockHash = _parentBlockHash; + // m_blockheaders[_id][_blockHash].txRootHash = SolUtils.BytesToBytes32(header[4].toBytes(), 1); + // m_blockheaders[_id][_blockHash].receiptRootHash = SolUtils.BytesToBytes32(header[5].toBytes(), 1); - addBlockHashToChain(_id, _blockHash); + // addBlockHashToChain(_id, _blockHash); - } - - function recoverSignature(bytes32 _id, bytes signedHeader, bytes _rlpBlockHeader) internal { - bytes memory extraDataSig = new bytes(65); - uint256 length = signedHeader.length; - SolUtils.BytesToBytes(extraDataSig, signedHeader, length-65); - - // Recover the signature of - address sigAddr = ECVerify.ecrecovery(keccak256(_rlpBlockHeader), extraDataSig); - require(m_validators[_id][sigAddr]==true, "Signer not a validator!"); - - emit broadcastSignature(sigAddr); - } + // } /* * CheckTxProof @@ -189,8 +179,10 @@ contract Ion { public returns (bool) { - BlockHeader storage blockHeader = m_blockheaders[_id][_blockHash]; - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.txRootHash) ); + // Connect to validation contract + Validation validation = Validation(m_validation[_id]); + bytes32 txRootHash = validation.getTxRootHash(_id, _blockHash); + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, txRootHash) ); emit VerifiedProof(_id, _blockHash, uint(ProofType.TX)); return true; @@ -225,8 +217,9 @@ contract Ion { public returns (bool) { - BlockHeader storage blockHeader = m_blockheaders[_id][_blockHash]; - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, blockHeader.receiptRootHash) ); + Validation validation = Validation(m_validation[_id]); + bytes32 receiptRootHash = validation.getReceiptRootHash(_id, _blockHash); + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, receiptRootHash) ); emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); return true; @@ -259,10 +252,13 @@ contract Ion { public returns (bool) { - BlockHeader storage blockHeader = m_blockheaders[_id][_blockHash]; + // BlockHeader storage blockHeader = m_blockheaders[_id][_blockHash]; + Validation validation = Validation(m_validation[_id]); + bytes32 txRootHash = validation.getTxRootHash(_id, _blockHash); + bytes32 receiptRootHash = validation.getReceiptRootHash(_id, _blockHash); - assert( blockHeader.txRootHash == getRootNodeHash(_txNodes) ); - assert( blockHeader.receiptRootHash == getRootNodeHash(_receiptNodes) ); + assert( txRootHash == getRootNodeHash(_txNodes) ); + assert( receiptRootHash == getRootNodeHash(_receiptNodes) ); emit VerifiedProof(_id, _blockHash, uint(ProofType.ROOTS)); return true; diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 0f4cd7f..acf4ef5 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -21,12 +21,13 @@ contract Validation { uint256 blockHeight; bytes32 latestHash; bytes32 prevBlockHash; + bytes32 txRootHash; + bytes32 receiptRootHash; } - mapping (bytes32 => uint256) public blockHeight; mapping (bytes32 => bool) public chains; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; - mapping (bytes32 => BlockHeader) public m_blockheaders; + mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; mapping (bytes32 => mapping (address => bool)) public m_validators; event broadcastSignature(address signer); @@ -42,13 +43,13 @@ contract Validation { /* - * InitChain + * RegisterChain * param: chainId (bytes32) Unique id of another chain to interoperate with * * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. */ - function InitChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { + function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { require( _id != chainId, "Cannot add this chain id to chain register" ); require(!chains[_id], "Chain already exists" ); chains[_id] = true; @@ -58,9 +59,8 @@ contract Validation { m_validators[_id][_validators[i]] = true; } - // m_blockhashes[_id][_genesisHash] = true; - m_blockheaders[_id].blockHeight = 0; - m_blockheaders[_id].latestHash = _genesisHash; + m_blockheaders[_id][_genesisHash].blockHeight = 0; + m_blockhashes[_id][_genesisHash] = true; } /* @@ -72,7 +72,7 @@ contract Validation { * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered * and if valid the block is persisted as BlockHeader structs defined above. */ - function ValidateBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { + function SubmitBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) onlyRegisteredChains(_id) public { RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); @@ -88,7 +88,7 @@ contract Validation { // Check the parent hash is the same as the previous block submitted bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header[0].toBytes(), 1); - require(m_blockheaders[_id].latestHash==_parentBlockHash, "Not child of previous block!"); + require(m_blockhashes[_id][_parentBlockHash], "Not child of previous block!"); // Check the blockhash bytes32 _blockHash = keccak256(_rlpSignedBlockHeader); @@ -97,9 +97,11 @@ contract Validation { recoverSignature(_id, signedHeader[12].toBytes(), _rlpBlockHeader); // Append the new block to the struct - m_blockheaders[_id].blockHeight++; - m_blockheaders[_id].latestHash = _blockHash; - m_blockheaders[_id].prevBlockHash = _parentBlockHash; + m_blockheaders[_id][_blockHash].blockHeight = header[8].toUint(); + m_blockheaders[_id][_blockHash].latestHash = _blockHash; + m_blockheaders[_id][_blockHash].prevBlockHash = _parentBlockHash; + m_blockheaders[_id][_blockHash].txRootHash = SolUtils.BytesToBytes32(header[4].toBytes(), 1); + m_blockheaders[_id][_blockHash].receiptRootHash = SolUtils.BytesToBytes32(header[5].toBytes(), 1); addBlockHashToChain(_id, _blockHash); @@ -112,20 +114,39 @@ contract Validation { // Recover the signature of address sigAddr = ECVerify.ecrecovery(keccak256(_rlpBlockHeader), extraDataSig); - require(m_validators[_id][sigAddr]==true, "Signer not a validator!"); + require(m_validators[_id][sigAddr], "Signer not a validator!"); emit broadcastSignature(sigAddr); } /* * @description when a block is submitted the root hash must be added to a mapping of chains to hashes - * @param _chainId unique identifier of the chain from which the block hails + * @param _id unique identifier of the chain from which the block hails * @param _hash root hash of the block being added */ - function addBlockHashToChain(bytes32 _chainId, bytes32 _hash) internal { - m_blockhashes[_chainId][_hash] = true; + function addBlockHashToChain(bytes32 _id, bytes32 _hash) internal { + m_blockhashes[_id][_hash] = true; } + /* + * @description returns the transaction root hash of a specific block + * @param _id unique identifier of the chain from which the block hails + * @param _hash root hash of the block being queried + */ + function getTxRootHash(bytes32 _id, bytes32 _hash) public returns(bytes32) { + return(m_blockheaders[_id][_hash].txRootHash); + } + + /* + * @description returns the receipt root hash of a specific block + * @param _id unique identifier of the chain from which the block hails + * @param _hash root hash of the block being queried + */ + function getReceiptRootHash(bytes32 _id, bytes32 _hash) public returns(bytes32) { + return(m_blockheaders[_id][_hash].receiptRootHash); + } + + /* * onlyRegisteredChains * param: _id (bytes32) Unique id of chain supplied to function diff --git a/docs/TransactionVerification.md b/docs/TransactionVerification.md deleted file mode 100644 index f2ba55c..0000000 --- a/docs/TransactionVerification.md +++ /dev/null @@ -1,2 +0,0 @@ -# Transaction Verification -As part of the Ion Stage 2 project in order to perform continuous execution it is necessary to prove that an event was emitted. In Ethereum this information is \ No newline at end of file diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index c252ef5..0be2d90 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -19,7 +19,7 @@ import ( ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contract.Validation) { +func Launch(setup config.Setup, clientFrom *ethclient.Client, Ion *contract.Ion) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -39,7 +39,6 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra auth.GasLimit = uint64(300000) // in units auth.GasPrice = gasPrice - // Get the latest block number shell.AddCmd(&ishell.Cmd{ Name: "latestBlock", Help: "use: latestBlock \n\t\t\t\tdescription: Returns number of latest block mined/sealed", @@ -52,7 +51,6 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra }, }) - // Get block N shell.AddCmd(&ishell.Cmd{ Name: "getBlock", Help: "use: getBlock [integer] \n\t\t\t\tdescription: Returns block header specified", @@ -71,106 +69,164 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra }) shell.AddCmd(&ishell.Cmd{ - Name: "getValidators", - Help: "use: getValidators \n\t\t\t\tdescription: Returns the whitelist of validators from validator contract", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrFrom) - result, err := Validation.GetValidators(&bind.CallOpts{}) - if err != nil { - fmt.Printf("Error: %s", err) - return - } - c.Println("Validators Whitelist:") - c.Printf("%x\n", result) - - c.Println("===============================================================") - }, - }) - - shell.AddCmd(&ishell.Cmd{ - Name: "latestValidationBlock", - Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Name: "ionChainId", + Help: "use: ionChainId \n\t\t\t\tdescription: Returns id of Ion chain", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) - result, err := Validation.LatestBlock(&bind.CallOpts{}) - if err != nil { - fmt.Printf("Error: %s", err) - return - } - c.Println("Last Block Submitted:") - c.Printf("0x%x\n", result) - - c.Println("===============================================================") - }, - }) - - shell.AddCmd(&ishell.Cmd{ - Name: "getValidationBlock", - Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrFrom) - blockNum := new(big.Int) - blockNum.SetString(c.Args[0], 10) - result, err := Validation.GetBlock(&bind.CallOpts{}, blockNum) - if err != nil { - fmt.Printf("Error: %s", err) - return + if len(c.Args) == 0 { + result, err := Ion.ChainId(&bind.CallOpts{}) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("Result:\t%x\n", result) + } else if len(c.Args) > 0 { + c.Println("Only enter single argument") } - c.Println("Last Block Submitted:") - c.Printf("Block:\n\t%x\n", result.BlockHeight) - c.Printf("Hash:\n\t0x%x\n", result.BlockHash) - c.Printf("Parent Hash:\n\t0x%x\n", result.PrevBlockHash) - c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ - Name: "submitValidationBlock", - Help: "use: submitValidationBlock [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", + Name: "ionRegisteredChains", + Help: "use: ionRegisteredChains \n\t\t\t\tdescription: Returns array of all registered chains", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) if len(c.Args) == 0 { - c.Println("Select a block") - } else if len(c.Args) > 1 { - c.Println("Too many arguments entered.") - } else { - c.Println("RLP encode block: " + c.Args[0]) - encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(clientFrom, c.Args[0]) - res, err := Validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) + result, err := Ion.RegisteredChains(&bind.CallOpts{}, big.NewInt(0)) if err != nil { c.Printf("Error: %s", err) return } - c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) + c.Printf("Result:\t%s\n", result) + } else if len(c.Args) > 0 { + c.Println("Only enter single argument") } c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ - Name: "generateTxProof", - Help: "use: generateTxProof [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Name: "ionRegisterChain", + Help: "use: ionRegisterChain \n\t\t\t\tdescription: Register chain with Ion contract", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) - if len(c.Args) == 0 { - c.Println("Select a block") - } else if len(c.Args) > 2 { - c.Println("Too many arguments entered.") - } else { - c.Println("RLP encode block: " + c.Args[0]) - rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) - c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) - } + c.ShowPrompt(false) + defer c.ShowPrompt(true) // yes, revert after login. + + // Get the chainId + c.Print("New ChainId: ") + chainId := c.ReadLine() + + c.Printf("Running Command:\t%s\t%s", chainId c.Println("===============================================================") }, }) + // shell.AddCmd(&ishell.Cmd{ + // Name: "getValidators", + // Help: "use: getValidators \n\t\t\t\tdescription: Returns the whitelist of validators from validator contract", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrFrom) + // result, err := Validation.GetValidators(&bind.CallOpts{}) + // if err != nil { + // fmt.Printf("Error: %s", err) + // return + // } + // c.Println("Validators Whitelist:") + // c.Printf("%x\n", result) + + // c.Println("===============================================================") + // }, + // }) + + // shell.AddCmd(&ishell.Cmd{ + // Name: "latestValidationBlock", + // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrTo) + // result, err := Validation.LatestBlock(&bind.CallOpts{}) + // if err != nil { + // fmt.Printf("Error: %s", err) + // return + // } + // c.Println("Last Block Submitted:") + // c.Printf("0x%x\n", result) + + // c.Println("===============================================================") + // }, + // }) + + // shell.AddCmd(&ishell.Cmd{ + // Name: "getValidationBlock", + // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrFrom) + // blockNum := new(big.Int) + // blockNum.SetString(c.Args[0], 10) + // result, err := Validation.GetBlock(&bind.CallOpts{}, blockNum) + // if err != nil { + // fmt.Printf("Error: %s", err) + // return + // } + // c.Println("Last Block Submitted:") + // c.Printf("Block:\n\t%x\n", result.BlockHeight) + // c.Printf("Hash:\n\t0x%x\n", result.BlockHash) + // c.Printf("Parent Hash:\n\t0x%x\n", result.PrevBlockHash) + + // c.Println("===============================================================") + // }, + // }) + + // shell.AddCmd(&ishell.Cmd{ + // Name: "submitValidationBlock", + // Help: "use: submitValidationBlock [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrTo) + // if len(c.Args) == 0 { + // c.Println("Select a block") + // } else if len(c.Args) > 1 { + // c.Println("Too many arguments entered.") + // } else { + // c.Println("RLP encode block: " + c.Args[0]) + // encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(clientFrom, c.Args[0]) + // res, err := Validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } + // c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) + // } + // c.Println("===============================================================") + // }, + // }) + + // shell.AddCmd(&ishell.Cmd{ + // Name: "generateTxProof", + // Help: "use: generateTxProof [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrTo) + // if len(c.Args) == 0 { + // c.Println("Select a block") + // } else if len(c.Args) > 2 { + // c.Println("Too many arguments entered.") + // } else { + // c.Println("RLP encode block: " + c.Args[0]) + // rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) + // c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) + // } + // c.Println("===============================================================") + // }, + // }) + //--------------------------------------------------------------------------------------------- // Ion Specific Commands // diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index 0b4ef21..4fa8c25 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -20,10 +20,10 @@ func InitClient(addr string) (clientTo *ethclient.Client) { return } -func InitValidationContract(setup Setup, client *ethclient.Client) (Validation *contract.Validation) { +func InitValidationContract(setup Setup, client *ethclient.Client) (Ion *contract.Ion) { // Initialise the contract address := common.HexToAddress(setup.Ion) - Validation, err := contract.NewValidation(address, client) + Ion, err := contract.NewIon(address, client) if err != nil { log.Fatal(err) } diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go index d57d8ca..df0ff96 100644 --- a/ion-cli/contracts/ion.go +++ b/ion-cli/contracts/ion.go @@ -4,7 +4,6 @@ package contract import ( - "encoding/hex" "math/big" "strings" @@ -17,10 +16,10 @@ import ( ) // IonABI is the input ABI used to generate the binding from. -const IonABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"chains\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"CheckReceiptProof\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_rlpBlockHeader\",\"type\":\"bytes\"}],\"name\":\"SubmitBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockHash\",\"type\":\"bytes32\"}],\"name\":\"getBlockHeader\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[3]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"txRootHash\",\"type\":\"bytes32\"},{\"name\":\"receiptRootHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"}],\"name\":\"RegisterChain\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"}],\"name\":\"CheckTxProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"CheckRootsProof\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"m_blockhashes\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"chainId\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"VerifiedTxProof\",\"type\":\"event\"}]" +const IonABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"registeredChains\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"validation_addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockhashes\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_rlpBlockHeader\",\"type\":\"bytes\"},{\"name\":\"_rlpSignedBlockHeader\",\"type\":\"bytes\"}],\"name\":\"SubmitBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"m_validators\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"validationAddr\",\"type\":\"address\"},{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"_genesisHash\",\"type\":\"bytes32\"}],\"name\":\"RegisterChain\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"}],\"name\":\"CheckTxProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"}],\"name\":\"CheckReceiptProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"chains\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"blockHeight\",\"type\":\"uint256\"},{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"txRootHash\",\"type\":\"bytes32\"},{\"name\":\"receiptRootHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockHash\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockHeight\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_txNodes\",\"type\":\"bytes\"},{\"name\":\"_receiptNodes\",\"type\":\"bytes\"}],\"name\":\"CheckRootsProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"chainId\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"proofType\",\"type\":\"uint256\"}],\"name\":\"VerifiedProof\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"broadcastSignature\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" // IonBin is the compiled bytecode used for deploying new contracts. -const IonBin = `608060405234801561001057600080fd5b50604051602080611487833981018060405281019080805190602001909291905050508060008160001916905550506114398061004e6000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063550325b5146100a957806359349832146100f25780635a0235e4146101095780636b4f9b9d1461018e578063927a32e3146101fb5780639a8a0592146102665780639e43d86b14610299578063affd8be9146102ca578063e318df54146103f3578063fecc37c31461040a575b600080fd5b3480156100b557600080fd5b506100d460048036038101908080359060200190929190505050610461565b60405180826000191660001916815260200191505060405180910390f35b3480156100fe57600080fd5b50610107610484565b005b34801561011557600080fd5b5061018c60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610486565b005b34801561019a57600080fd5b506101bd60048036038101908080356000191690602001909291905050506106be565b6040518082600360200280838360005b838110156101e85780820151818401526020810190506101cd565b5050505090500191505060405180910390f35b34801561020757600080fd5b5061022a600480360381019080803560001916906020019092919050505061072d565b60405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b34801561027257600080fd5b5061027b610757565b60405180826000191660001916815260200191505060405180910390f35b3480156102a557600080fd5b506102c8600480360381019080803560001916906020019092919050505061075d565b005b3480156102d657600080fd5b506103d960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108f4565b604051808215151515815260200191505060405180910390f35b3480156103ff57600080fd5b50610408610d83565b005b34801561041657600080fd5b50610443600480360381019080803560001916906020019092919080359060200190929190505050610d85565b60405180826000191660001916815260200191505060405180910390f35b60018181548110151561047057fe5b906000526020600020016000915090505481565b565b60606000808560008060009150600090505b6001805490508110156104e4576001818154811015156104b457fe5b906000526020600020015460001916836000191614156104d757600191506104e4565b8080600101915050610498565b811515610559576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61056a61056588610db5565b610e10565b9550866040518082805190602001908083835b6020831015156105a2578051825260208201915060208101905060208303925061057d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209450876000191685600019161415156105e757600080fd5b600360008960001916600019168152602001908152602001600020935061062f61062887600081518110151561061957fe5b90602001906020020151610ecd565b6001610f32565b84600001816000191690555061066661065f87600481518110151561065057fe5b90602001906020020151610ecd565b6001610f32565b84600101816000191690555061069d61069687600581518110151561068757fe5b90602001906020020151610ecd565b6001610f32565b8460020181600019169055506106b38989611010565b505050505050505050565b6106c6611395565b6000600360008460001916600019168152602001908152602001600020905060606040519081016040528082600001546000191660001916815260200182600101546000191660001916815260200182600201546000191660001916815250915050919050565b60036020528060005260406000206000915090508060000154908060010154908060020154905083565b60005481565b6000805460001916826000191614151515610806576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600090505b6001805490508110156108be57816000191660018281548110151561082c57fe5b906000526020600020015460001916141515156108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b808060010191505061080b565b60018290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055505050565b6000808660008060009150600090505b6001805490508110156109505760018181548110151561092057fe5b906000526020600020015460001916836000191614156109435760019150610950565b8080600101915050610904565b8115156109c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8989600060606000809250600260008660001916600019168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610a3957602002820191906000526020600020905b81546000191681526020019060010190808311610a21575b50505050509150600090505b8151811015610a8b578181815181101515610a5c57fe5b906020019060200201516000191684600019161415610a7e5760019250610a8b565b8080600101915050610a45565b821515610b00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600360008f60001916600019168152602001908152602001600020985073__./contracts/libraries/PatriciaTrie.s__634f7142ad8e8e8e8d600101546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610bc0578082015181840152602081019050610ba5565b50505050905090810190601f168015610bed5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610c26578082015181840152602081019050610c0b565b50505050905090810190601f168015610c535780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610c8c578082015181840152602081019050610c71565b50505050905090810190601f168015610cb95780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610cdb57600080fd5b505af4158015610cef573d6000803e3d6000fd5b505050506040513d6020811015610d0557600080fd5b81019080805190602001909291905050501515610d1e57fe5b7f202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a18f8f60405180836000191660001916815260200182600019166000191681526020019250505060405180910390a16001995050505050505050505095945050505050565b565b600260205281600052604060002081815481101515610da057fe5b90600052602060002001600091509150505481565b610dbd6113b8565b600080835191506000821415610deb5760408051908101604052806000815260200160008152509250610e09565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610e1c6113d2565b6000610e27856110b4565b1515610e3257600080fd5b610e3b856110e6565b925082604051908082528060200260200182016040528015610e7757816020015b610e646113f3565b815260200190600190039081610e5c5790505b509350610e8385611160565b91505b610e8f826111a8565b15610ec557610e9d826111d2565b8482815181101515610eab57fe5b906020019060200201819052508080600101915050610e86565b505050919050565b60606000826020015190506000811415610ee657610f2c565b806040519080825280601f01601f191660200182016040528015610f195781602001602082028038833980820191505090505b509150610f2b8360000151838361122e565b5b50919050565b60008060008090505b6020811015611005576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610f7c57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610f3b565b819250505092915050565b6000806002600085600019166000191681526020019081526020016000209150600090505b818054905081101561107d578260001916828281548110151561105457fe5b9060005260206000200154600019161415151561107057600080fd5b8080600101915050611035565b8183908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555050505050565b6000806000836020015114156110cd57600091506110e0565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806110f8876110b4565b15156111075760009550611156565b86600001519350835160001a945061111e8761126f565b840192506001876020015185010391505b818311151561115257611141836112fb565b83019250808060010191505061112f565b8095505b5050505050919050565b6111686113d2565b6000611173836110b4565b151561117e57600080fd5b6111878361126f565b83600001510190508282600001819052508082602001818152505050919050565b60006111b26113b8565b826000015190508060200151816000015101836020015110915050919050565b6111da6113b8565b6000806111e6846111a8565b1561122257836020015191506111fb826112fb565b90508183600001818152505080836020018181525050808201846020018181525050611227565b600080fd5b5050919050565b60006020601f83010484602085015b82841461125c576020840280830151818301526001850194505061123d565b6000865160200187015250505050505050565b6000806000808460200151141561128957600092506112f4565b83600001519050805160001a915060808210156112a957600092506112f4565b60b88210806112c5575060c082101580156112c4575060f882105b5b156112d357600192506112f4565b60c08210156112ea57600160b783030192506112f4565b600160f783030192505b5050919050565b600080825160001a90506080811015611317576001915061138f565b60b881101561132e5760016080820301915061138e565b60c08110156113585760b78103806020036101000a6001850151048082016001019350505061138d565b60f881101561136f57600160c0820301915061138c565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b606060405190810160405280600390602082028038833980820191505090505090565b604080519081016040528060008152602001600081525090565b6060604051908101604052806113e66113f3565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582092fe2217ce4fc7e2c1df216da8d39cd9ccf25c15d607088915e2dede2778065d0029` +const IonBin = `608060405234801561001057600080fd5b5060405160208061221f833981018060405281019080805190602001909291905050508060018160001916905550506121d18061004e6000396000f3006080604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100d5578063261e50731461011e5780634b3550301461018f57806352824374146101e657806353fe62e6146102a35780637558a01a1461030c5780639a8a0592146103ae578063affd8be9146103e1578063bec205b91461050a578063c18de0ef14610633578063e79b136c1461067c578063f22a195e146106fc578063f44ff7121461072f578063f484c1f71461075a575b600080fd5b3480156100e157600080fd5b506101006004803603810190808035906020019092919050505061083d565b60405180826000191660001916815260200191505060405180910390f35b34801561012a57600080fd5b5061014d6004803603810190808035600019169060200190929190505050610860565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561019b57600080fd5b506101cc60048036038101908080356000191690602001909291908035600019169060200190929190505050610893565b604051808215151515815260200191505060405180910390f35b3480156101f257600080fd5b506102a16004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108c2565b005b3480156102af57600080fd5b506102f26004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d71565b604051808215151515815260200191505060405180910390f35b34801561031857600080fd5b506103ac6004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035600019169060200190929190505050610da0565b005b3480156103ba57600080fd5b506103c3611124565b60405180826000191660001916815260200191505060405180910390f35b3480156103ed57600080fd5b506104f060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061112a565b604051808215151515815260200191505060405180910390f35b34801561051657600080fd5b5061061960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061152e565b604051808215151515815260200191505060405180910390f35b34801561063f57600080fd5b506106626004803603810190808035600019169060200190929190505050611932565b604051808215151515815260200191505060405180910390f35b34801561068857600080fd5b506106b960048036038101908080356000191690602001909291908035600019169060200190929190505050611952565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b34801561070857600080fd5b5061071161198f565b60405180826000191660001916815260200191505060405180910390f35b34801561073b57600080fd5b50610744611995565b6040518082815260200191505060405180910390f35b34801561076657600080fd5b5061082360048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199b565b604051808215151515815260200191505060405180910390f35b60028181548110151561084c57fe5b906000526020600020016000915090505481565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008060008960046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561096b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61097c6109778b611bda565b611c35565b975061098f61098a8a611bda565b611c35565b9650600560008c6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508594508473ffffffffffffffffffffffffffffffffffffffff166309fbd5368c8c8c6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610a6e578082015181840152602081019050610a53565b50505050905090810190601f168015610a9b5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610ad4578082015181840152602081019050610ab9565b50505050905090810190601f168015610b015780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015610b2357600080fd5b505af1158015610b37573d6000803e3d6000fd5b50505050610b66610b5f896000815181101515610b5057fe5b90602001906020020151611cf2565b6001611d57565b9350886040518082805190602001908083835b602083101515610b9e5780518252602082019150602081019050602083039250610b79565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092506001600760008d60001916600019168152602001908152602001600020600086600019166000191681526020019081526020016000206000015401915081600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206000018190555083600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206001018160001916905550610cb1610caa896004815181101515610c9b57fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206002018160001916905550610d1b610d14896005815181101515610d0557fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206003018160001916905550610d648b84611d6b565b5050505050505050505050565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600060015460001916856000191614151515610e4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000866000191660001916815260200190815260200160002060009054906101000a900460ff16151515610ee8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000876000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600285908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555060016006600087600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600060076000876000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600001819055508390508073ffffffffffffffffffffffffffffffffffffffff16630b5abdd08685856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808460001916600019168152602001806020018360001916600019168152602001828103825284818151815260200191508051906020019060200280838360005b83811015611084578082015181840152602081019050611069565b50505050905001945050505050600060405180830381600087803b1580156110ab57600080fd5b505af11580156110bf573d6000803e3d6000fd5b505050508360056000876000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b60015481565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156111cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600201546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b8381101561135c578082015181840152602081019050611341565b50505050905090810190601f1680156113895780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156113c25780820151818401526020810190506113a7565b50505050905090810190601f1680156113ef5780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561142857808201518184015260208101905061140d565b50505050905090810190601f1680156114555780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561147757600080fd5b505af415801561148b573d6000803e3d6000fd5b505050506040513d60208110156114a157600080fd5b810190808051906020019092919050505015156114ba57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600060028111156114ea57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156115cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611687576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600301546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611760578082015181840152602081019050611745565b50505050905090810190601f16801561178d5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156117c65780820151818401526020810190506117ab565b50505050905090810190601f1680156117f35780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561182c578082015181840152602081019050611811565b50505050905090810190601f1680156118595780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561187b57600080fd5b505af415801561188f573d6000803e3d6000fd5b505050506040513d60208110156118a557600080fd5b810190808051906020019092919050505015156118be57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600160028111156118ee57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000808560046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611a3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b86866006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611af4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008a60001916600019168152602001908152602001600020600089600019166000191681526020019081526020016000209350611b3387611dbc565b60001916846002015460001916141515611b4957fe5b611b5286611dbc565b60001916846003015460001916141515611b6857fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468989600280811115611b9757fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001945050505050949350505050565b611be2612150565b600080835191506000821415611c105760408051908101604052806000815260200160008152509250611c2e565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611c4161216a565b6000611c4c85611e6f565b1515611c5757600080fd5b611c6085611ea1565b925082604051908082528060200260200182016040528015611c9c57816020015b611c8961218b565b815260200190600190039081611c815790505b509350611ca885611f1b565b91505b611cb482611f63565b15611cea57611cc282611f8d565b8482815181101515611cd057fe5b906020019060200201819052508080600101915050611cab565b505050919050565b60606000826020015190506000811415611d0b57611d51565b806040519080825280601f01601f191660200182016040528015611d3e5781602001602082028038833980820191505090505b509150611d5083600001518383611fe9565b5b50919050565b600060208201915081830151905092915050565b60016006600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000611dc6612150565b606080611dd285611bda565b9250611ddd83611c35565b9150611e00826000815181101515611df157fe5b90602001906020020151611cf2565b9050806040518082805190602001908083835b602083101515611e385780518252602082019150602081019050602083039250611e13565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b600080600083602001511415611e885760009150611e9b565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611eb387611e6f565b1515611ec25760009550611f11565b86600001519350835160001a9450611ed98761202a565b840192506001876020015185010391505b8183111515611f0d57611efc836120b6565b830192508080600101915050611eea565b8095505b5050505050919050565b611f2361216a565b6000611f2e83611e6f565b1515611f3957600080fd5b611f428361202a565b83600001510190508282600001819052508082602001818152505050919050565b6000611f6d612150565b826000015190508060200151816000015101836020015110915050919050565b611f95612150565b600080611fa184611f63565b15611fdd5783602001519150611fb6826120b6565b90508183600001818152505080836020018181525050808201846020018181525050611fe2565b600080fd5b5050919050565b60006020601f83010484602085015b8284146120175760208402808301518183015260018501945050611ff8565b6000865160200187015250505050505050565b6000806000808460200151141561204457600092506120af565b83600001519050805160001a9150608082101561206457600092506120af565b60b8821080612080575060c0821015801561207f575060f882105b5b1561208e57600192506120af565b60c08210156120a557600160b783030192506120af565b600160f783030192505b5050919050565b600080825160001a905060808110156120d2576001915061214a565b60b88110156120e957600160808203019150612149565b60c08110156121135760b78103806020036101000a60018501510480820160010193505050612148565b60f881101561212a57600160c08203019150612147565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b60606040519081016040528061217e61218b565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582063bd23fd4aba60ad5fe5003097cfeb975ac723f7e78172be2b48321603b5cabd0029` // DeployIon deploys a new Ethereum contract, binding an instance of Ion to it. func DeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte) (common.Address, *types.Transaction, *Ion, error) { @@ -35,35 +34,6 @@ func DeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]by return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil } -func LinkDeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte, linkAddr common.Address, linkString string) (common.Address, *types.Transaction, *Ion, error) { - // Convert address to string and replace library reference in Bin - linkAddrStr := hex.EncodeToString(linkAddr.Bytes()) - NewIonBin := strings.Replace(IonBin, linkString, linkAddrStr, 1) - - parsed, err := abi.JSON(strings.NewReader(IonABI)) - if err != nil { - return common.Address{}, nil, nil, err - } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(NewIonBin), backend, _id) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil -} - -// Deploy and Link Ion to libraries -// func LinkDeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte, linkAddr common.Address) (common.Address, *types.Transaction, *Ion, error) { -// parsed, err := abi.JSON(strings.NewReader(IonABI)) -// if err != nil { -// return common.Address{}, nil, nil, err -// } -// address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(IonBin), backend, _id) -// if err != nil { -// return common.Address{}, nil, nil, err -// } -// return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil -// } - // Ion is an auto generated Go binding around an Ethereum contract. type Ion struct { IonCaller // Read-only binding to the contract @@ -206,52 +176,56 @@ func (_Ion *IonTransactorRaw) Transact(opts *bind.TransactOpts, method string, p return _Ion.Contract.contract.Transact(opts, method, params...) } -// CheckReceiptProof is a free data retrieval call binding the contract method 0x59349832. +// BlockHash is a free data retrieval call binding the contract method 0xf22a195e. // -// Solidity: function CheckReceiptProof() constant returns() -func (_Ion *IonCaller) CheckReceiptProof(opts *bind.CallOpts) error { - var () - out := &[]interface{}{} - err := _Ion.contract.Call(opts, out, "CheckReceiptProof") - return err +// Solidity: function blockHash() constant returns(bytes32) +func (_Ion *IonCaller) BlockHash(opts *bind.CallOpts) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "blockHash") + return *ret0, err } -// CheckReceiptProof is a free data retrieval call binding the contract method 0x59349832. +// BlockHash is a free data retrieval call binding the contract method 0xf22a195e. // -// Solidity: function CheckReceiptProof() constant returns() -func (_Ion *IonSession) CheckReceiptProof() error { - return _Ion.Contract.CheckReceiptProof(&_Ion.CallOpts) +// Solidity: function blockHash() constant returns(bytes32) +func (_Ion *IonSession) BlockHash() ([32]byte, error) { + return _Ion.Contract.BlockHash(&_Ion.CallOpts) } -// CheckReceiptProof is a free data retrieval call binding the contract method 0x59349832. +// BlockHash is a free data retrieval call binding the contract method 0xf22a195e. // -// Solidity: function CheckReceiptProof() constant returns() -func (_Ion *IonCallerSession) CheckReceiptProof() error { - return _Ion.Contract.CheckReceiptProof(&_Ion.CallOpts) +// Solidity: function blockHash() constant returns(bytes32) +func (_Ion *IonCallerSession) BlockHash() ([32]byte, error) { + return _Ion.Contract.BlockHash(&_Ion.CallOpts) } -// CheckRootsProof is a free data retrieval call binding the contract method 0xe318df54. +// BlockHeight is a free data retrieval call binding the contract method 0xf44ff712. // -// Solidity: function CheckRootsProof() constant returns() -func (_Ion *IonCaller) CheckRootsProof(opts *bind.CallOpts) error { - var () - out := &[]interface{}{} - err := _Ion.contract.Call(opts, out, "CheckRootsProof") - return err +// Solidity: function blockHeight() constant returns(uint256) +func (_Ion *IonCaller) BlockHeight(opts *bind.CallOpts) (*big.Int, error) { + var ( + ret0 = new(*big.Int) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "blockHeight") + return *ret0, err } -// CheckRootsProof is a free data retrieval call binding the contract method 0xe318df54. +// BlockHeight is a free data retrieval call binding the contract method 0xf44ff712. // -// Solidity: function CheckRootsProof() constant returns() -func (_Ion *IonSession) CheckRootsProof() error { - return _Ion.Contract.CheckRootsProof(&_Ion.CallOpts) +// Solidity: function blockHeight() constant returns(uint256) +func (_Ion *IonSession) BlockHeight() (*big.Int, error) { + return _Ion.Contract.BlockHeight(&_Ion.CallOpts) } -// CheckRootsProof is a free data retrieval call binding the contract method 0xe318df54. +// BlockHeight is a free data retrieval call binding the contract method 0xf44ff712. // -// Solidity: function CheckRootsProof() constant returns() -func (_Ion *IonCallerSession) CheckRootsProof() error { - return _Ion.Contract.CheckRootsProof(&_Ion.CallOpts) +// Solidity: function blockHeight() constant returns(uint256) +func (_Ion *IonCallerSession) BlockHeight() (*big.Int, error) { + return _Ion.Contract.BlockHeight(&_Ion.CallOpts) } // ChainId is a free data retrieval call binding the contract method 0x9a8a0592. @@ -280,122 +254,220 @@ func (_Ion *IonCallerSession) ChainId() ([32]byte, error) { return _Ion.Contract.ChainId(&_Ion.CallOpts) } -// Chains is a free data retrieval call binding the contract method 0x550325b5. +// Chains is a free data retrieval call binding the contract method 0xc18de0ef. // -// Solidity: function chains( uint256) constant returns(bytes32) -func (_Ion *IonCaller) Chains(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { +// Solidity: function chains( bytes32) constant returns(bool) +func (_Ion *IonCaller) Chains(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { var ( - ret0 = new([32]byte) + ret0 = new(bool) ) out := ret0 err := _Ion.contract.Call(opts, out, "chains", arg0) return *ret0, err } -// Chains is a free data retrieval call binding the contract method 0x550325b5. +// Chains is a free data retrieval call binding the contract method 0xc18de0ef. // -// Solidity: function chains( uint256) constant returns(bytes32) -func (_Ion *IonSession) Chains(arg0 *big.Int) ([32]byte, error) { +// Solidity: function chains( bytes32) constant returns(bool) +func (_Ion *IonSession) Chains(arg0 [32]byte) (bool, error) { return _Ion.Contract.Chains(&_Ion.CallOpts, arg0) } -// Chains is a free data retrieval call binding the contract method 0x550325b5. +// Chains is a free data retrieval call binding the contract method 0xc18de0ef. // -// Solidity: function chains( uint256) constant returns(bytes32) -func (_Ion *IonCallerSession) Chains(arg0 *big.Int) ([32]byte, error) { +// Solidity: function chains( bytes32) constant returns(bool) +func (_Ion *IonCallerSession) Chains(arg0 [32]byte) (bool, error) { return _Ion.Contract.Chains(&_Ion.CallOpts, arg0) } -// GetBlockHeader is a free data retrieval call binding the contract method 0x6b4f9b9d. -// -// Solidity: function getBlockHeader(_blockHash bytes32) constant returns(bytes32[3]) -func (_Ion *IonCaller) GetBlockHeader(opts *bind.CallOpts, _blockHash [32]byte) ([3][32]byte, error) { - var ( - ret0 = new([3][32]byte) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "getBlockHeader", _blockHash) - return *ret0, err -} - -// GetBlockHeader is a free data retrieval call binding the contract method 0x6b4f9b9d. +// MBlockhashes is a free data retrieval call binding the contract method 0x4b355030. // -// Solidity: function getBlockHeader(_blockHash bytes32) constant returns(bytes32[3]) -func (_Ion *IonSession) GetBlockHeader(_blockHash [32]byte) ([3][32]byte, error) { - return _Ion.Contract.GetBlockHeader(&_Ion.CallOpts, _blockHash) -} - -// GetBlockHeader is a free data retrieval call binding the contract method 0x6b4f9b9d. -// -// Solidity: function getBlockHeader(_blockHash bytes32) constant returns(bytes32[3]) -func (_Ion *IonCallerSession) GetBlockHeader(_blockHash [32]byte) ([3][32]byte, error) { - return _Ion.Contract.GetBlockHeader(&_Ion.CallOpts, _blockHash) -} - -// MBlockhashes is a free data retrieval call binding the contract method 0xfecc37c3. -// -// Solidity: function m_blockhashes( bytes32, uint256) constant returns(bytes32) -func (_Ion *IonCaller) MBlockhashes(opts *bind.CallOpts, arg0 [32]byte, arg1 *big.Int) ([32]byte, error) { +// Solidity: function m_blockhashes( bytes32, bytes32) constant returns(bool) +func (_Ion *IonCaller) MBlockhashes(opts *bind.CallOpts, arg0 [32]byte, arg1 [32]byte) (bool, error) { var ( - ret0 = new([32]byte) + ret0 = new(bool) ) out := ret0 err := _Ion.contract.Call(opts, out, "m_blockhashes", arg0, arg1) return *ret0, err } -// MBlockhashes is a free data retrieval call binding the contract method 0xfecc37c3. +// MBlockhashes is a free data retrieval call binding the contract method 0x4b355030. // -// Solidity: function m_blockhashes( bytes32, uint256) constant returns(bytes32) -func (_Ion *IonSession) MBlockhashes(arg0 [32]byte, arg1 *big.Int) ([32]byte, error) { +// Solidity: function m_blockhashes( bytes32, bytes32) constant returns(bool) +func (_Ion *IonSession) MBlockhashes(arg0 [32]byte, arg1 [32]byte) (bool, error) { return _Ion.Contract.MBlockhashes(&_Ion.CallOpts, arg0, arg1) } -// MBlockhashes is a free data retrieval call binding the contract method 0xfecc37c3. +// MBlockhashes is a free data retrieval call binding the contract method 0x4b355030. // -// Solidity: function m_blockhashes( bytes32, uint256) constant returns(bytes32) -func (_Ion *IonCallerSession) MBlockhashes(arg0 [32]byte, arg1 *big.Int) ([32]byte, error) { +// Solidity: function m_blockhashes( bytes32, bytes32) constant returns(bool) +func (_Ion *IonCallerSession) MBlockhashes(arg0 [32]byte, arg1 [32]byte) (bool, error) { return _Ion.Contract.MBlockhashes(&_Ion.CallOpts, arg0, arg1) } -// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// MBlockheaders is a free data retrieval call binding the contract method 0xe79b136c. // -// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) -func (_Ion *IonCaller) MBlockheaders(opts *bind.CallOpts, arg0 [32]byte) (struct { +// Solidity: function m_blockheaders( bytes32, bytes32) constant returns(blockHeight uint256, prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) +func (_Ion *IonCaller) MBlockheaders(opts *bind.CallOpts, arg0 [32]byte, arg1 [32]byte) (struct { + BlockHeight *big.Int PrevBlockHash [32]byte TxRootHash [32]byte ReceiptRootHash [32]byte }, error) { ret := new(struct { + BlockHeight *big.Int PrevBlockHash [32]byte TxRootHash [32]byte ReceiptRootHash [32]byte }) out := ret - err := _Ion.contract.Call(opts, out, "m_blockheaders", arg0) + err := _Ion.contract.Call(opts, out, "m_blockheaders", arg0, arg1) return *ret, err } -// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// MBlockheaders is a free data retrieval call binding the contract method 0xe79b136c. // -// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) -func (_Ion *IonSession) MBlockheaders(arg0 [32]byte) (struct { +// Solidity: function m_blockheaders( bytes32, bytes32) constant returns(blockHeight uint256, prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) +func (_Ion *IonSession) MBlockheaders(arg0 [32]byte, arg1 [32]byte) (struct { + BlockHeight *big.Int PrevBlockHash [32]byte TxRootHash [32]byte ReceiptRootHash [32]byte }, error) { - return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0) + return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0, arg1) } -// MBlockheaders is a free data retrieval call binding the contract method 0x927a32e3. +// MBlockheaders is a free data retrieval call binding the contract method 0xe79b136c. // -// Solidity: function m_blockheaders( bytes32) constant returns(prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) -func (_Ion *IonCallerSession) MBlockheaders(arg0 [32]byte) (struct { +// Solidity: function m_blockheaders( bytes32, bytes32) constant returns(blockHeight uint256, prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) +func (_Ion *IonCallerSession) MBlockheaders(arg0 [32]byte, arg1 [32]byte) (struct { + BlockHeight *big.Int PrevBlockHash [32]byte TxRootHash [32]byte ReceiptRootHash [32]byte }, error) { - return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0) + return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0, arg1) +} + +// MValidators is a free data retrieval call binding the contract method 0x53fe62e6. +// +// Solidity: function m_validators( bytes32, address) constant returns(bool) +func (_Ion *IonCaller) MValidators(opts *bind.CallOpts, arg0 [32]byte, arg1 common.Address) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "m_validators", arg0, arg1) + return *ret0, err +} + +// MValidators is a free data retrieval call binding the contract method 0x53fe62e6. +// +// Solidity: function m_validators( bytes32, address) constant returns(bool) +func (_Ion *IonSession) MValidators(arg0 [32]byte, arg1 common.Address) (bool, error) { + return _Ion.Contract.MValidators(&_Ion.CallOpts, arg0, arg1) +} + +// MValidators is a free data retrieval call binding the contract method 0x53fe62e6. +// +// Solidity: function m_validators( bytes32, address) constant returns(bool) +func (_Ion *IonCallerSession) MValidators(arg0 [32]byte, arg1 common.Address) (bool, error) { + return _Ion.Contract.MValidators(&_Ion.CallOpts, arg0, arg1) +} + +// RegisteredChains is a free data retrieval call binding the contract method 0x200ab0d3. +// +// Solidity: function registeredChains( uint256) constant returns(bytes32) +func (_Ion *IonCaller) RegisteredChains(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "registeredChains", arg0) + return *ret0, err +} + +// RegisteredChains is a free data retrieval call binding the contract method 0x200ab0d3. +// +// Solidity: function registeredChains( uint256) constant returns(bytes32) +func (_Ion *IonSession) RegisteredChains(arg0 *big.Int) ([32]byte, error) { + return _Ion.Contract.RegisteredChains(&_Ion.CallOpts, arg0) +} + +// RegisteredChains is a free data retrieval call binding the contract method 0x200ab0d3. +// +// Solidity: function registeredChains( uint256) constant returns(bytes32) +func (_Ion *IonCallerSession) RegisteredChains(arg0 *big.Int) ([32]byte, error) { + return _Ion.Contract.RegisteredChains(&_Ion.CallOpts, arg0) +} + +// ValidationAddr is a free data retrieval call binding the contract method 0x261e5073. +// +// Solidity: function validation_addr( bytes32) constant returns(address) +func (_Ion *IonCaller) ValidationAddr(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { + var ( + ret0 = new(common.Address) + ) + out := ret0 + err := _Ion.contract.Call(opts, out, "validation_addr", arg0) + return *ret0, err +} + +// ValidationAddr is a free data retrieval call binding the contract method 0x261e5073. +// +// Solidity: function validation_addr( bytes32) constant returns(address) +func (_Ion *IonSession) ValidationAddr(arg0 [32]byte) (common.Address, error) { + return _Ion.Contract.ValidationAddr(&_Ion.CallOpts, arg0) +} + +// ValidationAddr is a free data retrieval call binding the contract method 0x261e5073. +// +// Solidity: function validation_addr( bytes32) constant returns(address) +func (_Ion *IonCallerSession) ValidationAddr(arg0 [32]byte) (common.Address, error) { + return _Ion.Contract.ValidationAddr(&_Ion.CallOpts, arg0) +} + +// CheckReceiptProof is a paid mutator transaction binding the contract method 0xbec205b9. +// +// Solidity: function CheckReceiptProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) +func (_Ion *IonTransactor) CheckReceiptProof(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { + return _Ion.contract.Transact(opts, "CheckReceiptProof", _id, _blockHash, _value, _parentNodes, _path) +} + +// CheckReceiptProof is a paid mutator transaction binding the contract method 0xbec205b9. +// +// Solidity: function CheckReceiptProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) +func (_Ion *IonSession) CheckReceiptProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { + return _Ion.Contract.CheckReceiptProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) +} + +// CheckReceiptProof is a paid mutator transaction binding the contract method 0xbec205b9. +// +// Solidity: function CheckReceiptProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) +func (_Ion *IonTransactorSession) CheckReceiptProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { + return _Ion.Contract.CheckReceiptProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) +} + +// CheckRootsProof is a paid mutator transaction binding the contract method 0xf484c1f7. +// +// Solidity: function CheckRootsProof(_id bytes32, _blockHash bytes32, _txNodes bytes, _receiptNodes bytes) returns(bool) +func (_Ion *IonTransactor) CheckRootsProof(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _txNodes []byte, _receiptNodes []byte) (*types.Transaction, error) { + return _Ion.contract.Transact(opts, "CheckRootsProof", _id, _blockHash, _txNodes, _receiptNodes) +} + +// CheckRootsProof is a paid mutator transaction binding the contract method 0xf484c1f7. +// +// Solidity: function CheckRootsProof(_id bytes32, _blockHash bytes32, _txNodes bytes, _receiptNodes bytes) returns(bool) +func (_Ion *IonSession) CheckRootsProof(_id [32]byte, _blockHash [32]byte, _txNodes []byte, _receiptNodes []byte) (*types.Transaction, error) { + return _Ion.Contract.CheckRootsProof(&_Ion.TransactOpts, _id, _blockHash, _txNodes, _receiptNodes) +} + +// CheckRootsProof is a paid mutator transaction binding the contract method 0xf484c1f7. +// +// Solidity: function CheckRootsProof(_id bytes32, _blockHash bytes32, _txNodes bytes, _receiptNodes bytes) returns(bool) +func (_Ion *IonTransactorSession) CheckRootsProof(_id [32]byte, _blockHash [32]byte, _txNodes []byte, _receiptNodes []byte) (*types.Transaction, error) { + return _Ion.Contract.CheckRootsProof(&_Ion.TransactOpts, _id, _blockHash, _txNodes, _receiptNodes) } // CheckTxProof is a paid mutator transaction binding the contract method 0xaffd8be9. @@ -419,51 +491,51 @@ func (_Ion *IonTransactorSession) CheckTxProof(_id [32]byte, _blockHash [32]byte return _Ion.Contract.CheckTxProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) } -// RegisterChain is a paid mutator transaction binding the contract method 0x9e43d86b. +// RegisterChain is a paid mutator transaction binding the contract method 0x7558a01a. // -// Solidity: function RegisterChain(_id bytes32) returns() -func (_Ion *IonTransactor) RegisterChain(opts *bind.TransactOpts, _id [32]byte) (*types.Transaction, error) { - return _Ion.contract.Transact(opts, "RegisterChain", _id) +// Solidity: function RegisterChain(_id bytes32, validationAddr address, _validators address[], _genesisHash bytes32) returns() +func (_Ion *IonTransactor) RegisterChain(opts *bind.TransactOpts, _id [32]byte, validationAddr common.Address, _validators []common.Address, _genesisHash [32]byte) (*types.Transaction, error) { + return _Ion.contract.Transact(opts, "RegisterChain", _id, validationAddr, _validators, _genesisHash) } -// RegisterChain is a paid mutator transaction binding the contract method 0x9e43d86b. +// RegisterChain is a paid mutator transaction binding the contract method 0x7558a01a. // -// Solidity: function RegisterChain(_id bytes32) returns() -func (_Ion *IonSession) RegisterChain(_id [32]byte) (*types.Transaction, error) { - return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id) +// Solidity: function RegisterChain(_id bytes32, validationAddr address, _validators address[], _genesisHash bytes32) returns() +func (_Ion *IonSession) RegisterChain(_id [32]byte, validationAddr common.Address, _validators []common.Address, _genesisHash [32]byte) (*types.Transaction, error) { + return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id, validationAddr, _validators, _genesisHash) } -// RegisterChain is a paid mutator transaction binding the contract method 0x9e43d86b. +// RegisterChain is a paid mutator transaction binding the contract method 0x7558a01a. // -// Solidity: function RegisterChain(_id bytes32) returns() -func (_Ion *IonTransactorSession) RegisterChain(_id [32]byte) (*types.Transaction, error) { - return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id) +// Solidity: function RegisterChain(_id bytes32, validationAddr address, _validators address[], _genesisHash bytes32) returns() +func (_Ion *IonTransactorSession) RegisterChain(_id [32]byte, validationAddr common.Address, _validators []common.Address, _genesisHash [32]byte) (*types.Transaction, error) { + return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id, validationAddr, _validators, _genesisHash) } -// SubmitBlock is a paid mutator transaction binding the contract method 0x5a0235e4. +// SubmitBlock is a paid mutator transaction binding the contract method 0x52824374. // -// Solidity: function SubmitBlock(_id bytes32, _blockHash bytes32, _rlpBlockHeader bytes) returns() -func (_Ion *IonTransactor) SubmitBlock(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _rlpBlockHeader []byte) (*types.Transaction, error) { - return _Ion.contract.Transact(opts, "SubmitBlock", _id, _blockHash, _rlpBlockHeader) +// Solidity: function SubmitBlock(_id bytes32, _rlpBlockHeader bytes, _rlpSignedBlockHeader bytes) returns() +func (_Ion *IonTransactor) SubmitBlock(opts *bind.TransactOpts, _id [32]byte, _rlpBlockHeader []byte, _rlpSignedBlockHeader []byte) (*types.Transaction, error) { + return _Ion.contract.Transact(opts, "SubmitBlock", _id, _rlpBlockHeader, _rlpSignedBlockHeader) } -// SubmitBlock is a paid mutator transaction binding the contract method 0x5a0235e4. +// SubmitBlock is a paid mutator transaction binding the contract method 0x52824374. // -// Solidity: function SubmitBlock(_id bytes32, _blockHash bytes32, _rlpBlockHeader bytes) returns() -func (_Ion *IonSession) SubmitBlock(_id [32]byte, _blockHash [32]byte, _rlpBlockHeader []byte) (*types.Transaction, error) { - return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _blockHash, _rlpBlockHeader) +// Solidity: function SubmitBlock(_id bytes32, _rlpBlockHeader bytes, _rlpSignedBlockHeader bytes) returns() +func (_Ion *IonSession) SubmitBlock(_id [32]byte, _rlpBlockHeader []byte, _rlpSignedBlockHeader []byte) (*types.Transaction, error) { + return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _rlpBlockHeader, _rlpSignedBlockHeader) } -// SubmitBlock is a paid mutator transaction binding the contract method 0x5a0235e4. +// SubmitBlock is a paid mutator transaction binding the contract method 0x52824374. // -// Solidity: function SubmitBlock(_id bytes32, _blockHash bytes32, _rlpBlockHeader bytes) returns() -func (_Ion *IonTransactorSession) SubmitBlock(_id [32]byte, _blockHash [32]byte, _rlpBlockHeader []byte) (*types.Transaction, error) { - return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _blockHash, _rlpBlockHeader) +// Solidity: function SubmitBlock(_id bytes32, _rlpBlockHeader bytes, _rlpSignedBlockHeader bytes) returns() +func (_Ion *IonTransactorSession) SubmitBlock(_id [32]byte, _rlpBlockHeader []byte, _rlpSignedBlockHeader []byte) (*types.Transaction, error) { + return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _rlpBlockHeader, _rlpSignedBlockHeader) } -// IonVerifiedTxProofIterator is returned from FilterVerifiedTxProof and is used to iterate over the raw logs and unpacked data for VerifiedTxProof events raised by the Ion contract. -type IonVerifiedTxProofIterator struct { - Event *IonVerifiedTxProof // Event containing the contract specifics and raw log +// IonVerifiedProofIterator is returned from FilterVerifiedProof and is used to iterate over the raw logs and unpacked data for VerifiedProof events raised by the Ion contract. +type IonVerifiedProofIterator struct { + Event *IonVerifiedProof // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -477,7 +549,7 @@ type IonVerifiedTxProofIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IonVerifiedTxProofIterator) Next() bool { +func (it *IonVerifiedProofIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -486,7 +558,7 @@ func (it *IonVerifiedTxProofIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IonVerifiedTxProof) + it.Event = new(IonVerifiedProof) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -501,7 +573,7 @@ func (it *IonVerifiedTxProofIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IonVerifiedTxProof) + it.Event = new(IonVerifiedProof) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -517,42 +589,287 @@ func (it *IonVerifiedTxProofIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IonVerifiedTxProofIterator) Error() error { +func (it *IonVerifiedProofIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IonVerifiedTxProofIterator) Close() error { +func (it *IonVerifiedProofIterator) Close() error { it.sub.Unsubscribe() return nil } -// IonVerifiedTxProof represents a VerifiedTxProof event raised by the Ion contract. -type IonVerifiedTxProof struct { +// IonVerifiedProof represents a VerifiedProof event raised by the Ion contract. +type IonVerifiedProof struct { ChainId [32]byte + BlockHash [32]byte + ProofType *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterVerifiedProof is a free log retrieval operation binding the contract event 0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046. +// +// Solidity: e VerifiedProof(chainId bytes32, blockHash bytes32, proofType uint256) +func (_Ion *IonFilterer) FilterVerifiedProof(opts *bind.FilterOpts) (*IonVerifiedProofIterator, error) { + + logs, sub, err := _Ion.contract.FilterLogs(opts, "VerifiedProof") + if err != nil { + return nil, err + } + return &IonVerifiedProofIterator{contract: _Ion.contract, event: "VerifiedProof", logs: logs, sub: sub}, nil +} + +// WatchVerifiedProof is a free log subscription operation binding the contract event 0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046. +// +// Solidity: e VerifiedProof(chainId bytes32, blockHash bytes32, proofType uint256) +func (_Ion *IonFilterer) WatchVerifiedProof(opts *bind.WatchOpts, sink chan<- *IonVerifiedProof) (event.Subscription, error) { + + logs, sub, err := _Ion.contract.WatchLogs(opts, "VerifiedProof") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IonVerifiedProof) + if err := _Ion.contract.UnpackLog(event, "VerifiedProof", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// IonBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Ion contract. +type IonBroadcastHashIterator struct { + Event *IonBroadcastHash // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IonBroadcastHashIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IonBroadcastHash) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IonBroadcastHash) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IonBroadcastHashIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IonBroadcastHashIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IonBroadcastHash represents a BroadcastHash event raised by the Ion contract. +type IonBroadcastHash struct { BlockHash [32]byte Raw types.Log // Blockchain specific contextual infos } -// FilterVerifiedTxProof is a free log retrieval operation binding the contract event 0x202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a1. +// FilterBroadcastHash is a free log retrieval operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. +// +// Solidity: e broadcastHash(blockHash bytes32) +func (_Ion *IonFilterer) FilterBroadcastHash(opts *bind.FilterOpts) (*IonBroadcastHashIterator, error) { + + logs, sub, err := _Ion.contract.FilterLogs(opts, "broadcastHash") + if err != nil { + return nil, err + } + return &IonBroadcastHashIterator{contract: _Ion.contract, event: "broadcastHash", logs: logs, sub: sub}, nil +} + +// WatchBroadcastHash is a free log subscription operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. +// +// Solidity: e broadcastHash(blockHash bytes32) +func (_Ion *IonFilterer) WatchBroadcastHash(opts *bind.WatchOpts, sink chan<- *IonBroadcastHash) (event.Subscription, error) { + + logs, sub, err := _Ion.contract.WatchLogs(opts, "broadcastHash") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IonBroadcastHash) + if err := _Ion.contract.UnpackLog(event, "broadcastHash", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// IonBroadcastSignatureIterator is returned from FilterBroadcastSignature and is used to iterate over the raw logs and unpacked data for BroadcastSignature events raised by the Ion contract. +type IonBroadcastSignatureIterator struct { + Event *IonBroadcastSignature // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IonBroadcastSignatureIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IonBroadcastSignature) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IonBroadcastSignature) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IonBroadcastSignatureIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IonBroadcastSignatureIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IonBroadcastSignature represents a BroadcastSignature event raised by the Ion contract. +type IonBroadcastSignature struct { + Signer common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBroadcastSignature is a free log retrieval operation binding the contract event 0x3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef43. // -// Solidity: event VerifiedTxProof(chainId bytes32, blockHash bytes32) -func (_Ion *IonFilterer) FilterVerifiedTxProof(opts *bind.FilterOpts) (*IonVerifiedTxProofIterator, error) { +// Solidity: e broadcastSignature(signer address) +func (_Ion *IonFilterer) FilterBroadcastSignature(opts *bind.FilterOpts) (*IonBroadcastSignatureIterator, error) { - logs, sub, err := _Ion.contract.FilterLogs(opts, "VerifiedTxProof") + logs, sub, err := _Ion.contract.FilterLogs(opts, "broadcastSignature") if err != nil { return nil, err } - return &IonVerifiedTxProofIterator{contract: _Ion.contract, event: "VerifiedTxProof", logs: logs, sub: sub}, nil + return &IonBroadcastSignatureIterator{contract: _Ion.contract, event: "broadcastSignature", logs: logs, sub: sub}, nil } -// WatchVerifiedTxProof is a free log subscription operation binding the contract event 0x202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a1. +// WatchBroadcastSignature is a free log subscription operation binding the contract event 0x3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef43. // -// Solidity: event VerifiedTxProof(chainId bytes32, blockHash bytes32) -func (_Ion *IonFilterer) WatchVerifiedTxProof(opts *bind.WatchOpts, sink chan<- *IonVerifiedTxProof) (event.Subscription, error) { +// Solidity: e broadcastSignature(signer address) +func (_Ion *IonFilterer) WatchBroadcastSignature(opts *bind.WatchOpts, sink chan<- *IonBroadcastSignature) (event.Subscription, error) { - logs, sub, err := _Ion.contract.WatchLogs(opts, "VerifiedTxProof") + logs, sub, err := _Ion.contract.WatchLogs(opts, "broadcastSignature") if err != nil { return nil, err } @@ -562,8 +879,8 @@ func (_Ion *IonFilterer) WatchVerifiedTxProof(opts *bind.WatchOpts, sink chan<- select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IonVerifiedTxProof) - if err := _Ion.contract.UnpackLog(event, "VerifiedTxProof", log); err != nil { + event := new(IonBroadcastSignature) + if err := _Ion.contract.UnpackLog(event, "broadcastSignature", log); err != nil { return err } event.Raw = log diff --git a/ion-cli/main.go b/ion-cli/main.go index 5aac1be..2024db6 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -22,12 +22,12 @@ func main() { clientTo := config.InitClient(setup.AddrTo) clientFrom := config.InitClient(setup.AddrFrom) - Validation := config.InitValidationContract(setup, clientTo) + Ion := config.InitValidationContract(setup, clientTo) printInfo(setup) // Launch the CLI - cli.Launch(setup, clientFrom, Validation) + cli.Launch(setup, clientFrom, Ion) } else { fmt.Print("Error: empty config!\n") os.Exit(3) diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index a6094a3..b9b2c35 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -1,9 +1,9 @@ { "rpc-to":"http://127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-to":"../poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "ion-addr":"0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613", "rpc-from":"https://rinkeby.infura.io", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-from":"../poa-network/multi-peer/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f" + "keystore-from":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 22e0c65..08f8736 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -7,7 +7,6 @@ const EventVerifier = artifacts.require("EventVerifier"); module.exports = async (deployer) => { try { -// <<<<<<< HEAD deployer.deploy(Recover) .then(() => Recover.deployed) .then(() => deployer.deploy(Validation, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) @@ -21,16 +20,6 @@ module.exports = async (deployer) => { .then(() => EventVerifier.deployed) .then(() => deployer.deploy(EventFunction, Ion.address, EventVerifier.address)) .then(() => EventFunction.deployed) -// ======= -// await deployer.deploy(PatriciaTrie); -// await deployer.link(PatriciaTrie, Ion); -// await deployer.deploy(Ion, "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075"); -// eventVerifier = await deployer.deploy(EventVerifier); -// ion = await Ion.deployed(); -// eventVerifier = await EventVerifier.deployed(); -// deployer.deploy(Function, ion.address, eventVerifier.address); - -// >>>>>>> state-proof } catch(err) { console.log('ERROR on deploy:',err); } diff --git a/test/ion.js b/test/ion.js index bb29b30..ddb4aee 100644 --- a/test/ion.js +++ b/test/ion.js @@ -155,7 +155,7 @@ const GENESIS_HASH = TESTBLOCK.parentHash; // const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; -contract('Ion.js', (accounts) => { +contract.only('Ion.js', (accounts) => { it('Deploy Ion', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); let chainId = await ion.chainId(); @@ -168,115 +168,26 @@ contract('Ion.js', (accounts) => { const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); let chain = await ion.chains(TESTCHAINID); assert.equal(chain, true); // Fail adding id of this chain - await ion.RegisterChain(DEPLOYEDCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; + await ion.RegisterChain(DEPLOYEDCHAINID, validation.address).should.be.rejected; // Fail adding id of chain already registered - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH).should.be.rejected; - }) - - it('Register Chain - Check Genesis Hash', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); - - // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); - - let header = await ion.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); - let blockHeight = header[0]; - - assert.equal(0, blockHeight); -; - }) - - it('Register Chain - Check Validators', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); - - // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); - - let validators = await ion.m_validators.call(TESTCHAINID, TEST_VALIDATORS[0]); - assert.equal(validators, true); - }) - - it('Submit Block', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); - - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); - - // Submit block should succeed - const validationReceipt = await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; - - let blockHash = await ion.m_blockhashes(TESTCHAINID, TESTBLOCK.hash); - assert.equal(blockHash, true); - - let header = await ion.m_blockheaders(TESTCHAINID, TESTBLOCK.hash); - - // Separate fetched header info - parentHash = header[1]; - txRootHash = header[2]; - receiptRootHash = header[3]; - - // Assert that block was persisted correctly - assert.equal(parentHash, TESTBLOCK.parentHash); - assert.equal(txRootHash, TESTBLOCK.transactionsRoot); - assert.equal(receiptRootHash, TESTBLOCK.receiptsRoot); - }) - - it('Fail Submit Block from unknown chain', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); - - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); - - await ion.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; - }) - - it('Fail Submit Block with wrong unsigned header', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); - - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); - - const incorrectHeader = [ - TESTBLOCK.parentHash, - TESTBLOCK.sha3Uncles, - TESTBLOCK.miner, - TESTBLOCK.stateRoot, - TESTBLOCK.transactionsRoot, - TESTBLOCK.receiptsRoot.slice(0, -2) + "fa", - TESTBLOCK.logsBloom, - Web3Utils.toBN(TESTBLOCK.difficulty), - Web3Utils.toBN(TESTBLOCK.number), - TESTBLOCK.gasLimit, - TESTBLOCK.gasUsed, - Web3Utils.toBN(TESTBLOCK.timestamp), - extraDataShort, // extraData minus the signature - TESTBLOCK.mixHash, - TESTBLOCK.nonce - ]; - - - const TEST_INCORRECT_UNSIGNED_HEADER = '0x' + rlp.encode(incorrectHeader).toString('hex'); - - await ion.SubmitBlock(TESTCHAINID, TEST_INCORRECT_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; + await ion.RegisterChain(TESTCHAINID, validation.address).should.be.rejected; }) it('Check Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); @@ -287,9 +198,10 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); // Fail with wrong chain ID await ion.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; @@ -305,9 +217,10 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); nodes = generateTestReceiptRLPNodes(); @@ -319,9 +232,10 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); // Fail with wrong chain ID await ion.CheckReceiptProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; @@ -337,9 +251,11 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + + await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); let tx = await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); @@ -350,9 +266,11 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + + await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); // Fail with wrong chain ID await ion.CheckRootsProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected @@ -367,13 +285,13 @@ contract('Ion.js', (accounts) => { await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; }) - it('Deploy Function Contract', async () => { + it.only('Deploy Function Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); const verifier = await TriggerEventVerifier.new(); - const functionContract = await Function.new(ion.address, verifier.address); - }) + // const functionContract = await Function.new(ion.address, verifier.address); +}) it('Verify Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); @@ -383,9 +301,10 @@ contract('Ion.js', (accounts) => { const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion - await ion.RegisterChain(TESTCHAINID, validation.address, TEST_VALIDATORS, GENESIS_HASH); + await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); - await ion.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); diff --git a/test/validation.js b/test/validation.js index 20587c0..fb97300 100644 --- a/test/validation.js +++ b/test/validation.js @@ -53,16 +53,6 @@ contract('Validation.js', (accounts) => { const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); - const blockNum = 1; - - // Hash of the genesis block - const genesisBlock = web3.eth.getBlock(0); - // const genHash = genesisBlock.hash; - const genHash = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; - - // Find the validator of block 1 as it is not known a priori - const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]; - it('Test: Deploy Contract', async () => { const validation = await Validation.new(DEPLOYEDCHAINID); let chainId = await validation.chainId(); @@ -70,26 +60,125 @@ contract('Validation.js', (accounts) => { assert.equal(chainId, DEPLOYEDCHAINID); }) - it('Test: Initialise Chain', async () => { + it('Test: Register Chain', async () => { const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await validation.InitChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); let chain = await validation.chains(TESTCHAINID); assert.equal(chain, true); // Fail adding id of this chain - await validation.InitChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already initialised - await validation.InitChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + }) + + it('Test: Register Chain - Check Validators', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + // Successfully add id of another chain + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + let validators = await validation.m_validators.call(TESTCHAINID, VALIDATORS[0]); + assert.equal(validators, true); + }) + + + it('Test: Register Chain - Check Genesis Hash', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + // Successfully add id of another chain + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + let header = await validation.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); + let blockHeight = header[0]; + + assert.equal(0, blockHeight); +; +}) + + it('Test: Authentic Submission Happy Path - SubmitBlock()', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; + + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; + + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + assert.equal(block.hash, signedHeaderHash); + + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + + // Submit block should succeed + const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); + const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; + assert.equal(signedHeaderHash, recoveredBlockHash); + + let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); + assert.equal(blockHash, true); + + let header = await validation.m_blockheaders(TESTCHAINID, block.hash); + + // Separate fetched header info + parentHash = header[2]; + + // Assert that block was persisted correctly + assert.equal(parentHash, block.parentHash); }) - it('Validate Block', async () => { + // Here the block header is signed off chain but by a whitelisted validator + it('Test: Authentic Submission Off-Chain Signature - SubmitBlock()', async () => { const validation = await Validation.new(DEPLOYEDCHAINID); - await validation.InitChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -143,15 +232,50 @@ contract('Validation.js', (accounts) => { const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + // Encode and sign the new header + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); + const newSignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); + + const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + + let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); + + // Append signature to the end of extraData + const sigBytes = utils.hexToBytes(signature.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); + assert.equal(extraDataSignature, '0x'+signature.toString('hex')) + + const newSignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + newExtraData, // Off-chain signed block + block.mixHash, + block.nonce + ]; + + // Encode the offchain signed header + const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); + // Submit block should succeed - const validationReceipt = await validation.ValidateBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); + const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader); const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; assert.equal(signedHeaderHash, recoveredBlockHash); let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); assert.equal(blockHash, true); - let header = await validation.m_blockheaders(TESTCHAINID); + let header = await validation.m_blockheaders(TESTCHAINID, block.hash); // Separate fetched header info parentHash = header[2]; @@ -160,424 +284,345 @@ contract('Validation.js', (accounts) => { assert.equal(parentHash, block.parentHash); }) - // This test takes a block and makes no changes to the block and submits it to the contract -// it('Test: Authentic Submission Happy Path - ValidateBlock()', async () => { -// const validation = await Validation.new(validators, genHash); -// const accounts = web3.eth.accounts; -// const signer = validators[0]; - -// // Get a single block -// const block = web3.eth.getBlock(blockNum); - -// // Decompose the values in the block to hash -// const parentHash = block.parentHash; -// const sha3Uncles = block.sha3Uncles; -// const coinbase = block.miner; -// const root = block.stateRoot; -// const txHash = block.transactionsRoot; -// const receiptHash = block.receiptsRoot; -// const logsBloom = block.logsBloom; -// const difficulty = Web3Utils.toBN(block.difficulty); -// const number = Web3Utils.toBN(block.number); -// const gasLimit = block.gasLimit; -// const gasUsed = block.gasUsed; -// const timestamp = Web3Utils.toBN(block.timestamp); -// const extraData = block.extraData; -// const mixHash = block.mixHash; -// const nonce = block.nonce; - -// // Remove last 65 Bytes of extraData -// const extraBytes = utils.hexToBytes(extraData); -// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); -// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); -// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - -// const blockHeader = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// txHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// extraData, -// mixHash, -// nonce -// ]; - -// const header = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// txHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// extraDataShort, -// mixHash, -// nonce -// ]; - -// const encodedBlockHeader = '0x' + rlp.encode(blockHeader).toString('hex'); -// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); -// assert.equal(block.hash, blockHeaderHash); + // Here the block header is signed off chain but by a whitelisted validator who alters the block + it('Test: Inauthentic Block Submission - SubmitBlock()', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + // Alter txHash + const newTxHash = Web3Utils.sha3("Test Data"); + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + newTxHash, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; + + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + newTxHash, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; + + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); + + const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') + + const sig = eth_util.ecsign(unsignedHeaderHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = eth_util.ecrecover(unsignedHeaderHash, sig.v, sig.r, sig.s); + const addrBuf = eth_util.pubToAddress(pubKey); + assert.equal(VALIDATORS[0], '0x'+addrBuf.toString('hex')); + + const newSigBytes = Buffer.concat([sig.r, sig.s]); + let newSig; + + // Need to understand why but signature requires different v than in others to recover correctly + if (sig.v=="27") { + newSig = newSigBytes.toString('hex') + '00'; + } + if (sig.v=="28") { + newSig = newSigBytes.toString('hex') + '01'; + } + + // let signature = await signHeader(unsignedHeaderHash, privateKey, block.extraData); + + // Append signature to the end of extraData + const sigBytes = utils.hexToBytes(newSig.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); + + const newSignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + newTxHash, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + newExtraData, // Off-chain signed block + block.mixHash, + block.nonce + ]; + + // Encode the offchain signed header + const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); + const offchainHeaderHash = Web3Utils.sha3(offchainSignedHeader); + + // Submit block should succeed + const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader); + const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; + // console.log(validationReceipt.logs[1].args['signer']); + assert.equal(offchainHeaderHash, recoveredBlockHash); + + let blockHash = await validation.m_blockhashes(TESTCHAINID, offchainHeaderHash); + assert.equal(blockHash, true); + + }) + + // Here the block header is signed off chain but by a a non-whitelisted validator + it('Test: Fail Submit Block unkown validator - SubmitBlock()', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + // Alter txHash + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; + + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; + + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + + // Encode and sign the new header + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); + const newSignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); + + const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') + + let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); + + // Append signature to the end of extraData + const sigBytes = utils.hexToBytes(signature.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); + + const newSignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + newExtraData, // Off-chain signed block + block.mixHash, + block.nonce + ]; + + // Encode the offchain signed header + const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); + const offchainHeaderHash = Web3Utils.sha3(offchainSignedHeader); + + await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader).should.be.rejected; + + }) + + it('Test: Fail Submit Block from unknown chain - SubmitBlock()', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; + + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; + + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + assert.equal(block.hash, signedHeaderHash); + + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + + // Submit block should succeed + await validation.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", encodedUnsignedHeader, encodedSignedHeader).should.be.rejected; -// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); -// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); -// const headerHash = Web3Utils.sha3(encodedHeader); - -// // Get Prefixes -// const prefixHeader = '0x' + encodedHeader.substring(4, 8); -// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); - -// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); -// const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; -// const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; -// assert.equal(block.hash, recoveredBlockHash) -// assert.notEqual(validators.indexOf(recoveredSignature), -1); - -// }) - -// // Here the block header is signed off chain but by a whitelisted validator -// it('Test: Authentic Submission Off-Chain Signature - ValidateBlock()', async () => { -// const validation = await Validation.new(validators, genHash); -// const accounts = web3.eth.accounts; -// const signer = validators[0]; - -// // Get a single block -// const block = web3.eth.getBlock(blockNum); - -// // Decompose the values in the block to hash -// const parentHash = block.parentHash; -// const sha3Uncles = block.sha3Uncles; -// const coinbase = block.miner; -// const root = block.stateRoot; -// const txHash = block.transactionsRoot; -// const receiptHash = block.receiptsRoot; -// const logsBloom = block.logsBloom; -// const difficulty = Web3Utils.toBN(block.difficulty); -// const number = Web3Utils.toBN(block.number); -// const gasLimit = block.gasLimit; -// const gasUsed = block.gasUsed; -// const timestamp = Web3Utils.toBN(block.timestamp); -// const extraData = block.extraData; -// const mixHash = block.mixHash; -// const nonce = block.nonce; - -// // Create new signed hash -// const extraBytes = hexToBytes(extraData); -// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); -// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); -// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - -// // Make some changes to the block -// const header = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// txHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// extraDataShort, -// mixHash, -// nonce -// ]; - -// // Encode and sign the new header -// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); -// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); -// const headerHash = eth_util.sha3(encodedHeader); - -// const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - -// let signature = await signHeader(headerHash, privateKey, extraData); - -// // Append signature to the end of extraData -// const sigBytes = hexToBytes(signature.toString('hex')); -// const newExtraDataBytes = extraBytesShort.concat(sigBytes); -// const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); -// assert.equal(extraDataSignature, '0x'+signature.toString('hex')) - -// const newBlockHeader = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// txHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// newExtraData, -// mixHash, -// nonce -// ]; - -// const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); -// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); -// assert.equal(block.hash, blockHeaderHash); - -// // Get Prefixes -// const prefixHeader = '0x' + encodedHeader.substring(4, 8); -// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); - -// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); -// const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; -// const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; -// assert.equal(block.hash, recoveredBlockHash) -// assert.equal(recoveredSignature, signer); -// }) - -// it('Test: Inauthentic Block Submission - ValidateBlock()', async () => { -// const validation = await Validation.new(validators, genHash); -// const accounts = web3.eth.accounts; -// const signer = validators[0]; - -// // Get a single block -// const block = web3.eth.getBlock(blockNum); - -// // Decompose the values in the block to hash -// const parentHash = block.parentHash; -// const sha3Uncles = block.sha3Uncles; -// const coinbase = block.miner; -// const root = block.stateRoot; -// const txHash = block.transactionsRoot; -// const receiptHash = block.receiptsRoot; -// const logsBloom = block.logsBloom; -// const difficulty = Web3Utils.toBN(block.difficulty); -// const number = Web3Utils.toBN(block.number); -// const gasLimit = block.gasLimit; -// const gasUsed = block.gasUsed; -// const timestamp = Web3Utils.toBN(block.timestamp); -// const extraData = block.extraData; -// const mixHash = block.mixHash; -// const nonce = block.nonce; - -// // Create new signed hash -// const extraBytes = hexToBytes(extraData); -// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); -// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); -// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - -// // Make some changes to the block -// const newTxHash = Web3Utils.sha3("Test Data"); -// // console.log(txHash, newTxHash); -// const header = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// // txHash, -// newTxHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// extraDataShort, -// mixHash, -// nonce -// ]; - -// // Encode and sign the new header -// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); -// const headerHash = eth_util.sha3(encodedHeader); - -// const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - -// const sig = eth_util.ecsign(headerHash, privateKey) -// if (this._chainId > 0) { -// sig.v += this._chainId * 2 + 8 -// } - -// const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); -// const addrBuf = eth_util.pubToAddress(pubKey); -// assert.equal(signer, '0x'+addrBuf.toString('hex')); - -// const newSigBytes = Buffer.concat([sig.r, sig.s]); -// let newSig; - -// // Need to understand why but signature requires different v than in others to recover correctly -// if (sig.v=="27") { -// newSig = newSigBytes.toString('hex') + '00'; -// } -// if (sig.v=="28") { -// newSig = newSigBytes.toString('hex') + '01'; -// } - -// // Append signature to the end of extraData -// const sigBytes = hexToBytes(newSig.toString('hex')); -// const newExtraDataBytes = extraBytesShort.concat(sigBytes); -// const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); - -// const newBlockHeader = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// // txHash, -// newTxHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// newExtraData, -// mixHash, -// nonce -// ]; - -// const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); -// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); -// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - -// // Get Prefixes -// const prefixHeader = '0x' + encodedHeader.substring(4, 8); -// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); - -// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); -// const recoveredBlockHash = ecrecoveryReceipt.logs[0].args['blockHash']; -// const recoveredSignature = ecrecoveryReceipt.logs[1].args['owner']; -// assert.equal(recoveredBlockHash, blockHeaderHash); -// assert.equal(recoveredSignature, signer); - -// }) - -// it('Test: Authentic Block Unkown Validator Submission - ValidateBlock()', async () => { -// const validation = await Validation.new(validators, genHash); -// const accounts = web3.eth.accounts; -// const signer = validators[1]; - -// // Get a single block -// const block = web3.eth.getBlock(blockNum); - -// // Decompose the values in the block to hash -// const parentHash = block.parentHash; -// const sha3Uncles = block.sha3Uncles; -// const coinbase = block.miner; -// const root = block.stateRoot; -// const txHash = block.transactionsRoot; -// const receiptHash = block.receiptsRoot; -// const logsBloom = block.logsBloom; -// const difficulty = Web3Utils.toBN(block.difficulty); -// const number = Web3Utils.toBN(block.number); -// const gasLimit = block.gasLimit; -// const gasUsed = block.gasUsed; -// const timestamp = Web3Utils.toBN(block.timestamp); -// const extraData = block.extraData; -// const mixHash = block.mixHash; -// const nonce = block.nonce; - -// // Create new signed hash -// const extraBytes = hexToBytes(extraData); -// const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); -// const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); -// const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - -// // Make some changes to the block -// const newTxHash = Web3Utils.sha3("Test Data"); -// const header = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// newTxHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// extraDataShort, -// mixHash, -// nonce -// ]; - -// // Encode and sign the new header -// const encodedHeader = '0x' + rlp.encode(header).toString('hex'); -// const headerHash = eth_util.sha3(encodedHeader); - -// const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') - -// const sig = eth_util.ecsign(headerHash, privateKey) -// if (this._chainId > 0) { -// sig.v += this._chainId * 2 + 8 -// } - -// const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); -// const addrBuf = eth_util.pubToAddress(pubKey); -// const addr = eth_util.bufferToHex(addrBuf); - -// const newSigBytes = Buffer.concat([sig.r, sig.s]); -// let newSig; - -// const bytes = hexToBytes(extraData) -// const finalByte = bytes.splice(bytes.length-1) -// if (finalByte.toString('hex')=="00") -// newSig = newSigBytes.toString('hex') + '00'; -// else (finalByte.toString('hex')=="01") -// newSig = newSigBytes.toString('hex') + '01'; - -// // Append signature to the end of extraData -// const sigBytes = hexToBytes(newSig.toString('hex')); -// const newExtraDataBytes = extraBytesShort.concat(sigBytes); -// const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); - -// const newBlockHeader = [ -// parentHash, -// sha3Uncles, -// coinbase, -// root, -// newTxHash, -// receiptHash, -// logsBloom, -// difficulty, -// number, -// gasLimit, -// gasUsed, -// timestamp, -// newExtraData, -// mixHash, -// nonce -// ]; - -// const encodedBlockHeader = '0x' + rlp.encode(newBlockHeader).toString('hex'); -// const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); -// const blockHeaderHash = Web3Utils.sha3(encodedBlockHeader); - -// // Get Prefixes -// const prefixHeader = '0x' + encodedHeader.substring(4, 8); -// const prefixExtraData = '0x' + encodedExtraData.substring(2,4); - -// try { -// const ecrecoveryReceipt = await validation.ValidateBlock(encodedBlockHeader, prefixHeader, prefixExtraData); -// } catch (err) { -// assert.isDefined(err, "transaction should have thrown"); -// } -// }) + }) + + it('Test: Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { + const validation = await Validation.new(DEPLOYEDCHAINID); + + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; + + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot.slice(0, -2) + "fa", + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; + + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + assert.equal(block.hash, signedHeaderHash); + + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + + // Submit block should succeed + await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader).should.be.rejected; + + }) }); From 001242535e490c60423482fa89d0ab63aad64fe8 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 31 Jul 2018 09:38:54 +0100 Subject: [PATCH 086/203] Fixed the error in previous build, solidity test in wrong directory --- {contracts => test}/PatriciaTrieTest.sol | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {contracts => test}/PatriciaTrieTest.sol (100%) diff --git a/contracts/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol similarity index 100% rename from contracts/PatriciaTrieTest.sol rename to test/PatriciaTrieTest.sol From 016eab07825a2ce8c41e432fde33cce46ae8baa3 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Tue, 31 Jul 2018 09:49:22 +0100 Subject: [PATCH 087/203] added missing go-dep and package-lock files and started test flow of contracts in golanf --- ion-cli/.gitignore | 1 + ion-cli/Gopkg.lock | 240 + ion-cli/Gopkg.toml | 46 + ion-cli/flow_test/flow_test.go | 236 + package-lock.json | 9380 ++++++++++++++++++++++++++++++++ 5 files changed, 9903 insertions(+) create mode 100644 ion-cli/Gopkg.lock create mode 100644 ion-cli/Gopkg.toml create mode 100644 ion-cli/flow_test/flow_test.go create mode 100644 package-lock.json diff --git a/ion-cli/.gitignore b/ion-cli/.gitignore index 8d335a8..e51b86e 100644 --- a/ion-cli/.gitignore +++ b/ion-cli/.gitignore @@ -1 +1,2 @@ ion-cli +vendor diff --git a/ion-cli/Gopkg.lock b/ion-cli/Gopkg.lock new file mode 100644 index 0000000..773aa19 --- /dev/null +++ b/ion-cli/Gopkg.lock @@ -0,0 +1,240 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/abiosoft/ishell" + packages = ["."] + revision = "0a6b1640e32638dd433ee7e57ec325a7bdd79561" + version = "v2.0.0" + +[[projects]] + branch = "master" + name = "github.com/abiosoft/readline" + packages = ["."] + revision = "155bce2042db95a783081fab225e74dd879055b0" + +[[projects]] + branch = "master" + name = "github.com/aristanetworks/goarista" + packages = ["monotime"] + revision = "3e95f038af02770089c3988f48f9e1a6b6fe2ac5" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcd" + packages = ["btcec"] + revision = "9a2f9524024889e129a5422aca2cff73cb3eabf6" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/edsrzf/mmap-go" + packages = ["."] + revision = "0bce6a6887123b67a60366d2c9fe2dfb74289d2e" + +[[projects]] + name = "github.com/ethereum/go-ethereum" + packages = [ + ".", + "accounts", + "accounts/abi", + "accounts/abi/bind", + "accounts/abi/bind/backends", + "accounts/keystore", + "common", + "common/bitutil", + "common/hexutil", + "common/math", + "common/mclock", + "consensus", + "consensus/ethash", + "consensus/misc", + "core", + "core/bloombits", + "core/rawdb", + "core/state", + "core/types", + "core/vm", + "crypto", + "crypto/bn256", + "crypto/bn256/cloudflare", + "crypto/bn256/google", + "crypto/randentropy", + "crypto/secp256k1", + "crypto/sha3", + "eth/filters", + "ethclient", + "ethdb", + "event", + "log", + "metrics", + "p2p/netutil", + "params", + "rlp", + "rpc", + "trie" + ] + revision = "37685930d953bcbe023f9bc65b135a8d8b8f1488" + version = "v1.8.12" + +[[projects]] + name = "github.com/fatih/color" + packages = ["."] + revision = "5b77d2a35fb0ede96d138fc9a99f5c9b6aef11b4" + version = "v1.7.0" + +[[projects]] + branch = "master" + name = "github.com/flynn-archive/go-shlex" + packages = ["."] + revision = "3f9db97f856818214da2e1057f8ad84803971cff" + +[[projects]] + name = "github.com/go-stack/stack" + packages = ["."] + revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" + version = "v1.7.0" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/golang-lru" + packages = [ + ".", + "simplelru" + ] + revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3" + +[[projects]] + name = "github.com/mattn/go-colorable" + packages = ["."] + revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" + version = "v0.0.9" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/maxrobot/go-ethereum" + packages = ["crypto"] + revision = "dea1ce052a10cd7d401a5c04f83f371a06fe293c" + version = "v1.8.11" + +[[projects]] + name = "github.com/pborman/uuid" + packages = ["."] + revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53" + version = "v1.1" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/rjeczalik/notify" + packages = ["."] + revision = "52ae50d8490436622a8941bd70c3dbe0acdd4bbf" + version = "v0.9.0" + +[[projects]] + name = "github.com/rs/cors" + packages = ["."] + revision = "3fb1b69b103a84de38a19c3c6ec073dd6caa4d3f" + version = "v1.5.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert"] + revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" + version = "v1.2.2" + +[[projects]] + branch = "master" + name = "github.com/syndtr/goleveldb" + packages = [ + "leveldb", + "leveldb/cache", + "leveldb/comparer", + "leveldb/errors", + "leveldb/filter", + "leveldb/iterator", + "leveldb/journal", + "leveldb/memdb", + "leveldb/opt", + "leveldb/storage", + "leveldb/table", + "leveldb/util" + ] + revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "pbkdf2", + "ripemd160", + "scrypt" + ] + revision = "c126467f60eb25f8f27e5a981f32a87e3965053f" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["websocket"] + revision = "c4299a1a0d8524c11563db160fbf9bddbceadb21" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "bd9dbc187b6e1dacfdd2722a87e83093c2d7bd6e" + +[[projects]] + branch = "master" + name = "golang.org/x/tools" + packages = [ + "go/ast/astutil", + "imports", + "internal/fastwalk" + ] + revision = "8cc4e8a6f4841aa92a8683fca47bc5d64b58875b" + +[[projects]] + name = "gopkg.in/fatih/set.v0" + packages = ["."] + revision = "57907de300222151a123d29255ed17f5ed43fad3" + version = "v0.1.0" + +[[projects]] + branch = "v2" + name = "gopkg.in/karalabe/cookiejar.v2" + packages = ["collections/prque"] + revision = "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57" + +[[projects]] + branch = "v2" + name = "gopkg.in/natefinch/npipe.v2" + packages = ["."] + revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "805e01dd280107fbb7b37497eab1b47175b241c1a5b253db91a375d83d208ae5" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/ion-cli/Gopkg.toml b/ion-cli/Gopkg.toml new file mode 100644 index 0000000..d511c01 --- /dev/null +++ b/ion-cli/Gopkg.toml @@ -0,0 +1,46 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/abiosoft/ishell" + version = "2.0.0" + +[[constraint]] + name = "github.com/ethereum/go-ethereum" + version = "1.8.12" + +[[constraint]] + name = "github.com/maxrobot/go-ethereum" + version = "1.8.11" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.2" + +[prune] + go-tests = true + unused-packages = true diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/flow_test.go new file mode 100644 index 0000000..0b6b8f0 --- /dev/null +++ b/ion-cli/flow_test/flow_test.go @@ -0,0 +1,236 @@ +package ionflow + +import ( + "bytes" + "context" + "math/big" + "regexp" + "strings" + "testing" + + contract "github.com/clearmatics/ion/ion-cli/contracts" + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" +) + +func TestRawTransactionSimulated(t *testing.T) { + ctx := context.Background() + initialBalance := big.NewInt(1000000000) + + userAKey, _ := crypto.GenerateKey() + userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) + + alloc := make(core.GenesisAlloc) + alloc[userAAddr] = core.GenesisAccount{ + Balance: initialBalance, + } + + blockchain := backends.NewSimulatedBackend(alloc) + + userBKey, _ := crypto.GenerateKey() + userBAddr := crypto.PubkeyToAddress(userBKey.PublicKey) + + // create transaction + // NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) + from := userAAddr // useless variable, just to make clear who the signer is + nonce, err := blockchain.PendingNonceAt(ctx, from) // uint64(0) + if err != nil { + t.Fatal("Error getting pending nonce ", err) + } + to := userBAddr + amount := big.NewInt(10000) // random amount + gasLimit := uint64(30000) // random magic number (we could estimate) + gasPrice, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) + if err != nil { + t.Fatal("Error suggesting gas price ", err) + } + // data := []byte{} + tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, nil) + + // to better understand the different signers + // worth looking into https://github.com/ethereum/go-ethereum/blob/cbfb40b0aab093e1b612f3b16834894b2cc67882/core/types/transaction_signing.go#L42-L53 + // signer need chainID + //chainID := big.NewInt(18) + //signer := types.NewEIP155Signer(chainID) + // simulated backend used homestead signer... but the latest might be EIP155? + signer := types.HomesteadSigner{} + signedTx, err := types.SignTx(tx, signer, userAKey) + if err != nil { + t.Fatal("Error signing tx: ", err) + } + + blockchain.SendTransaction(ctx, signedTx) + blockchain.Commit() + + txReceipt, _ := blockchain.TransactionReceipt(ctx, signedTx.Hash()) + + gasUsed := big.NewInt(int64(txReceipt.GasUsed)) + balA, err := blockchain.BalanceAt(ctx, userAAddr, nil) + if err != nil { + t.Fatal("Error retrieving balance of user A") + } + balB, err := blockchain.BalanceAt(ctx, userBAddr, nil) + if err != nil { + t.Fatal("Error retrieving balance of user B") + } + sum := new(big.Int) + sum.Add(balA, balB) + sum.Add(sum, gasUsed) + + // assert + if sum.Cmp(initialBalance) != 0 { + t.Fatal("FAILED: bad sum of balances and gas cost of transfer") + } +} + +// inspired by https://medium.com/@akshay_111meher/creating-offline-raw-transactions-with-go-ethereum-8d6cc8174c5d +func TestDeployRawContract(t *testing.T) { + ctx := context.Background() + initialBalance := big.NewInt(1000000000) + + userAKey, _ := crypto.GenerateKey() + userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) + + // start simulated blockchain + alloc := make(core.GenesisAlloc) + alloc[userAAddr] = core.GenesisAccount{ + Balance: initialBalance, + } + blockchain := backends.NewSimulatedBackend(alloc) + + // --------------------------------------------- + // DEPLOY PATRICIA LIB ADDRESS + // --------------------------------------------- + // generate payload bytes (we are using PatriciaTrie in our example) + contractBinStr := contract.PatriciaTrieBin + contractABIStr := contract.PatriciaTrieABI + bytecode := common.Hex2Bytes(contractBinStr) + abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) + if err != nil { + t.Fatal("ERROR reading PatriciaTrie ABI ", err) + } + // packedABI, err := abi.Pack("",arg1,arg2,arg3) // if there is construxtor + packedABI, err := abiPatriciaTrie.Pack("") + if err != nil { + t.Fatal("ERROR packing ABI ", err) + } + payloadBytecode := append(bytecode, packedABI...) + + // transaction parameters + from := userAAddr // useless variable, just to make clear who the signer is + nonce, err := blockchain.PendingNonceAt(ctx, from) // uint64(0) + if err != nil { + t.Fatal("Error getting pending nonce ", err) + } + amount := big.NewInt(0) // random amount + gasLimit := uint64(3000000) // random magic number (we could estimate) + gasPrice, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) + if err != nil { + t.Fatal("Error suggesting gas price ", err) + } + + // create contract transaction NewContractCreation is the same has NewTransaction with `to` == nil + // tx := types.NewTransaction(nonce, nil, amount, gasLimit, gasPrice, payloadBytecode) + tx := types.NewContractCreation(nonce, amount, gasLimit, gasPrice, payloadBytecode) + + // sign transaction + signer := types.HomesteadSigner{} + signedTx, err := types.SignTx(tx, signer, userAKey) + if err != nil { + t.Fatal("Error signing tx: ", err) + } + + blockchain.SendTransaction(ctx, signedTx) + blockchain.Commit() + + txReceipt, err := blockchain.TransactionReceipt(ctx, signedTx.Hash()) + if err != nil { + t.Fatal("ERROR getting tx receipt", err) + } + + // --------------------------------------------- + // DEPLOY ION CONTRACT WITH PATRICIA LIB ADDRESS + // --------------------------------------------- + // after PatriciaTrie is deployed we deploy the Ion contract + patriciaTrieLibAddr := txReceipt.ContractAddress + + // generate payload bytes (we are using Ion in our example) + // we added the key word Ion to make the variables different form the previous + contractIonBinStr := contract.IonBin + contractIonABIStr := contract.IonABI + + // add library address to Ion bytecode + var re = regexp.MustCompile(`__.*PatriciaTrie.*__`) + contractIonBinStrWithLibAddr := re.ReplaceAllString(contractIonBinStr, patriciaTrieLibAddr.Hex()[2:]) + + bytecodeIon := common.Hex2Bytes(contractIonBinStrWithLibAddr) + abiIon, err := abi.JSON(strings.NewReader(contractIonABIStr)) + if err != nil { + t.Fatal("ERROR reading PatriciaTrie ABI ", err) + } + + constructorArg1Ion := crypto.Keccak256Hash([]byte("test argument")) // Ion argument + packedABIIon, err := abiIon.Pack("", constructorArg1Ion) // the Ion constructor argument is added here! + if err != nil { + t.Fatal("ERROR packing ABI ", err) + } + payloadBytecodeIon := append(bytecodeIon, packedABIIon...) + + // transaction parameters + fromIon := userAAddr // useless variable, just to make clear who the signer is + nonceIon, err := blockchain.PendingNonceAt(ctx, fromIon) // uint64(0) + if err != nil { + t.Fatal("Error getting pending nonce ", err) + } + amountIon := big.NewInt(0) + gasLimitIon := uint64(3000000) // random magic number (we could estimate) + gasPriceIon, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) + if err != nil { + t.Fatal("Error suggesting gas price ", err) + } + + // create transaction + txIon := types.NewContractCreation(nonceIon, amountIon, gasLimitIon, gasPriceIon, payloadBytecodeIon) + + // sign transaction + signedTxIon, err := types.SignTx(txIon, signer, userAKey) + if err != nil { + t.Fatal("Error signing tx: ", err) + } + + blockchain.SendTransaction(ctx, signedTxIon) + blockchain.Commit() + + // test to see if chain id in contract matches the one sent + txReceiptIon, err := blockchain.TransactionReceipt(ctx, signedTxIon.Hash()) + if err != nil { + t.Fatal("ERROR getting tx receipt", err) + } + ionAddr := txReceiptIon.ContractAddress + + // contract Call function (to actually run a write function we would need to add transaction) + methodName := "chainId" + out := new([32]byte) + input, err := abiIon.Pack(methodName) + if err != nil { + t.Fatal("ERROR packing the method name for the contract call", err) + } + msg := ethereum.CallMsg{From: userAAddr, To: &ionAddr, Data: input} + output, err := blockchain.CallContract(ctx, msg, nil) + if err != nil { + t.Fatal("ERROR calling the Ion Contract", err) + } + err = abiIon.Unpack(out, methodName, output) + if err != nil { + t.Fatal("ERROR upacking the call", err) + } + + if !bytes.Equal((*out)[:], constructorArg1Ion.Bytes()) { + t.Fatalf("ERROR bytes stored in contract differ from bytes expected\n\tExpected:\t% 0x\n\tResult:\t\t% 0x\n", constructorArg1Ion.Bytes(), *out) + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..2681c09 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,9380 @@ +{ + "name": "ion-truffle", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "requires": { + "call-me-maybe": "1.0.1", + "glob-to-regexp": "0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", + "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "requires": { + "any-observable": "0.3.0" + } + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + }, + "abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "requires": { + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.19", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "antlr4": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.0.tgz", + "integrity": "sha1-KX+VbdwG+DOX/AmQ7PLgzyC/u+4=" + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true, + "optional": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.11.0", + "convert-source-map": "1.5.1", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.10", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.10", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "3.2.8", + "invariant": "2.2.4", + "semver": "5.4.1" + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-preset-node6": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-node6/-/babel-preset-node6-11.0.0.tgz", + "integrity": "sha1-CDWZRRckiYWinRj21GXasWu4p9g=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "requires": { + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "home-or-tmp": "2.0.0", + "lodash": "4.17.10", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "requires": { + "source-map": "0.5.7" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.10" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.10" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.10", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "bignumber.js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true, + "optional": true + }, + "binaryextensions": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", + "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "1.2.0", + "browserify-des": "1.0.2", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sha3": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", + "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", + "requires": { + "js-sha3": "0.3.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000865", + "electron-to-chromium": "1.3.52" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, + "buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "caniuse-lite": { + "version": "1.0.30000865", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", + "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "requires": { + "check-error": "1.0.2" + } + }, + "chai-bignumber": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/chai-bignumber/-/chai-bignumber-2.0.2.tgz", + "integrity": "sha512-BIdRNjRaoRj4bMsZLKbIZPMNKqmwnzNiyxqBYDSs6dFOCs9w8OHPuUE8e1bH60i1IhOzT0NjLtCD+lKEWB1KTQ==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "requires": { + "slice-ansi": "0.0.4", + "string-width": "1.0.2" + }, + "dependencies": { + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + } + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "1.0.1" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "requires": { + "color-name": "1.1.1" + } + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" + }, + "colors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.1.tgz", + "integrity": "sha512-jg/vxRmv430jixZrC+La5kMbUWqIg32/JsYNZb94+JEmzceYbWKTsv1OuTp+7EaqiaWRR2tPcykibwCRgclIsw==" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.2" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.3", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" + } + }, + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + }, + "dargs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" + }, + "death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "1.0.1" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "requires": { + "abstract-leveldown": "2.6.3" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-conflict": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "2.0.1" + } + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "2.0.2" + } + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "create-hmac": "1.1.7" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" + } + }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" + }, + "electron-to-chromium": { + "version": "1.3.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", + "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.5", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "tapable": "1.0.0" + } + }, + "envinfo": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-5.10.0.tgz", + "integrity": "sha512-rXbzXWvnQxy+TcqZlARbWVQwgGVVouVJgFZhLVN5htjLxl1thstrP2ZGi0pXC309AbK7gVOPU+ulz/tmpCI7iw==" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "1.0.1" + } + }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "requires": { + "string-template": "0.2.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.4.1", + "concat-stream": "1.6.2", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.3", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "3.3.10", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "xhr-request-promise": "0.1.2" + } + }, + "eth-proof": { + "version": "git+https://github.com/Shirikatsu/eth-proof.git#9b7fdea64ec5810c9c8a74c67ab96dbf0f035567", + "requires": { + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.7", + "keccak": "1.4.0", + "leveldown": "1.9.0", + "levelup": "1.3.9", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "rlp": "2.1.0", + "web3": "0.19.1" + }, + "dependencies": { + "ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "requires": { + "async": "2.6.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "1.3.7", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" + } + }, + "merkle-patricia-tree": { + "version": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "integrity": "sha512-wJSFtpBHTdtRsqrVH7UoEyQOm0KNqqmTdE3vzZ/FamCe/w3cIhv7+khBiMlNlvRsrhxIhCCeVbshaG/FMz+xiQ==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.6", + "rlp": "2.1.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + } + } + }, + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, + "ethereumjs-block": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.0.0.tgz", + "integrity": "sha512-doi2jH6fryGmBMzjxv2XFuJjcOUx4qZCil+qBNNdruNpDtXE1BZvC8Chj+YpuabzzTUZx5op9ob/MjXz3Xk+aw==", + "requires": { + "async": "2.6.1", + "ethereumjs-common": "0.3.1", + "ethereumjs-tx": "1.3.7", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "2.3.1" + } + }, + "ethereumjs-common": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-0.3.1.tgz", + "integrity": "sha512-o7GIMruAsif5RBe5A+dB3NhHjssYitoriiTzqHweTe5Wh45zL0kbpjPGTBQXo8dUp1QbjML40Cwsu+v7lcU6lA==" + }, + "ethereumjs-testrpc-sc": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.2.tgz", + "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", + "requires": { + "source-map-support": "0.5.6", + "webpack-cli": "2.1.5" + } + }, + "ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "requires": { + "ethereum-common": "0.0.18", + "ethereumjs-util": "5.2.0" + }, + "dependencies": { + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + } + } + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.1.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + }, + "ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "requires": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.2" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "2.2.4" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.4", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "1.4.0", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.23", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-future": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", + "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" + }, + "fast-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", + "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "requires": { + "@mrmlnc/readdir-enhanced": "2.2.1", + "@nodelib/fs.stat": "1.1.0", + "glob-parent": "3.1.0", + "is-glob": "4.0.0", + "merge2": "1.2.2", + "micromatch": "3.1.10" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.0.0", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "requires": { + "readable-stream": "2.3.6" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "flow-parser": { + "version": "0.76.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.76.0.tgz", + "integrity": "sha512-p+K8OKiMlq8AIZH8KTydHEGUUd71AqfCL+zTJNsdHtQmX3i3eaeIysF83Ad6Oo7OQcHCj3vocb/EHYiEyq+ZBg==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "1.1.4" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.19" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "ganache-cli": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.6.tgz", + "integrity": "sha512-S+mPguwQD8dt9T0O/7mH941U9IYDbmCsoenCr31Zlr9yxjSYdNbWYGj3xsNw8CViZsMRGwIYeCaHPqK4bx2YVw==", + "dev": true, + "requires": { + "source-map-support": "0.5.6" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "gh-got": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", + "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", + "requires": { + "got": "7.1.0", + "is-plain-obj": "1.1.0" + }, + "dependencies": { + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + } + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "github-username": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", + "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", + "requires": { + "gh-got": "6.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-all": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", + "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", + "requires": { + "glob": "7.1.2", + "yargs": "1.2.6" + }, + "dependencies": { + "minimist": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" + }, + "yargs": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", + "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", + "requires": { + "minimist": "0.1.0" + } + } + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "2.19.0", + "process": "0.5.2" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "requires": { + "@sindresorhus/is": "0.7.0", + "cacheable-request": "2.1.4", + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "into-stream": "3.1.0", + "is-retry-allowed": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "mimic-response": "1.0.1", + "p-cancelable": "0.4.1", + "p-timeout": "2.0.1", + "pify": "3.0.0", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "3.0.0", + "url-to-options": "1.0.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grouped-queue": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", + "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", + "requires": { + "lodash": "4.17.10" + } + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "1.4.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "1.1.5", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.5.0" + } + }, + "http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "2.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "2.3.0", + "p-is-promise": "1.1.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "1.4.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "requires": { + "symbol-observable": "1.2.0" + }, + "dependencies": { + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-scoped": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", + "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", + "requires": { + "scoped-regex": "1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.12.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.1", + "wordwrap": "1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "requires": { + "binaryextensions": "2.1.1", + "editions": "1.3.4", + "textextensions": "2.2.0" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "js-sha3": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", + "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jscodeshift": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.1.tgz", + "integrity": "sha512-sRMollbhbmSDrR79JMAnhEjyZJlQQVozeeY9A6/KNuV26DNcuB3mGSCWXp0hks9dcwRNOELbNOiwraZaXXRk5Q==", + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "7.0.0-beta.47", + "colors": "1.3.1", + "flow-parser": "0.76.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "neo-async": "2.5.1", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.15.3", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.47", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", + "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==" + } + } + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + }, + "json-bigint-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint-string/-/json-bigint-string-1.0.0.tgz", + "integrity": "sha1-M5l4TXeLt4RAvXLHCUrw4HW75oM=", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "1.3.0", + "inherits": "2.0.3", + "nan": "2.10.0", + "safe-buffer": "5.1.2" + } + }, + "keccakjs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", + "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", + "requires": { + "browserify-sha3": "0.0.1", + "sha3": "1.2.2" + } + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "optional": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + }, + "level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "requires": { + "inherits": "2.0.3", + "level-errors": "1.0.5", + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "leveldown": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-1.9.0.tgz", + "integrity": "sha512-3MwcrnCUIuFiKp/jSrG1UqDTV4k1yH8f5HH6T9dpqCKG+lRxcfo2KwAqbzTT+TTKfCbaATeHMy9mm1y6sI3ZvA==", + "requires": { + "abstract-leveldown": "2.7.2", + "bindings": "1.3.0", + "fast-future": "1.0.2", + "nan": "2.7.0", + "prebuild-install": "2.5.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "requires": { + "deferred-leveldown": "1.2.2", + "level-codec": "7.0.1", + "level-errors": "1.0.5", + "level-iterator-stream": "1.3.1", + "prr": "1.0.1", + "semver": "5.4.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "listr": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.1.tgz", + "integrity": "sha512-MSMUUVN1f8aRnPi4034RkOqdiUlpYW+FqwFE3aL0uYNPRavkt2S2SsSpDDofn8BDpqv2RNnsdOcCHWsChcq77A==", + "requires": { + "@samverschueren/stream-to-observable": "0.3.0", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "1.1.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "6.2.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + }, + "rxjs": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", + "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", + "requires": { + "tslib": "1.9.3" + } + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" + }, + "listr-update-renderer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", + "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "requires": { + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "1.0.1" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "1.2.0" + } + }, + "mem-fs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", + "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", + "requires": { + "through2": "2.0.3", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" + } + }, + "mem-fs-editor": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-4.0.3.tgz", + "integrity": "sha512-tgWmwI/+6vwu6POan82dTjxEpwAoaj0NAFnghtVo/FcLK2/7IhPUtFUUYlwou4MOY6OtjTUJtwpfH1h+eSUziw==", + "requires": { + "commondir": "1.0.1", + "deep-extend": "0.6.0", + "ejs": "2.6.1", + "glob": "7.1.2", + "globby": "7.1.1", + "isbinaryfile": "3.0.2", + "mkdirp": "0.5.1", + "multimatch": "2.1.0", + "rimraf": "2.6.2", + "through2": "2.0.3", + "vinyl": "2.2.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.10", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + } + } + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "requires": { + "abstract-leveldown": "2.7.2", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "0.1.7", + "readable-stream": "2.3.6" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge2": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", + "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==" + }, + "merkle-patricia-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", + "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.6", + "rlp": "2.1.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" + }, + "mime-types": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "requires": { + "mime-db": "1.35.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "0.1.1" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", + "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==" + }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" + }, + "node-abi": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", + "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "requires": { + "semver": "5.4.1" + } + }, + "node-dir": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", + "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "requires": { + "chalk": "0.4.0", + "underscore": "1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" + } + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.0.9" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.3" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "2.0.0", + "query-string": "5.1.1", + "sort-keys": "2.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "requires": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "oboe": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", + "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", + "requires": { + "http-https": "1.0.0" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "1.2.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "original-require": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", + "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "requires": { + "p-reduce": "1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-lazy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", + "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "1.3.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-headers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", + "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", + "requires": { + "for-each": "0.3.3", + "trim": "0.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.2" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "requires": { + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, + "pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + } + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "prettier": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.0.tgz", + "integrity": "sha512-KtQ2EGaUwf2EyDfp1fxyEb0PqGKakVm0WyXwDt6u+cAoxbO2Z2CwKvOe3+b4+F2IlO9lYHi1kqFuRM70ddBnow==" + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.2" + } + }, + "randomhex": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "read-chunk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", + "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", + "requires": { + "pify": "3.0.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" + } + }, + "recast": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.3.tgz", + "integrity": "sha512-xqnagxQH7mL4+UpcCVMObPPdjCEE2dmfGcTwcdpyNgZOd9W0rfdLRF3+smoA+AQqMw6xK6G4021dAQK8XfPYIQ==", + "requires": { + "ast-types": "0.11.5", + "esprima": "4.0.1", + "private": "0.1.8", + "source-map": "0.6.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "1.8.1" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==" + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "requires": { + "regenerate": "1.4.0", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "0.5.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "req-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", + "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", + "requires": { + "req-from": "1.0.1" + } + }, + "req-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", + "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", + "requires": { + "resolve-from": "2.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + } + } + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.19", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "1.0.1" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "rlp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", + "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "requires": { + "rx-lite": "4.0.8" + } + }, + "rxjs": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", + "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "scoped-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" + }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "requires": { + "nan": "2.10.0" + } + }, + "scrypt.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", + "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", + "requires": { + "scrypt": "6.0.3", + "scryptsy": "1.2.1" + } + }, + "scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "requires": { + "pbkdf2": "3.0.16" + } + }, + "secp256k1": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.0.tgz", + "integrity": "sha512-e5QIJl8W7Y4tT6LHffVcZAxJjvpgE5Owawv6/XCYPQljE9aP2NFFddQ8OYMKhdLshNu88FfL3qCN3/xYkXGRsA==", + "requires": { + "bindings": "1.3.0", + "bip66": "1.1.5", + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "drbg.js": "1.0.1", + "elliptic": "6.4.0", + "nan": "2.10.0", + "safe-buffer": "5.1.2" + } + }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.3", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.2" + } + }, + "servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "requires": { + "body-parser": "1.18.3", + "cors": "2.8.4", + "express": "4.16.3", + "request": "2.87.0", + "xhr": "2.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "optional": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "sha3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", + "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", + "requires": { + "nan": "2.10.0" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + } + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "3.2.2" + } + }, + "sol-explore": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", + "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=" + }, + "solc": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", + "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", + "requires": { + "fs-extra": "0.30.0", + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "semver": "5.4.1", + "yargs": "4.8.1" + } + }, + "solhint": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.2.1.tgz", + "integrity": "sha512-3B0ydhkOlicyyTmKnwJC6kiwdJUXvbbDYXcy8m7rznoQPgzzkmSOsJgb9BAe+KBQP5BD3PLgcoOQ84t3FSxqsQ==", + "requires": { + "antlr4": "4.7.0", + "commander": "2.11.0", + "eslint": "4.19.1", + "glob": "7.1.2", + "ignore": "3.3.10", + "lodash": "4.17.10" + } + }, + "solidity-coverage": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.5.5.tgz", + "integrity": "sha512-WexTLFZ3NBIWGYpNgWHtFLkASdoGP0i5Q/OJzwoCpHNtG1QrJO/mxUctc5BghP8srwMN8HxCtUJtu/eyGbIOJw==", + "requires": { + "death": "1.1.0", + "ethereumjs-testrpc-sc": "6.1.2", + "istanbul": "0.4.5", + "keccakjs": "0.2.1", + "req-cwd": "1.0.1", + "shelljs": "0.7.8", + "sol-explore": "1.6.2", + "solidity-parser-sc": "0.4.11", + "tree-kill": "1.2.0", + "web3": "0.18.4" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + }, + "web3": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", + "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + } + } + }, + "solidity-parser-sc": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz", + "integrity": "sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw==", + "requires": { + "mocha": "4.1.0", + "pegjs": "0.10.0", + "yargs": "4.8.1" + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", + "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "requires": { + "buffer-from": "1.1.0", + "source-map": "0.6.1" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "requires": { + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.4.1", + "lodash": "4.17.10", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.6.1" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "textextensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", + "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "truffle": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.13.tgz", + "integrity": "sha1-vydYaYi0/4RWPt+/MrR5QUCKdq0=", + "dev": true, + "requires": { + "mocha": "4.1.0", + "original-require": "1.0.1", + "solc": "0.4.24" + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.19" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "optional": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "optional": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==" + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "2.0.0" + } + }, + "url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "utf8": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", + "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + }, + "v8-compile-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", + "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" + } + }, + "web3": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", + "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", + "requires": { + "bignumber.js": "4.1.0", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + }, + "web3-core": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.35.tgz", + "integrity": "sha512-ayGavbgVk4KL9Y88Uv411fBJ0SVgVfKhKEBweKYzmP0zOqneMzWt6YsyD1n6kRvjAbqA0AfUPEOKyMNjcx2tjw==", + "requires": { + "web3-core-helpers": "1.0.0-beta.35", + "web3-core-method": "1.0.0-beta.35", + "web3-core-requestmanager": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz", + "integrity": "sha512-APOu3sEsamyqWt//8o4yq9KF25/uqGm+pQShson/sC4gKzmfJB07fLo2ond0X30E8fIqAPeVCotPXQxGciGUmA==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-method": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz", + "integrity": "sha512-jidImCide8q0GpfsO4L73qoHrbkeWgwU3uOH5DKtJtv0ccmG086knNMRgryb/o9ZgetDWLmDEsJnHjBSoIwcbA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35", + "web3-core-promievent": "1.0.0-beta.35", + "web3-core-subscriptions": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz", + "integrity": "sha512-GvqXqKq07OmHuVi5uNRg6k79a1/CI0ViCC+EtNv4CORHtDRmYEt5Bvdv6z6FJEiaaQkD0lKbFwNhLxutx7HItw==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.35.tgz", + "integrity": "sha512-S+zW2h17ZZQU9oe3yaCJE0E7aJS4C3Kf4kGPDv+nXjW0gKhQQhgVhw1Doq/aYQGqNSWJp7f1VHkz5gQWwg6RRg==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35", + "web3-providers-http": "1.0.0-beta.35", + "web3-providers-ipc": "1.0.0-beta.35", + "web3-providers-ws": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.35.tgz", + "integrity": "sha512-gXzLrWvcGkGiWq1y33Z4Y80XI8XMrwowiQJkrPSjQ81K5PBKquOGwcMffLaKcwdmEy/NpsOXDeFo3eLE1Ghvvw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz", + "integrity": "sha512-KUDC+EtFFYG8z01ZleKrASdjj327/rtWHzEt6RWsEj7bBa0bGp9nEh+nqdZx/Sdgz1O8tnfFzJlrRcXpfr1vGg==", + "dev": true, + "requires": { + "bn.js": "4.11.6", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + } + } + }, + "web3-eth-accounts": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz", + "integrity": "sha512-duIgRsfht/0kAW/eQ0X9lKtVIykbETrnM2H7EnvplCzPHtQLodpib4o9JXfh9n6ZDgdDC7cuJoiVB9QJg089ew==", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.35", + "web3-core-helpers": "1.0.0-beta.35", + "web3-core-method": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz", + "integrity": "sha512-H5wkcNcAIc+h/WoDIKv7ZYmrM2Xqu3O7jBQl1IWo73EDVQji+AoB2i3J8tuwI1yZRInRwrfpI3Zuwuf54hXHmQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.35.tgz", + "integrity": "sha512-DcIMFq52Fb08UpWyZ3ZlES6NsNqJnco4hBS/Ej6eOcASfuUayPI+GLkYVZsnF3cBYqlH+DOKuArcKSuIxK7jIA==", + "requires": { + "web3-core-helpers": "1.0.0-beta.35", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.35.tgz", + "integrity": "sha512-iB0FG0HcpUnayfa8pn4guqEQ4Y1nrroi/jffdtQgFkrNt0sD3fMSwwC0AbmECqj3tDLl0e1slBR0RENll+ZF0g==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.35.tgz", + "integrity": "sha512-Cx64NgDStynKaUGDIIOfaCd0fZusL8h5avKTkdTjUu2aHhFJhZoVBGVLhoDtUaqZGWIZGcBJOoVf2JkGUOjDRQ==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-utils": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.35.tgz", + "integrity": "sha512-Dq6f0SOKj3BDFRgOPnE6ALbzBDCKVIW8mKWVf7tGVhTDHf+wQaWwQSC3aArFSqdExB75BPBPyDpuMTNszhljpA==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + } + } + }, + "webpack-addons": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", + "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", + "requires": { + "jscodeshift": "0.4.1" + }, + "dependencies": { + "ast-types": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "jscodeshift": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", + "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", + "requires": { + "async": "1.5.2", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "6.18.0", + "colors": "1.3.1", + "flow-parser": "0.76.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.12.9", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + } + }, + "recast": { + "version": "0.12.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", + "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", + "requires": { + "ast-types": "0.10.1", + "core-js": "2.5.7", + "esprima": "4.0.1", + "private": "0.1.8", + "source-map": "0.6.1" + } + } + } + }, + "webpack-cli": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.1.5.tgz", + "integrity": "sha512-CiWQR+1JS77rmyiO6y1q8Kt/O+e8nUUC9YfJ25JtSmzDwbqJV7vIsh3+QKRHVTbTCa0DaVh8iY1LBiagUIDB3g==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "diff": "3.5.0", + "enhanced-resolve": "4.1.0", + "envinfo": "5.10.0", + "glob-all": "3.1.0", + "global-modules": "1.0.0", + "got": "8.3.2", + "import-local": "1.0.0", + "inquirer": "5.2.0", + "interpret": "1.1.0", + "jscodeshift": "0.5.1", + "listr": "0.14.1", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mkdirp": "0.5.1", + "p-each-series": "1.0.0", + "p-lazy": "1.0.0", + "prettier": "1.14.0", + "supports-color": "5.4.0", + "v8-compile-cache": "2.0.0", + "webpack-addons": "1.1.5", + "yargs": "11.1.0", + "yeoman-environment": "2.3.1", + "yeoman-generator": "2.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "requires": { + "debug": "2.6.9", + "nan": "2.10.0", + "typedarray-to-buffer": "3.1.5", + "yaeti": "0.0.6" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" + } + }, + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "4.3.2", + "is-function": "1.0.1", + "parse-headers": "2.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "requires": { + "buffer-to-arraybuffer": "0.0.5", + "object-assign": "4.1.1", + "query-string": "5.1.1", + "simple-get": "2.8.1", + "timed-out": "4.0.1", + "url-set-query": "1.0.0", + "xhr": "2.5.0" + } + }, + "xhr-request-promise": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", + "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", + "requires": { + "xhr-request": "1.1.0" + } + }, + "xhr2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", + "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" + }, + "xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "requires": { + "cookiejar": "2.1.2" + } + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + }, + "yeoman-environment": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.3.1.tgz", + "integrity": "sha512-7BFbWNnJqG8f0TFR/awcccHj7Vl9CeG66Yuu81DiVIamqO7Uo/EOrdryjNICdRJNFdaQTliN4HUkM1zQBzszCQ==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "globby": "8.0.1", + "grouped-queue": "0.3.3", + "inquirer": "5.2.0", + "is-scoped": "1.0.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mem-fs": "1.1.3", + "strip-ansi": "4.0.0", + "text-table": "0.2.0", + "untildify": "3.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globby": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", + "glob": "7.1.2", + "ignore": "3.3.10", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "yeoman-generator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.5.tgz", + "integrity": "sha512-rV6tJ8oYzm4mmdF2T3wjY+Q42jKF2YiiD0VKfJ8/0ZYwmhCKC9Xs2346HVLPj/xE13i68psnFJv7iS6gWRkeAg==", + "requires": { + "async": "2.6.1", + "chalk": "2.4.1", + "cli-table": "0.3.1", + "cross-spawn": "6.0.5", + "dargs": "5.1.0", + "dateformat": "3.0.3", + "debug": "3.1.0", + "detect-conflict": "1.0.1", + "error": "7.0.2", + "find-up": "2.1.0", + "github-username": "4.1.0", + "istextorbinary": "2.2.1", + "lodash": "4.17.10", + "make-dir": "1.3.0", + "mem-fs-editor": "4.0.3", + "minimist": "1.2.0", + "pretty-bytes": "4.0.2", + "read-chunk": "2.1.0", + "read-pkg-up": "3.0.0", + "rimraf": "2.6.2", + "run-async": "2.3.0", + "shelljs": "0.8.2", + "text-table": "0.2.0", + "through2": "2.0.3", + "yeoman-environment": "2.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "requires": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + } + } +} From 5764055c8bb7b271e2ac856025358a0a879bf2b2 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 31 Jul 2018 10:11:06 +0100 Subject: [PATCH 088/203] Added autogeneration of contract golang interfaces --- abi/Function.bin | 2 +- abi/Ion.abi | 2 +- abi/Ion.bin | 2 +- abi/IonCompatible.bin | 2 +- abi/PatriciaTrie.bin | 2 +- abi/Validation.abi | 2 +- abi/Validation.bin | 2 +- ion-cli/Makefile | 10 +- ion-cli/cli/cli.go | 2 +- ion-cli/contracts/ion.go | 902 --------------------------- ion-cli/contracts/ion_test.go | 445 +++++++------ ion-cli/contracts/patricia.go | 200 ------ ion-cli/contracts/validation.go | 842 ------------------------- ion-cli/contracts/validation_test.go | 245 ++++---- package.json | 3 +- test/PatriciaTrieTest.sol | 2 +- 16 files changed, 353 insertions(+), 2312 deletions(-) delete mode 100644 ion-cli/contracts/ion.go delete mode 100644 ion-cli/contracts/patricia.go delete mode 100644 ion-cli/contracts/validation.go diff --git a/abi/Function.bin b/abi/Function.bin index ba0272a..310c8c5 100644 --- a/abi/Function.bin +++ b/abi/Function.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051604080610b28833981018060405281019080805190602001909291908051906020019092919050505081806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610a57806100d16000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d0fdb2b314610046575b600080fd5b34801561005257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff1916906020019092919050505061022d565b604051808215151515815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f484c1f78b8b88876040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180856000191660001916815260200184600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156102fb5780820151818401526020810190506102e0565b50505050905090810190601f1680156103285780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156103b157600080fd5b505af11580156103c5573d6000803e3d6000fd5b505050506040513d60208110156103db57600080fd5b810190808051906020019092919050505015156103f457fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663affd8be98b8b89898c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156104c55780820151818401526020810190506104aa565b50505050905090810190601f1680156104f25780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561052b578082015181840152602081019050610510565b50505050905090810190601f1680156105585780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015610591578082015181840152602081019050610576565b50505050905090810190601f1680156105be5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1580156105e357600080fd5b505af11580156105f7573d6000803e3d6000fd5b505050506040513d602081101561060d57600080fd5b8101908080519060200190929190505050151561062657fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bec205b98b8b87878c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106f75780820151818401526020810190506106dc565b50505050905090810190601f1680156107245780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561075d578082015181840152602081019050610742565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b838110156107c35780820151818401526020810190506107a8565b50505050905090810190601f1680156107f05780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b15801561081557600080fd5b505af1158015610829573d6000803e3d6000fd5b505050506040513d602081101561083f57600080fd5b8101908080519060200190929190505050151561085857fe5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357064c3d8986856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200180602001836bffffffffffffffffffffffff19166bffffffffffffffffffffffff19168152602001828103825284818151815260200191508051906020019080838360005b8381101561094c578082015181840152602081019050610931565b50505050905090810190601f1680156109795780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d60208110156109c457600080fd5b8101908080519060200190929190505050156109eb576109e26109fd565b600190506109f0565b600090505b9998505050505050505050565b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e60405160405180910390a15600a165627a7a72305820eedb1504d9ba40d675657ad3dd7079e897af70039718f2e02e76d9caedcfc3a50029 \ No newline at end of file +608060405234801561001057600080fd5b50604051604080610b28833981018060405281019080805190602001909291908051906020019092919050505081806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610a57806100d16000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d0fdb2b314610046575b600080fd5b34801561005257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff1916906020019092919050505061022d565b604051808215151515815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f484c1f78b8b88876040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180856000191660001916815260200184600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156102fb5780820151818401526020810190506102e0565b50505050905090810190601f1680156103285780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156103b157600080fd5b505af11580156103c5573d6000803e3d6000fd5b505050506040513d60208110156103db57600080fd5b810190808051906020019092919050505015156103f457fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663affd8be98b8b89898c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156104c55780820151818401526020810190506104aa565b50505050905090810190601f1680156104f25780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561052b578082015181840152602081019050610510565b50505050905090810190601f1680156105585780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015610591578082015181840152602081019050610576565b50505050905090810190601f1680156105be5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1580156105e357600080fd5b505af11580156105f7573d6000803e3d6000fd5b505050506040513d602081101561060d57600080fd5b8101908080519060200190929190505050151561062657fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bec205b98b8b87878c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106f75780820151818401526020810190506106dc565b50505050905090810190601f1680156107245780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561075d578082015181840152602081019050610742565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b838110156107c35780820151818401526020810190506107a8565b50505050905090810190601f1680156107f05780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b15801561081557600080fd5b505af1158015610829573d6000803e3d6000fd5b505050506040513d602081101561083f57600080fd5b8101908080519060200190929190505050151561085857fe5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357064c3d8986856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200180602001836bffffffffffffffffffffffff19166bffffffffffffffffffffffff19168152602001828103825284818151815260200191508051906020019080838360005b8381101561094c578082015181840152602081019050610931565b50505050905090810190601f1680156109795780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d60208110156109c457600080fd5b8101908080519060200190929190505050156109eb576109e26109fd565b600190506109f0565b600090505b9998505050505050505050565b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e60405160405180910390a15600a165627a7a723058208dce48a6acecdc2c29df28051d1eb880843a0e0958c7720b53ec0e0e5c21b4020029 \ No newline at end of file diff --git a/abi/Ion.abi b/abi/Ion.abi index a83cfb8..221cda6 100644 --- a/abi/Ion.abi +++ b/abi/Ion.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"registeredChains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"validation_addr","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"validationAddr","type":"address"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckReceiptProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_txNodes","type":"bytes"},{"name":"_receiptNodes","type":"bytes"}],"name":"CheckRootsProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"},{"indexed":false,"name":"proofType","type":"uint256"}],"name":"VerifiedProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"registeredChains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"validationAddr","type":"address"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_validation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckReceiptProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_txNodes","type":"bytes"},{"name":"_receiptNodes","type":"bytes"}],"name":"CheckRootsProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"},{"indexed":false,"name":"proofType","type":"uint256"}],"name":"VerifiedProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin index 41354e3..b2e9bed 100644 --- a/abi/Ion.bin +++ b/abi/Ion.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b5060405160208061221f833981018060405281019080805190602001909291905050508060018160001916905550506121d18061004e6000396000f3006080604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100d5578063261e50731461011e5780634b3550301461018f57806352824374146101e657806353fe62e6146102a35780637558a01a1461030c5780639a8a0592146103ae578063affd8be9146103e1578063bec205b91461050a578063c18de0ef14610633578063e79b136c1461067c578063f22a195e146106fc578063f44ff7121461072f578063f484c1f71461075a575b600080fd5b3480156100e157600080fd5b506101006004803603810190808035906020019092919050505061083d565b60405180826000191660001916815260200191505060405180910390f35b34801561012a57600080fd5b5061014d6004803603810190808035600019169060200190929190505050610860565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561019b57600080fd5b506101cc60048036038101908080356000191690602001909291908035600019169060200190929190505050610893565b604051808215151515815260200191505060405180910390f35b3480156101f257600080fd5b506102a16004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108c2565b005b3480156102af57600080fd5b506102f26004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d71565b604051808215151515815260200191505060405180910390f35b34801561031857600080fd5b506103ac6004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035600019169060200190929190505050610da0565b005b3480156103ba57600080fd5b506103c3611124565b60405180826000191660001916815260200191505060405180910390f35b3480156103ed57600080fd5b506104f060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061112a565b604051808215151515815260200191505060405180910390f35b34801561051657600080fd5b5061061960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061152e565b604051808215151515815260200191505060405180910390f35b34801561063f57600080fd5b506106626004803603810190808035600019169060200190929190505050611932565b604051808215151515815260200191505060405180910390f35b34801561068857600080fd5b506106b960048036038101908080356000191690602001909291908035600019169060200190929190505050611952565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b34801561070857600080fd5b5061071161198f565b60405180826000191660001916815260200191505060405180910390f35b34801561073b57600080fd5b50610744611995565b6040518082815260200191505060405180910390f35b34801561076657600080fd5b5061082360048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199b565b604051808215151515815260200191505060405180910390f35b60028181548110151561084c57fe5b906000526020600020016000915090505481565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008060008960046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561096b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61097c6109778b611bda565b611c35565b975061098f61098a8a611bda565b611c35565b9650600560008c6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508594508473ffffffffffffffffffffffffffffffffffffffff166309fbd5368c8c8c6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610a6e578082015181840152602081019050610a53565b50505050905090810190601f168015610a9b5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610ad4578082015181840152602081019050610ab9565b50505050905090810190601f168015610b015780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015610b2357600080fd5b505af1158015610b37573d6000803e3d6000fd5b50505050610b66610b5f896000815181101515610b5057fe5b90602001906020020151611cf2565b6001611d57565b9350886040518082805190602001908083835b602083101515610b9e5780518252602082019150602081019050602083039250610b79565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092506001600760008d60001916600019168152602001908152602001600020600086600019166000191681526020019081526020016000206000015401915081600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206000018190555083600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206001018160001916905550610cb1610caa896004815181101515610c9b57fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206002018160001916905550610d1b610d14896005815181101515610d0557fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206003018160001916905550610d648b84611d6b565b5050505050505050505050565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600060015460001916856000191614151515610e4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000866000191660001916815260200190815260200160002060009054906101000a900460ff16151515610ee8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000876000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600285908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555060016006600087600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600060076000876000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600001819055508390508073ffffffffffffffffffffffffffffffffffffffff16630b5abdd08685856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808460001916600019168152602001806020018360001916600019168152602001828103825284818151815260200191508051906020019060200280838360005b83811015611084578082015181840152602081019050611069565b50505050905001945050505050600060405180830381600087803b1580156110ab57600080fd5b505af11580156110bf573d6000803e3d6000fd5b505050508360056000876000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b60015481565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156111cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600201546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b8381101561135c578082015181840152602081019050611341565b50505050905090810190601f1680156113895780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156113c25780820151818401526020810190506113a7565b50505050905090810190601f1680156113ef5780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561142857808201518184015260208101905061140d565b50505050905090810190601f1680156114555780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561147757600080fd5b505af415801561148b573d6000803e3d6000fd5b505050506040513d60208110156114a157600080fd5b810190808051906020019092919050505015156114ba57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600060028111156114ea57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156115cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611687576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600301546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611760578082015181840152602081019050611745565b50505050905090810190601f16801561178d5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156117c65780820151818401526020810190506117ab565b50505050905090810190601f1680156117f35780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561182c578082015181840152602081019050611811565b50505050905090810190601f1680156118595780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561187b57600080fd5b505af415801561188f573d6000803e3d6000fd5b505050506040513d60208110156118a557600080fd5b810190808051906020019092919050505015156118be57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600160028111156118ee57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000808560046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611a3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b86866006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611af4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008a60001916600019168152602001908152602001600020600089600019166000191681526020019081526020016000209350611b3387611dbc565b60001916846002015460001916141515611b4957fe5b611b5286611dbc565b60001916846003015460001916141515611b6857fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468989600280811115611b9757fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001945050505050949350505050565b611be2612150565b600080835191506000821415611c105760408051908101604052806000815260200160008152509250611c2e565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611c4161216a565b6000611c4c85611e6f565b1515611c5757600080fd5b611c6085611ea1565b925082604051908082528060200260200182016040528015611c9c57816020015b611c8961218b565b815260200190600190039081611c815790505b509350611ca885611f1b565b91505b611cb482611f63565b15611cea57611cc282611f8d565b8482815181101515611cd057fe5b906020019060200201819052508080600101915050611cab565b505050919050565b60606000826020015190506000811415611d0b57611d51565b806040519080825280601f01601f191660200182016040528015611d3e5781602001602082028038833980820191505090505b509150611d5083600001518383611fe9565b5b50919050565b600060208201915081830151905092915050565b60016006600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000611dc6612150565b606080611dd285611bda565b9250611ddd83611c35565b9150611e00826000815181101515611df157fe5b90602001906020020151611cf2565b9050806040518082805190602001908083835b602083101515611e385780518252602082019150602081019050602083039250611e13565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b600080600083602001511415611e885760009150611e9b565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611eb387611e6f565b1515611ec25760009550611f11565b86600001519350835160001a9450611ed98761202a565b840192506001876020015185010391505b8183111515611f0d57611efc836120b6565b830192508080600101915050611eea565b8095505b5050505050919050565b611f2361216a565b6000611f2e83611e6f565b1515611f3957600080fd5b611f428361202a565b83600001510190508282600001819052508082602001818152505050919050565b6000611f6d612150565b826000015190508060200151816000015101836020015110915050919050565b611f95612150565b600080611fa184611f63565b15611fdd5783602001519150611fb6826120b6565b90508183600001818152505080836020018181525050808201846020018181525050611fe2565b600080fd5b5050919050565b60006020601f83010484602085015b8284146120175760208402808301518183015260018501945050611ff8565b6000865160200187015250505050505050565b6000806000808460200151141561204457600092506120af565b83600001519050805160001a9150608082101561206457600092506120af565b60b8821080612080575060c0821015801561207f575060f882105b5b1561208e57600192506120af565b60c08210156120a557600160b783030192506120af565b600160f783030192505b5050919050565b600080825160001a905060808110156120d2576001915061214a565b60b88110156120e957600160808203019150612149565b60c08110156121135760b78103806020036101000a60018501510480820160010193505050612148565b60f881101561212a57600160c08203019150612147565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b60606040519081016040528061217e61218b565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582063bd23fd4aba60ad5fe5003097cfeb975ac723f7e78172be2b48321603b5cabd0029 \ No newline at end of file +608060405234801561001057600080fd5b50604051602080611fde83398101806040528101908080519060200190929190505050806001816000191690555050611f908061004e6000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100ca5780634b3550301461011357806353fe62e61461016a57806395b0ea00146101d35780639a8a059214610224578063affd8be914610257578063b64b633614610380578063bec205b9146103f1578063c18de0ef1461051a578063e79b136c14610563578063f22a195e146105e3578063f44ff71214610616578063f484c1f714610641575b600080fd5b3480156100d657600080fd5b506100f560048036038101908080359060200190929190505050610724565b60405180826000191660001916815260200191505060405180910390f35b34801561011f57600080fd5b5061015060048036038101908080356000191690602001909291908035600019169060200190929190505050610747565b604051808215151515815260200191505060405180910390f35b34801561017657600080fd5b506101b96004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610776565b604051808215151515815260200191505060405180910390f35b3480156101df57600080fd5b506102226004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107a5565b005b34801561023057600080fd5b506102396109af565b60405180826000191660001916815260200191505060405180910390f35b34801561026357600080fd5b5061036660048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506109b5565b604051808215151515815260200191505060405180910390f35b34801561038c57600080fd5b506103af6004803603810190808035600019169060200190929190505050610f45565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103fd57600080fd5b5061050060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610f78565b604051808215151515815260200191505060405180910390f35b34801561052657600080fd5b506105496004803603810190808035600019169060200190929190505050611508565b604051808215151515815260200191505060405180910390f35b34801561056f57600080fd5b506105a060048036038101908080356000191690602001909291908035600019169060200190929190505050611528565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b3480156105ef57600080fd5b506105f8611565565b60405180826000191660001916815260200191505060405180910390f35b34801561062257600080fd5b5061062b61156b565b6040518082815260200191505060405180910390f35b34801561064d57600080fd5b5061070a60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050611571565b604051808215151515815260200191505060405180910390f35b60028181548110151561073357fe5b906000526020600020016000915090505481565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6001546000191682600019161415151561084d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000836000191660001916815260200190815260200160002060009054906101000a900460ff161515156108eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555060028290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055508060056000846000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60015481565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610a58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610b2157600080fd5b505af1158015610b35573d6000803e3d6000fd5b505050506040513d6020811015610b4b57600080fd5b81019080805190602001909291905050501515610bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610c9557600080fd5b505af1158015610ca9573d6000803e3d6000fd5b505050506040513d6020811015610cbf57600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610d71578082015181840152602081019050610d56565b50505050905090810190601f168015610d9e5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610dd7578082015181840152602081019050610dbc565b50505050905090810190601f168015610e045780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610e3d578082015181840152602081019050610e22565b50505050905090810190601f168015610e6a5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610e8c57600080fd5b505af4158015610ea0573d6000803e3d6000fd5b505050506040513d6020811015610eb657600080fd5b81019080805190602001909291905050501515610ecf57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c60006002811115610eff57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561101b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156110e457600080fd5b505af11580156110f8573d6000803e3d6000fd5b505050506040513d602081101561110e57600080fd5b81019080805190602001909291905050501515611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561125857600080fd5b505af115801561126c573d6000803e3d6000fd5b505050506040513d602081101561128257600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611334578082015181840152602081019050611319565b50505050905090810190601f1680156113615780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b8381101561139a57808201518184015260208101905061137f565b50505050905090810190601f1680156113c75780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b838110156114005780820151818401526020810190506113e5565b50505050905090810190601f16801561142d5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561144f57600080fd5b505af4158015611463573d6000803e3d6000fd5b505050506040513d602081101561147957600080fd5b8101908080519060200190929190505050151561149257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c600160028111156114c257fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000806000808760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156116de57600080fd5b505af11580156116f2573d6000803e3d6000fd5b505050506040513d602081101561170857600080fd5b8101908080519060200190929190505050151561178d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1696508673ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561185257600080fd5b505af1158015611866573d6000803e3d6000fd5b505050506040513d602081101561187c57600080fd5b810190808051906020019092919050505095508673ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561191657600080fd5b505af115801561192a573d6000803e3d6000fd5b505050506040513d602081101561194057600080fd5b8101908080519060200190929190505050945061195c8a6119fe565b60001916866000191614151561196e57fe5b611977896119fe565b60001916856000191614151561198957fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c6002808111156119b857fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001975050505050505050949350505050565b6000611a08611f0f565b606080611a1485611ab1565b9250611a1f83611b0c565b9150611a42826000815181101515611a3357fe5b90602001906020020151611bc9565b9050806040518082805190602001908083835b602083101515611a7a5780518252602082019150602081019050602083039250611a55565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b611ab9611f0f565b600080835191506000821415611ae75760408051908101604052806000815260200160008152509250611b05565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611b18611f29565b6000611b2385611c2e565b1515611b2e57600080fd5b611b3785611c60565b925082604051908082528060200260200182016040528015611b7357816020015b611b60611f4a565b815260200190600190039081611b585790505b509350611b7f85611cda565b91505b611b8b82611d22565b15611bc157611b9982611d4c565b8482815181101515611ba757fe5b906020019060200201819052508080600101915050611b82565b505050919050565b60606000826020015190506000811415611be257611c28565b806040519080825280601f01601f191660200182016040528015611c155781602001602082028038833980820191505090505b509150611c2783600001518383611da8565b5b50919050565b600080600083602001511415611c475760009150611c5a565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611c7287611c2e565b1515611c815760009550611cd0565b86600001519350835160001a9450611c9887611de9565b840192506001876020015185010391505b8183111515611ccc57611cbb83611e75565b830192508080600101915050611ca9565b8095505b5050505050919050565b611ce2611f29565b6000611ced83611c2e565b1515611cf857600080fd5b611d0183611de9565b83600001510190508282600001819052508082602001818152505050919050565b6000611d2c611f0f565b826000015190508060200151816000015101836020015110915050919050565b611d54611f0f565b600080611d6084611d22565b15611d9c5783602001519150611d7582611e75565b90508183600001818152505080836020018181525050808201846020018181525050611da1565b600080fd5b5050919050565b60006020601f83010484602085015b828414611dd65760208402808301518183015260018501945050611db7565b6000865160200187015250505050505050565b60008060008084602001511415611e035760009250611e6e565b83600001519050805160001a91506080821015611e235760009250611e6e565b60b8821080611e3f575060c08210158015611e3e575060f882105b5b15611e4d5760019250611e6e565b60c0821015611e6457600160b78303019250611e6e565b600160f783030192505b5050919050565b600080825160001a90506080811015611e915760019150611f09565b60b8811015611ea857600160808203019150611f08565b60c0811015611ed25760b78103806020036101000a60018501510480820160010193505050611f07565b60f8811015611ee957600160c08203019150611f06565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611f3d611f4a565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820d6cf1288a129db81ed6bbc34f59ab6b76a8c79ff25da2ef9bb507004c96a65d10029 \ No newline at end of file diff --git a/abi/IonCompatible.bin b/abi/IonCompatible.bin index 93b6858..52cf03f 100644 --- a/abi/IonCompatible.bin +++ b/abi/IonCompatible.bin @@ -1 +1 @@ -6080604052348015600f57600080fd5b5060405160208060b483398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050603580607f6000396000f3006080604052600080fd00a165627a7a72305820ff572c047d1000242abe0ad1fe67b1eca042830f56970a40a559eec0d77707de0029 \ No newline at end of file +6080604052348015600f57600080fd5b5060405160208060b483398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050603580607f6000396000f3006080604052600080fd00a165627a7a7230582004a7d02edd9360be54604bf8d2702e8ec8cb90c5f32925f414bdc43d211679930029 \ No newline at end of file diff --git a/abi/PatriciaTrie.bin b/abi/PatriciaTrie.bin index 9e0cab5..134bc2b 100644 --- a/abi/PatriciaTrie.bin +++ b/abi/PatriciaTrie.bin @@ -1 +1 @@ -611322610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634f7142ad1461005d575b600080fd5b81801561006957600080fd5b5061015e600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035600019169060200190929190505050610178565b604051808215151515815260200191505060405180910390f35b600061018261127f565b60606000806060600060606101968b61030a565b96506101a187610365565b9550889450600093506101b58a6000610422565b9250600091505b85518210156102fa576101e586838151811015156101d657fe5b906020019060200201516107d2565b6040518082805190602001908083835b60208310151561021a57805182526020820191506020810190506020830392506101f5565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916856000191614151561026057600097506102fb565b610280868381518110151561027157fe5b90602001906020020151610365565b90506011815114156102a5576102988185858f610837565b80955081965050506102d2565b6002815114156102c8576102bb8185858f6109a5565b80955081965050506102d1565b600097506102fb565b5b6000600102856000191614156102ed576001841497506102fb565b81806001019250506101bc565b5b50505050505050949350505050565b61031261127f565b600080835191506000821415610340576040805190810160405280600081526020016000815250925061035e565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610371611299565b600061037c85610aa4565b151561038757600080fd5b61039085610ad6565b9250826040519080825280602002602001820160405280156103cc57816020015b6103b96112ba565b8152602001906001900390816103b15790505b5093506103d885610b50565b91505b6103e482610b98565b1561041a576103f282610bc2565b848281518110151561040057fe5b9060200190602002018190525080806001019150506103db565b505050919050565b6060806000806104306112d4565b6060600060ff6040519080825280601f01601f1916602001820160405280156104685781602001602082028038833980820191505090505b50955060009450600093505b88518410156106d6576104de898581518110151561048e57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002610c1e565b92508780156104ed5750600084145b156106155760017f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561052557fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105af575060037f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561058657fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b15610610578260016002811015156105c357fe5b6020020151868660ff168151811015156105d957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001850194505b6106c9565b82600060028110151561062457fe5b6020020151868660ff1681518110151561063a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535082600160028110151561067957fe5b6020020151866001870160ff1681518110151561069257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506002850194505b8380600101945050610474565b8460ff166040519080825280601f01601f19166020018201604052801561070c5781602001602082028038833980820191505090505b509150600090505b8460ff168110156107c357858181518110151561072d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002828281518110151561078657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050610714565b81965050505050505092915050565b606060008260200151905060008114156107eb57610831565b806040519080825280601f01601f19166020018201604052801561081e5781602001602082028038833980820191505090505b50915061083083600001518383610d04565b5b50919050565b600080600061084461127f565b6000865188141561089e57600061087b876108768c601081518110151561086757fe5b906020019060200201516107d2565b610d45565b610886576000610889565b60015b8160010291508060ff16905094509450610999565b86888151811015156108ac57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250888361ffff1681518110151561092e57fe5b906020019060200201519150600188019750602061094b836107d2565b51101561096b5761095e82898989610e1e565b8099508192505050610992565b61098f898461ffff1681518110151561098057fe5b90602001906020020151610e87565b90505b8088945094505b50505094509492505050565b60008060608060006109ce8960008151811015156109bf57fe5b90602001906020020151610e9c565b92506109db836001610422565b51880197508651881415610a38576000610a1587610a108c6001815181101515610a0157fe5b90602001906020020151610e9c565b610d45565b610a20576000610a23565b60015b8160010291508060ff16905094509450610a98565b6000610a45846001610422565b511415610a615760008081600102915080905094509450610a98565b610a82896001815181101515610a7357fe5b90602001906020020151610e9c565b9150610a8f826000610f0e565b90508088945094505b50505094509492505050565b600080600083602001511415610abd5760009150610ad0565b8260000151905060c0815160001a101591505b50919050565b600080600080600080610ae887610aa4565b1515610af75760009550610b46565b86600001519350835160001a9450610b0e87610fec565b840192506001876020015185010391505b8183111515610b4257610b3183611078565b830192508080600101915050610b1f565b8095505b5050505050919050565b610b58611299565b6000610b6383610aa4565b1515610b6e57600080fd5b610b7783610fec565b83600001510190508282600001819052508082602001818152505050919050565b6000610ba261127f565b826000015190508060200151816000015101836020015110915050919050565b610bca61127f565b600080610bd684610b98565b15610c125783602001519150610beb82611078565b90508183600001818152505080836020018181525050808201846020018181525050610c17565b600080fd5b5050919050565b610c266112d4565b600080610c34846004611112565b9150600f7f010000000000000000000000000000000000000000000000000000000000000002841690506040805190810160405280837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525092505050919050565b60006020601f83010484602085015b828414610d325760208402808301518183015260018501945050610d13565b6000865160200187015250505050505050565b6000816040518082805190602001908083835b602083101515610d7d5780518252602082019150602081019050602083039250610d58565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916836040518082805190602001908083835b602083101515610de45780518252602082019150602081019050602083039250610dbf565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614905092915050565b6000806060610e2c87610365565b9050601181511415610e4d57610e4481878787610837565b92509250610e7d565b600281511415610e6c57610e63818787876109a5565b92509250610e7d565b600080816001029150809050925092505b5094509492505050565b6000610e9282611176565b6001029050919050565b6060600080610eaa846111cd565b1515610eb557600080fd5b610ebe846111fe565b8092508193505050806040519080825280601f01601f191660200182016040528015610ef95781602001602082028038833980820191505090505b509250610f07828483610d04565b5050919050565b60008060008090505b6020811015610fe1576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610f5857fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610f17565b819250505092915050565b600080600080846020015114156110065760009250611071565b83600001519050805160001a915060808210156110265760009250611071565b60b8821080611042575060c08210158015611041575060f882105b5b156110505760019250611071565b60c082101561106757600160b78303019250611071565b600160f783030192505b5050919050565b600080825160001a90506080811015611094576001915061110c565b60b88110156110ab5760016080820301915061110b565b60c08110156110d55760b78103806020036101000a6001850151048082016001019350505061110a565b60f88110156110ec57600160c08203019150611109565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008160020a60ff16837f0100000000000000000000000000000000000000000000000000000000000000900460ff1681151561114b57fe5b047f010000000000000000000000000000000000000000000000000000000000000002905092915050565b6000806000611184846111cd565b151561118f57600080fd5b611198846111fe565b809250819350505060208111806111af5750600081145b156111b957600080fd5b806020036101000a82510492505050919050565b6000806000836020015114156111e657600091506111f8565b8260000151905060c0815160001a1091505b50919050565b600080600080600061120f866111cd565b151561121a57600080fd5b85600001519150815160001a9250608083101561123d5781945060019350611277565b60b883101561125b5760018660200151039350600182019450611276565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b604080519081016040528060008152602001600081525090565b6060604051908101604052806112ad6112ba565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a7230582062c120ac04d83a1f0be254ec010b3af455b1d08eca98fad20401929be7d7c8460029 \ No newline at end of file +611322610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634f7142ad1461005d575b600080fd5b81801561006957600080fd5b5061015e600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035600019169060200190929190505050610178565b604051808215151515815260200191505060405180910390f35b600061018261127f565b60606000806060600060606101968b61030a565b96506101a187610365565b9550889450600093506101b58a6000610422565b9250600091505b85518210156102fa576101e586838151811015156101d657fe5b906020019060200201516107d2565b6040518082805190602001908083835b60208310151561021a57805182526020820191506020810190506020830392506101f5565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916856000191614151561026057600097506102fb565b610280868381518110151561027157fe5b90602001906020020151610365565b90506011815114156102a5576102988185858f610837565b80955081965050506102d2565b6002815114156102c8576102bb8185858f6109a5565b80955081965050506102d1565b600097506102fb565b5b6000600102856000191614156102ed576001841497506102fb565b81806001019250506101bc565b5b50505050505050949350505050565b61031261127f565b600080835191506000821415610340576040805190810160405280600081526020016000815250925061035e565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610371611299565b600061037c85610aa4565b151561038757600080fd5b61039085610ad6565b9250826040519080825280602002602001820160405280156103cc57816020015b6103b96112ba565b8152602001906001900390816103b15790505b5093506103d885610b50565b91505b6103e482610b98565b1561041a576103f282610bc2565b848281518110151561040057fe5b9060200190602002018190525080806001019150506103db565b505050919050565b6060806000806104306112d4565b6060600060ff6040519080825280601f01601f1916602001820160405280156104685781602001602082028038833980820191505090505b50955060009450600093505b88518410156106d6576104de898581518110151561048e57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002610c1e565b92508780156104ed5750600084145b156106155760017f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561052557fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105af575060037f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561058657fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b15610610578260016002811015156105c357fe5b6020020151868660ff168151811015156105d957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001850194505b6106c9565b82600060028110151561062457fe5b6020020151868660ff1681518110151561063a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535082600160028110151561067957fe5b6020020151866001870160ff1681518110151561069257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506002850194505b8380600101945050610474565b8460ff166040519080825280601f01601f19166020018201604052801561070c5781602001602082028038833980820191505090505b509150600090505b8460ff168110156107c357858181518110151561072d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002828281518110151561078657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050610714565b81965050505050505092915050565b606060008260200151905060008114156107eb57610831565b806040519080825280601f01601f19166020018201604052801561081e5781602001602082028038833980820191505090505b50915061083083600001518383610d04565b5b50919050565b600080600061084461127f565b6000865188141561089e57600061087b876108768c601081518110151561086757fe5b906020019060200201516107d2565b610d45565b610886576000610889565b60015b8160010291508060ff16905094509450610999565b86888151811015156108ac57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250888361ffff1681518110151561092e57fe5b906020019060200201519150600188019750602061094b836107d2565b51101561096b5761095e82898989610e1e565b8099508192505050610992565b61098f898461ffff1681518110151561098057fe5b90602001906020020151610e87565b90505b8088945094505b50505094509492505050565b60008060608060006109ce8960008151811015156109bf57fe5b90602001906020020151610e9c565b92506109db836001610422565b51880197508651881415610a38576000610a1587610a108c6001815181101515610a0157fe5b90602001906020020151610e9c565b610d45565b610a20576000610a23565b60015b8160010291508060ff16905094509450610a98565b6000610a45846001610422565b511415610a615760008081600102915080905094509450610a98565b610a82896001815181101515610a7357fe5b90602001906020020151610e9c565b9150610a8f826000610f0e565b90508088945094505b50505094509492505050565b600080600083602001511415610abd5760009150610ad0565b8260000151905060c0815160001a101591505b50919050565b600080600080600080610ae887610aa4565b1515610af75760009550610b46565b86600001519350835160001a9450610b0e87610fec565b840192506001876020015185010391505b8183111515610b4257610b3183611078565b830192508080600101915050610b1f565b8095505b5050505050919050565b610b58611299565b6000610b6383610aa4565b1515610b6e57600080fd5b610b7783610fec565b83600001510190508282600001819052508082602001818152505050919050565b6000610ba261127f565b826000015190508060200151816000015101836020015110915050919050565b610bca61127f565b600080610bd684610b98565b15610c125783602001519150610beb82611078565b90508183600001818152505080836020018181525050808201846020018181525050610c17565b600080fd5b5050919050565b610c266112d4565b600080610c34846004611112565b9150600f7f010000000000000000000000000000000000000000000000000000000000000002841690506040805190810160405280837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525092505050919050565b60006020601f83010484602085015b828414610d325760208402808301518183015260018501945050610d13565b6000865160200187015250505050505050565b6000816040518082805190602001908083835b602083101515610d7d5780518252602082019150602081019050602083039250610d58565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916836040518082805190602001908083835b602083101515610de45780518252602082019150602081019050602083039250610dbf565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614905092915050565b6000806060610e2c87610365565b9050601181511415610e4d57610e4481878787610837565b92509250610e7d565b600281511415610e6c57610e63818787876109a5565b92509250610e7d565b600080816001029150809050925092505b5094509492505050565b6000610e9282611176565b6001029050919050565b6060600080610eaa846111cd565b1515610eb557600080fd5b610ebe846111fe565b8092508193505050806040519080825280601f01601f191660200182016040528015610ef95781602001602082028038833980820191505090505b509250610f07828483610d04565b5050919050565b60008060008090505b6020811015610fe1576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610f5857fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610f17565b819250505092915050565b600080600080846020015114156110065760009250611071565b83600001519050805160001a915060808210156110265760009250611071565b60b8821080611042575060c08210158015611041575060f882105b5b156110505760019250611071565b60c082101561106757600160b78303019250611071565b600160f783030192505b5050919050565b600080825160001a90506080811015611094576001915061110c565b60b88110156110ab5760016080820301915061110b565b60c08110156110d55760b78103806020036101000a6001850151048082016001019350505061110a565b60f88110156110ec57600160c08203019150611109565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008160020a60ff16837f0100000000000000000000000000000000000000000000000000000000000000900460ff1681151561114b57fe5b047f010000000000000000000000000000000000000000000000000000000000000002905092915050565b6000806000611184846111cd565b151561118f57600080fd5b611198846111fe565b809250819350505060208111806111af5750600081145b156111b957600080fd5b806020036101000a82510492505050919050565b6000806000836020015114156111e657600091506111f8565b8260000151905060c0815160001a1091505b50919050565b600080600080600061120f866111cd565b151561121a57600080fd5b85600001519150815160001a9250608083101561123d5781945060019350611277565b60b883101561125b5760018660200151039350600182019450611276565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b604080519081016040528060008152602001600081525090565b6060604051908101604052806112ad6112ba565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a72305820804e182cb5646c79807339af20606a7f19266d97aae0e147854870495919200f0029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi index 056ae8a..283c820 100644 --- a/abi/Validation.abi +++ b/abi/Validation.abi @@ -1 +1 @@ -[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"InitChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getReceiptRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getTxRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin index bb18e92..3ea00e2 100644 --- a/abi/Validation.bin +++ b/abi/Validation.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b506040516020806114d883398101806040528101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600181600019169055505061144a8061008e6000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806309fbd5361461009e5780630b5abdd01461015b5780634b355030146101dd57806353fe62e61461023457806359a533311461029d5780638da5cb5b146102e2578063927a32e3146103395780639a8a05921461039c578063c18de0ef146103cf575b600080fd5b3480156100aa57600080fd5b506101596004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610418565b005b34801561016757600080fd5b506101db60048036038101908080356000191690602001909291908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080356000191690602001909291905050506108b9565b005b3480156101e957600080fd5b5061021a60048036038101908080356000191690602001909291908035600019169060200190929190505050610b29565b604051808215151515815260200191505060405180910390f35b34801561024057600080fd5b506102836004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b58565b604051808215151515815260200191505060405180910390f35b3480156102a957600080fd5b506102cc6004803603810190808035600019169060200190929190505050610b87565b6040518082815260200191505060405180910390f35b3480156102ee57600080fd5b506102f7610b9f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561034557600080fd5b506103686004803603810190808035600019169060200190929190505050610bc4565b6040518084815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b3480156103a857600080fd5b506103b1610bee565b60405180826000191660001916815260200191505060405180910390f35b3480156103db57600080fd5b506103fe6004803603810190808035600019169060200190929190505050610bf4565b604051808215151515815260200191505060405180910390f35b60608060008060008760036000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156104be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b6104cf6104ca89610c14565b610c6f565b95506104e26104dd88610c14565b610c6f565b9450600093505b845184101561068f57600c84141561050057610682565b610520858581518110151561051157fe5b90602001906020020151610d2c565b6040518082805190602001908083835b6020831015156105555780518252602082019150602081019050602083039250610530565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166105a6878681518110151561059757fe5b90602001906020020151610d2c565b6040518082805190602001908083835b6020831015156105db57805182526020820191506020810190506020830392506105b6565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141515610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486561646572206461746120646f65736e2774206d617463682100000000000081525060200191505060405180910390fd5b5b83806001019450506104e9565b6106ba6106b38760008151811015156106a457fe5b90602001906020020151610d2c565b6001610d91565b92508260001916600560008b600019166000191681526020019081526020016000206001015460001916141515610759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b866040518082805190602001908083835b60208310151561078f578051825260208201915060208101905060208303925061076a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018260405180826000191660001916815260200191505060405180910390a16108288961082287600c81518110151561081357fe5b90602001906020020151610d2c565b8a610da5565b600560008a600019166000191681526020019081526020016000206000016000815480929190600101919050555081600560008b60001916600019168152602001908152602001600020600101816000191690555082600560008b6000191660001916815260200190815260200160002060020181600019169055506108ae8983610fad565b505050505050505050565b600060015460001916846000191614151515610963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60036000856000191660001916815260200190815260200160002060009054906101000a900460ff16151515610a01576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160036000866000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600090505b8251811015610ad857600160066000866000191660001916815260200190815260200160002060008584815181101515610a7057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610a3a565b60006005600086600019166000191681526020019081526020016000206000018190555081600560008660001916600019168152602001908152602001600020600101816000191690555050505050565b60046020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60026020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60056020528060005260406000206000915090508060000154908060010154908060020154905083565b60015481565b60036020528060005260406000206000915054906101000a900460ff1681565b610c1c6113c9565b600080835191506000821415610c4a5760408051908101604052806000815260200160008152509250610c68565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610c7b6113e3565b6000610c8685610ffe565b1515610c9157600080fd5b610c9a85611030565b925082604051908082528060200260200182016040528015610cd657816020015b610cc3611404565b815260200190600190039081610cbb5790505b509350610ce2856110aa565b91505b610cee826110f2565b15610d2457610cfc8261111c565b8482815181101515610d0a57fe5b906020019060200201819052508080600101915050610ce5565b505050919050565b60606000826020015190506000811415610d4557610d8b565b806040519080825280601f01601f191660200182016040528015610d785781602001602082028038833980820191505090505b509150610d8a83600001518383611178565b5b50919050565b600060208201915081830151905092915050565b606060008060416040519080825280601f01601f191660200182016040528015610dde5781602001602082028038833980820191505090505b50925084519150610df38386604185036111b9565b610e5f846040518082805190602001908083835b602083101515610e2c5780518252602082019150602081019050602083039250610e07565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020846111db565b90506001151560066000886000191660001916815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515610f42576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef4381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b60016004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600080600083602001511415611017576000915061102a565b8260000151905060c0815160001a101591505b50919050565b60008060008060008061104287610ffe565b151561105157600095506110a0565b86600001519350835160001a945061106887611253565b840192506001876020015185010391505b818311151561109c5761108b836112df565b830192508080600101915050611079565b8095505b5050505050919050565b6110b26113e3565b60006110bd83610ffe565b15156110c857600080fd5b6110d183611253565b83600001510190508282600001819052508082602001818152505050919050565b60006110fc6113c9565b826000015190508060200151816000015101836020015110915050919050565b6111246113c9565b600080611130846110f2565b1561116c5783602001519150611145826112df565b90508183600001818152505080836020018181525050808201846020018181525050611171565b600080fd5b5050919050565b60006020601f83010484602085015b8284146111a65760208402808301518183015260018501945050611187565b6000865160200187015250505050505050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b600080600080604185511415156111f157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561121c57601b810190505b601b8160ff1614806112315750601c8160ff16145b151561123c57600080fd5b61124886828585611379565b935050505092915050565b6000806000808460200151141561126d57600092506112d8565b83600001519050805160001a9150608082101561128d57600092506112d8565b60b88210806112a9575060c082101580156112a8575060f882105b5b156112b757600192506112d8565b60c08210156112ce57600160b783030192506112d8565b600160f783030192505b5050919050565b600080825160001a905060808110156112fb5760019150611373565b60b881101561131257600160808203019150611372565b60c081101561133c5760b78103806020036101000a60018501510480820160010193505050611371565b60f881101561135357600160c08203019150611370565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa92508051915050600115158215151415156113bc57600080fd5b8092505050949350505050565b604080519081016040528060008152602001600081525090565b6060604051908101604052806113f7611404565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820897cc24853981b569e808746bf0fedcd4e017d77e97cdb224a413d00378c0be20029 \ No newline at end of file +608060405234801561001057600080fd5b5060405160208061189383398101806040528101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060018160001916905550506118058061008e6000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806307bff1b1146100a957806313d3babb1461010457806347bfc0a81461015f5780634b355030146101e1578063528243741461023857806353fe62e6146102f55780638da5cb5b1461035e5780639a8a0592146103b5578063c18de0ef146103e8578063e79b136c14610431575b600080fd5b3480156100b557600080fd5b506100e6600480360381019080803560001916906020019092919080356000191690602001909291905050506104c0565b60405180826000191660001916815260200191505060405180910390f35b34801561011057600080fd5b5061014160048036038101908080356000191690602001909291908035600019169060200190929190505050610502565b60405180826000191660001916815260200191505060405180910390f35b34801561016b57600080fd5b506101df6004803603810190808035600019169060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035600019169060200190929190505050610544565b005b3480156101ed57600080fd5b5061021e600480360381019080803560001916906020019092919080356000191690602001909291905050506107f3565b604051808215151515815260200191505060405180910390f35b34801561024457600080fd5b506102f36004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610822565b005b34801561030157600080fd5b506103446004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e10565b604051808215151515815260200191505060405180910390f35b34801561036a57600080fd5b50610373610e3f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103c157600080fd5b506103ca610e64565b60405180826000191660001916815260200191505060405180910390f35b3480156103f457600080fd5b506104176004803603810190808035600019169060200190929190505050610e6a565b604051808215151515815260200191505060405180910390f35b34801561043d57600080fd5b5061046e60048036038101908080356000191690602001909291908035600019169060200190929190505050610e8a565b6040518086815260200185600019166000191681526020018460001916600019168152602001836000191660001916815260200182600019166000191681526020019550505050505060405180910390f35b60006004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060040154905092915050565b60006004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060030154905092915050565b6000600154600019168460001916141515156105ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60026000856000191660001916815260200190815260200160002060009054906101000a900460ff1615151561068c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160026000866000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600090505b8251811015610763576001600560008660001916600019168152602001908152602001600020600085848151811015156106fb57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080806001019150506106c5565b6000600460008660001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555060016003600086600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555050505050565b60036020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008760026000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156108c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b6108d96108d489610ecd565b610f28565b95506108ec6108e788610ecd565b610f28565b9450600093505b8451841015610a9957600c84141561090a57610a8c565b61092a858581518110151561091b57fe5b90602001906020020151610fe5565b6040518082805190602001908083835b60208310151561095f578051825260208201915060208101905060208303925061093a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166109b087868151811015156109a157fe5b90602001906020020151610fe5565b6040518082805190602001908083835b6020831015156109e557805182526020820191506020810190506020830392506109c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141515610a8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486561646572206461746120646f65736e2774206d617463682100000000000081525060200191505060405180910390fd5b5b83806001019450506108f3565b610ac4610abd876000815181101515610aae57fe5b90602001906020020151610fe5565b600161104a565b9250600360008a600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060009054906101000a900460ff161515610b7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b866040518082805190602001908083835b602083101515610bb25780518252602082019150602081019050602083039250610b8d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018260405180826000191660001916815260200191505060405180910390a1610c4b89610c4587600c815181101515610c3657fe5b90602001906020020151610fe5565b8a61105e565b610c6c866008815181101515610c5d57fe5b9060200190602002015161125f565b600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555081600460008b6000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600101816000191690555082600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206002018160001916905550610d52610d4b876004815181101515610d3c57fe5b90602001906020020151610fe5565b600161104a565b600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206003018160001916905550610dbc610db5876005815181101515610da657fe5b90602001906020020151610fe5565b600161104a565b600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206004018160001916905550610e0589836112b6565b505050505050505050565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b60026020528060005260406000206000915054906101000a900460ff1681565b6004602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154908060040154905085565b610ed5611784565b600080835191506000821415610f035760408051908101604052806000815260200160008152509250610f21565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610f3461179e565b6000610f3f85611307565b1515610f4a57600080fd5b610f5385611339565b925082604051908082528060200260200182016040528015610f8f57816020015b610f7c6117bf565b815260200190600190039081610f745790505b509350610f9b856113b3565b91505b610fa7826113fb565b15610fdd57610fb582611425565b8482815181101515610fc357fe5b906020019060200201819052508080600101915050610f9e565b505050919050565b60606000826020015190506000811415610ffe57611044565b806040519080825280601f01601f1916602001820160405280156110315781602001602082028038833980820191505090505b50915061104383600001518383611481565b5b50919050565b600060208201915081830151905092915050565b606060008060416040519080825280601f01601f1916602001820160405280156110975781602001602082028038833980820191505090505b509250845191506110ac8386604185036114c2565b611118846040518082805190602001908083835b6020831015156110e557805182526020820191506020810190506020830392506110c0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020846114e4565b905060056000876000191660001916815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156111f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef4381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b600080600061126d8461155c565b151561127857600080fd5b6112818461158d565b809250819350505060208111806112985750600081145b156112a257600080fd5b806020036101000a82510492505050919050565b60016003600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000806000836020015114156113205760009150611333565b8260000151905060c0815160001a101591505b50919050565b60008060008060008061134b87611307565b151561135a57600095506113a9565b86600001519350835160001a94506113718761160e565b840192506001876020015185010391505b81831115156113a5576113948361169a565b830192508080600101915050611382565b8095505b5050505050919050565b6113bb61179e565b60006113c683611307565b15156113d157600080fd5b6113da8361160e565b83600001510190508282600001819052508082602001818152505050919050565b6000611405611784565b826000015190508060200151816000015101836020015110915050919050565b61142d611784565b600080611439846113fb565b15611475578360200151915061144e8261169a565b9050818360000181815250508083602001818152505080820184602001818152505061147a565b600080fd5b5050919050565b60006020601f83010484602085015b8284146114af5760208402808301518183015260018501945050611490565b6000865160200187015250505050505050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b600080600080604185511415156114fa57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561152557601b810190505b601b8160ff16148061153a5750601c8160ff16145b151561154557600080fd5b61155186828585611734565b935050505092915050565b6000806000836020015114156115755760009150611587565b8260000151905060c0815160001a1091505b50919050565b600080600080600061159e8661155c565b15156115a957600080fd5b85600001519150815160001a925060808310156115cc5781945060019350611606565b60b88310156115ea5760018660200151039350600182019450611605565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b600080600080846020015114156116285760009250611693565b83600001519050805160001a915060808210156116485760009250611693565b60b8821080611664575060c08210158015611663575060f882105b5b156116725760019250611693565b60c082101561168957600160b78303019250611693565b600160f783030192505b5050919050565b600080825160001a905060808110156116b6576001915061172e565b60b88110156116cd5760016080820301915061172d565b60c08110156116f75760b78103806020036101000a6001850151048082016001019350505061172c565b60f881101561170e57600160c0820301915061172b565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561177757600080fd5b8092505050949350505050565b604080519081016040528060008152602001600081525090565b6060604051908101604052806117b26117bf565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582080fcb68fb04bfab7a40966801cfb76a69a1bce4a52c2e6e779069869e7733eb40029 \ No newline at end of file diff --git a/ion-cli/Makefile b/ion-cli/Makefile index da06ea5..4a7fa08 100644 --- a/ion-cli/Makefile +++ b/ion-cli/Makefile @@ -5,7 +5,9 @@ SHELL=/bin/bash clean: @rm -f ion-cli - @rm *.out + @rm contracts/validation.go + @rm contracts/ion.go + @rm contracts/patricia.go test: @go test ./... -v -short @@ -24,6 +26,12 @@ coverage: go tool cover -html=coverage-all.out build: + # Auto generate the smart contracts + @abigen --bin=../abi/Validation.bin --abi=../abi/Validation.abi --pkg=contract --type=validation --out=contracts/validation.go + @abigen --bin=../abi/Ion.bin --abi=../abi/Ion.abi --pkg=contract --type=ion --out=contracts/ion.go + @abigen --bin=../abi/PatriciaTrie.bin --abi=../abi/PatriciaTrie.abi --pkg=contract --type=patricia --out=contracts/patricia.go + + # Now build project @go get -t -v ./... @go build -o ion-cli . diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 0be2d90..9c5fd1e 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -121,7 +121,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Ion *contract.Ion) c.Print("New ChainId: ") chainId := c.ReadLine() - c.Printf("Running Command:\t%s\t%s", chainId + c.Printf("Running Command:\t%s\t%s", chainId) c.Println("===============================================================") }, }) diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go deleted file mode 100644 index df0ff96..0000000 --- a/ion-cli/contracts/ion.go +++ /dev/null @@ -1,902 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contract - -import ( - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// IonABI is the input ABI used to generate the binding from. -const IonABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"registeredChains\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"validation_addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockhashes\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_rlpBlockHeader\",\"type\":\"bytes\"},{\"name\":\"_rlpSignedBlockHeader\",\"type\":\"bytes\"}],\"name\":\"SubmitBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"m_validators\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"validationAddr\",\"type\":\"address\"},{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"_genesisHash\",\"type\":\"bytes32\"}],\"name\":\"RegisterChain\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"}],\"name\":\"CheckTxProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"}],\"name\":\"CheckReceiptProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"chains\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"blockHeight\",\"type\":\"uint256\"},{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"txRootHash\",\"type\":\"bytes32\"},{\"name\":\"receiptRootHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockHash\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockHeight\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_txNodes\",\"type\":\"bytes\"},{\"name\":\"_receiptNodes\",\"type\":\"bytes\"}],\"name\":\"CheckRootsProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"chainId\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"proofType\",\"type\":\"uint256\"}],\"name\":\"VerifiedProof\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"broadcastSignature\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"}]" - -// IonBin is the compiled bytecode used for deploying new contracts. -const IonBin = `608060405234801561001057600080fd5b5060405160208061221f833981018060405281019080805190602001909291905050508060018160001916905550506121d18061004e6000396000f3006080604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100d5578063261e50731461011e5780634b3550301461018f57806352824374146101e657806353fe62e6146102a35780637558a01a1461030c5780639a8a0592146103ae578063affd8be9146103e1578063bec205b91461050a578063c18de0ef14610633578063e79b136c1461067c578063f22a195e146106fc578063f44ff7121461072f578063f484c1f71461075a575b600080fd5b3480156100e157600080fd5b506101006004803603810190808035906020019092919050505061083d565b60405180826000191660001916815260200191505060405180910390f35b34801561012a57600080fd5b5061014d6004803603810190808035600019169060200190929190505050610860565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561019b57600080fd5b506101cc60048036038101908080356000191690602001909291908035600019169060200190929190505050610893565b604051808215151515815260200191505060405180910390f35b3480156101f257600080fd5b506102a16004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506108c2565b005b3480156102af57600080fd5b506102f26004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d71565b604051808215151515815260200191505060405180910390f35b34801561031857600080fd5b506103ac6004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035600019169060200190929190505050610da0565b005b3480156103ba57600080fd5b506103c3611124565b60405180826000191660001916815260200191505060405180910390f35b3480156103ed57600080fd5b506104f060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061112a565b604051808215151515815260200191505060405180910390f35b34801561051657600080fd5b5061061960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061152e565b604051808215151515815260200191505060405180910390f35b34801561063f57600080fd5b506106626004803603810190808035600019169060200190929190505050611932565b604051808215151515815260200191505060405180910390f35b34801561068857600080fd5b506106b960048036038101908080356000191690602001909291908035600019169060200190929190505050611952565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b34801561070857600080fd5b5061071161198f565b60405180826000191660001916815260200191505060405180910390f35b34801561073b57600080fd5b50610744611995565b6040518082815260200191505060405180910390f35b34801561076657600080fd5b5061082360048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199b565b604051808215151515815260200191505060405180910390f35b60028181548110151561084c57fe5b906000526020600020016000915090505481565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008060008960046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561096b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61097c6109778b611bda565b611c35565b975061098f61098a8a611bda565b611c35565b9650600560008c6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508594508473ffffffffffffffffffffffffffffffffffffffff166309fbd5368c8c8c6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610a6e578082015181840152602081019050610a53565b50505050905090810190601f168015610a9b5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610ad4578082015181840152602081019050610ab9565b50505050905090810190601f168015610b015780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015610b2357600080fd5b505af1158015610b37573d6000803e3d6000fd5b50505050610b66610b5f896000815181101515610b5057fe5b90602001906020020151611cf2565b6001611d57565b9350886040518082805190602001908083835b602083101515610b9e5780518252602082019150602081019050602083039250610b79565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092506001600760008d60001916600019168152602001908152602001600020600086600019166000191681526020019081526020016000206000015401915081600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206000018190555083600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206001018160001916905550610cb1610caa896004815181101515610c9b57fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206002018160001916905550610d1b610d14896005815181101515610d0557fe5b90602001906020020151611cf2565b6001611d57565b600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206003018160001916905550610d648b84611d6b565b5050505050505050505050565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600060015460001916856000191614151515610e4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000866000191660001916815260200190815260200160002060009054906101000a900460ff16151515610ee8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000876000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600285908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555060016006600087600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600060076000876000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600001819055508390508073ffffffffffffffffffffffffffffffffffffffff16630b5abdd08685856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808460001916600019168152602001806020018360001916600019168152602001828103825284818151815260200191508051906020019060200280838360005b83811015611084578082015181840152602081019050611069565b50505050905001945050505050600060405180830381600087803b1580156110ab57600080fd5b505af11580156110bf573d6000803e3d6000fd5b505050508360056000876000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b60015481565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156111cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600201546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b8381101561135c578082015181840152602081019050611341565b50505050905090810190601f1680156113895780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156113c25780820151818401526020810190506113a7565b50505050905090810190601f1680156113ef5780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561142857808201518184015260208101905061140d565b50505050905090810190601f1680156114555780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561147757600080fd5b505af415801561148b573d6000803e3d6000fd5b505050506040513d60208110156114a157600080fd5b810190808051906020019092919050505015156114ba57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600060028111156114ea57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b6000808660046000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156115cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b87876006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611687576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008b6000191660001916815260200190815260200160002060008a60001916600019168152602001908152602001600020935073__./contracts/libraries/PatriciaTrie.s__634f7142ad89898988600301546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611760578082015181840152602081019050611745565b50505050905090810190601f16801561178d5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156117c65780820151818401526020810190506117ab565b50505050905090810190601f1680156117f35780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b8381101561182c578082015181840152602081019050611811565b50505050905090810190601f1680156118595780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561187b57600080fd5b505af415801561188f573d6000803e3d6000fd5b505050506040513d60208110156118a557600080fd5b810190808051906020019092919050505015156118be57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a600160028111156118ee57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a1600194505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000808560046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611a3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b86866006600083600019166000191681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611af4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600760008a60001916600019168152602001908152602001600020600089600019166000191681526020019081526020016000209350611b3387611dbc565b60001916846002015460001916141515611b4957fe5b611b5286611dbc565b60001916846003015460001916141515611b6857fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468989600280811115611b9757fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001945050505050949350505050565b611be2612150565b600080835191506000821415611c105760408051908101604052806000815260200160008152509250611c2e565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611c4161216a565b6000611c4c85611e6f565b1515611c5757600080fd5b611c6085611ea1565b925082604051908082528060200260200182016040528015611c9c57816020015b611c8961218b565b815260200190600190039081611c815790505b509350611ca885611f1b565b91505b611cb482611f63565b15611cea57611cc282611f8d565b8482815181101515611cd057fe5b906020019060200201819052508080600101915050611cab565b505050919050565b60606000826020015190506000811415611d0b57611d51565b806040519080825280601f01601f191660200182016040528015611d3e5781602001602082028038833980820191505090505b509150611d5083600001518383611fe9565b5b50919050565b600060208201915081830151905092915050565b60016006600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000611dc6612150565b606080611dd285611bda565b9250611ddd83611c35565b9150611e00826000815181101515611df157fe5b90602001906020020151611cf2565b9050806040518082805190602001908083835b602083101515611e385780518252602082019150602081019050602083039250611e13565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b600080600083602001511415611e885760009150611e9b565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611eb387611e6f565b1515611ec25760009550611f11565b86600001519350835160001a9450611ed98761202a565b840192506001876020015185010391505b8183111515611f0d57611efc836120b6565b830192508080600101915050611eea565b8095505b5050505050919050565b611f2361216a565b6000611f2e83611e6f565b1515611f3957600080fd5b611f428361202a565b83600001510190508282600001819052508082602001818152505050919050565b6000611f6d612150565b826000015190508060200151816000015101836020015110915050919050565b611f95612150565b600080611fa184611f63565b15611fdd5783602001519150611fb6826120b6565b90508183600001818152505080836020018181525050808201846020018181525050611fe2565b600080fd5b5050919050565b60006020601f83010484602085015b8284146120175760208402808301518183015260018501945050611ff8565b6000865160200187015250505050505050565b6000806000808460200151141561204457600092506120af565b83600001519050805160001a9150608082101561206457600092506120af565b60b8821080612080575060c0821015801561207f575060f882105b5b1561208e57600192506120af565b60c08210156120a557600160b783030192506120af565b600160f783030192505b5050919050565b600080825160001a905060808110156120d2576001915061214a565b60b88110156120e957600160808203019150612149565b60c08110156121135760b78103806020036101000a60018501510480820160010193505050612148565b60f881101561212a57600160c08203019150612147565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b60606040519081016040528061217e61218b565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582063bd23fd4aba60ad5fe5003097cfeb975ac723f7e78172be2b48321603b5cabd0029` - -// DeployIon deploys a new Ethereum contract, binding an instance of Ion to it. -func DeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte) (common.Address, *types.Transaction, *Ion, error) { - parsed, err := abi.JSON(strings.NewReader(IonABI)) - if err != nil { - return common.Address{}, nil, nil, err - } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(IonBin), backend, _id) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil -} - -// Ion is an auto generated Go binding around an Ethereum contract. -type Ion struct { - IonCaller // Read-only binding to the contract - IonTransactor // Write-only binding to the contract - IonFilterer // Log filterer for contract events -} - -// IonCaller is an auto generated read-only Go binding around an Ethereum contract. -type IonCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IonTransactor is an auto generated write-only Go binding around an Ethereum contract. -type IonTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IonFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type IonFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IonSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type IonSession struct { - Contract *Ion // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IonCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type IonCallerSession struct { - Contract *IonCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// IonTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type IonTransactorSession struct { - Contract *IonTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IonRaw is an auto generated low-level Go binding around an Ethereum contract. -type IonRaw struct { - Contract *Ion // Generic contract binding to access the raw methods on -} - -// IonCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type IonCallerRaw struct { - Contract *IonCaller // Generic read-only contract binding to access the raw methods on -} - -// IonTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type IonTransactorRaw struct { - Contract *IonTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewIon creates a new instance of Ion, bound to a specific deployed contract. -func NewIon(address common.Address, backend bind.ContractBackend) (*Ion, error) { - contract, err := bindIon(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil -} - -// NewIonCaller creates a new read-only instance of Ion, bound to a specific deployed contract. -func NewIonCaller(address common.Address, caller bind.ContractCaller) (*IonCaller, error) { - contract, err := bindIon(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &IonCaller{contract: contract}, nil -} - -// NewIonTransactor creates a new write-only instance of Ion, bound to a specific deployed contract. -func NewIonTransactor(address common.Address, transactor bind.ContractTransactor) (*IonTransactor, error) { - contract, err := bindIon(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &IonTransactor{contract: contract}, nil -} - -// NewIonFilterer creates a new log filterer instance of Ion, bound to a specific deployed contract. -func NewIonFilterer(address common.Address, filterer bind.ContractFilterer) (*IonFilterer, error) { - contract, err := bindIon(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &IonFilterer{contract: contract}, nil -} - -// bindIon binds a generic wrapper to an already deployed contract. -func bindIon(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(IonABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Ion *IonRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Ion.Contract.IonCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Ion *IonRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Ion.Contract.IonTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Ion *IonRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Ion.Contract.IonTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Ion *IonCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Ion.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Ion *IonTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Ion.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Ion *IonTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Ion.Contract.contract.Transact(opts, method, params...) -} - -// BlockHash is a free data retrieval call binding the contract method 0xf22a195e. -// -// Solidity: function blockHash() constant returns(bytes32) -func (_Ion *IonCaller) BlockHash(opts *bind.CallOpts) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "blockHash") - return *ret0, err -} - -// BlockHash is a free data retrieval call binding the contract method 0xf22a195e. -// -// Solidity: function blockHash() constant returns(bytes32) -func (_Ion *IonSession) BlockHash() ([32]byte, error) { - return _Ion.Contract.BlockHash(&_Ion.CallOpts) -} - -// BlockHash is a free data retrieval call binding the contract method 0xf22a195e. -// -// Solidity: function blockHash() constant returns(bytes32) -func (_Ion *IonCallerSession) BlockHash() ([32]byte, error) { - return _Ion.Contract.BlockHash(&_Ion.CallOpts) -} - -// BlockHeight is a free data retrieval call binding the contract method 0xf44ff712. -// -// Solidity: function blockHeight() constant returns(uint256) -func (_Ion *IonCaller) BlockHeight(opts *bind.CallOpts) (*big.Int, error) { - var ( - ret0 = new(*big.Int) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "blockHeight") - return *ret0, err -} - -// BlockHeight is a free data retrieval call binding the contract method 0xf44ff712. -// -// Solidity: function blockHeight() constant returns(uint256) -func (_Ion *IonSession) BlockHeight() (*big.Int, error) { - return _Ion.Contract.BlockHeight(&_Ion.CallOpts) -} - -// BlockHeight is a free data retrieval call binding the contract method 0xf44ff712. -// -// Solidity: function blockHeight() constant returns(uint256) -func (_Ion *IonCallerSession) BlockHeight() (*big.Int, error) { - return _Ion.Contract.BlockHeight(&_Ion.CallOpts) -} - -// ChainId is a free data retrieval call binding the contract method 0x9a8a0592. -// -// Solidity: function chainId() constant returns(bytes32) -func (_Ion *IonCaller) ChainId(opts *bind.CallOpts) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "chainId") - return *ret0, err -} - -// ChainId is a free data retrieval call binding the contract method 0x9a8a0592. -// -// Solidity: function chainId() constant returns(bytes32) -func (_Ion *IonSession) ChainId() ([32]byte, error) { - return _Ion.Contract.ChainId(&_Ion.CallOpts) -} - -// ChainId is a free data retrieval call binding the contract method 0x9a8a0592. -// -// Solidity: function chainId() constant returns(bytes32) -func (_Ion *IonCallerSession) ChainId() ([32]byte, error) { - return _Ion.Contract.ChainId(&_Ion.CallOpts) -} - -// Chains is a free data retrieval call binding the contract method 0xc18de0ef. -// -// Solidity: function chains( bytes32) constant returns(bool) -func (_Ion *IonCaller) Chains(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "chains", arg0) - return *ret0, err -} - -// Chains is a free data retrieval call binding the contract method 0xc18de0ef. -// -// Solidity: function chains( bytes32) constant returns(bool) -func (_Ion *IonSession) Chains(arg0 [32]byte) (bool, error) { - return _Ion.Contract.Chains(&_Ion.CallOpts, arg0) -} - -// Chains is a free data retrieval call binding the contract method 0xc18de0ef. -// -// Solidity: function chains( bytes32) constant returns(bool) -func (_Ion *IonCallerSession) Chains(arg0 [32]byte) (bool, error) { - return _Ion.Contract.Chains(&_Ion.CallOpts, arg0) -} - -// MBlockhashes is a free data retrieval call binding the contract method 0x4b355030. -// -// Solidity: function m_blockhashes( bytes32, bytes32) constant returns(bool) -func (_Ion *IonCaller) MBlockhashes(opts *bind.CallOpts, arg0 [32]byte, arg1 [32]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "m_blockhashes", arg0, arg1) - return *ret0, err -} - -// MBlockhashes is a free data retrieval call binding the contract method 0x4b355030. -// -// Solidity: function m_blockhashes( bytes32, bytes32) constant returns(bool) -func (_Ion *IonSession) MBlockhashes(arg0 [32]byte, arg1 [32]byte) (bool, error) { - return _Ion.Contract.MBlockhashes(&_Ion.CallOpts, arg0, arg1) -} - -// MBlockhashes is a free data retrieval call binding the contract method 0x4b355030. -// -// Solidity: function m_blockhashes( bytes32, bytes32) constant returns(bool) -func (_Ion *IonCallerSession) MBlockhashes(arg0 [32]byte, arg1 [32]byte) (bool, error) { - return _Ion.Contract.MBlockhashes(&_Ion.CallOpts, arg0, arg1) -} - -// MBlockheaders is a free data retrieval call binding the contract method 0xe79b136c. -// -// Solidity: function m_blockheaders( bytes32, bytes32) constant returns(blockHeight uint256, prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) -func (_Ion *IonCaller) MBlockheaders(opts *bind.CallOpts, arg0 [32]byte, arg1 [32]byte) (struct { - BlockHeight *big.Int - PrevBlockHash [32]byte - TxRootHash [32]byte - ReceiptRootHash [32]byte -}, error) { - ret := new(struct { - BlockHeight *big.Int - PrevBlockHash [32]byte - TxRootHash [32]byte - ReceiptRootHash [32]byte - }) - out := ret - err := _Ion.contract.Call(opts, out, "m_blockheaders", arg0, arg1) - return *ret, err -} - -// MBlockheaders is a free data retrieval call binding the contract method 0xe79b136c. -// -// Solidity: function m_blockheaders( bytes32, bytes32) constant returns(blockHeight uint256, prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) -func (_Ion *IonSession) MBlockheaders(arg0 [32]byte, arg1 [32]byte) (struct { - BlockHeight *big.Int - PrevBlockHash [32]byte - TxRootHash [32]byte - ReceiptRootHash [32]byte -}, error) { - return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0, arg1) -} - -// MBlockheaders is a free data retrieval call binding the contract method 0xe79b136c. -// -// Solidity: function m_blockheaders( bytes32, bytes32) constant returns(blockHeight uint256, prevBlockHash bytes32, txRootHash bytes32, receiptRootHash bytes32) -func (_Ion *IonCallerSession) MBlockheaders(arg0 [32]byte, arg1 [32]byte) (struct { - BlockHeight *big.Int - PrevBlockHash [32]byte - TxRootHash [32]byte - ReceiptRootHash [32]byte -}, error) { - return _Ion.Contract.MBlockheaders(&_Ion.CallOpts, arg0, arg1) -} - -// MValidators is a free data retrieval call binding the contract method 0x53fe62e6. -// -// Solidity: function m_validators( bytes32, address) constant returns(bool) -func (_Ion *IonCaller) MValidators(opts *bind.CallOpts, arg0 [32]byte, arg1 common.Address) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "m_validators", arg0, arg1) - return *ret0, err -} - -// MValidators is a free data retrieval call binding the contract method 0x53fe62e6. -// -// Solidity: function m_validators( bytes32, address) constant returns(bool) -func (_Ion *IonSession) MValidators(arg0 [32]byte, arg1 common.Address) (bool, error) { - return _Ion.Contract.MValidators(&_Ion.CallOpts, arg0, arg1) -} - -// MValidators is a free data retrieval call binding the contract method 0x53fe62e6. -// -// Solidity: function m_validators( bytes32, address) constant returns(bool) -func (_Ion *IonCallerSession) MValidators(arg0 [32]byte, arg1 common.Address) (bool, error) { - return _Ion.Contract.MValidators(&_Ion.CallOpts, arg0, arg1) -} - -// RegisteredChains is a free data retrieval call binding the contract method 0x200ab0d3. -// -// Solidity: function registeredChains( uint256) constant returns(bytes32) -func (_Ion *IonCaller) RegisteredChains(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "registeredChains", arg0) - return *ret0, err -} - -// RegisteredChains is a free data retrieval call binding the contract method 0x200ab0d3. -// -// Solidity: function registeredChains( uint256) constant returns(bytes32) -func (_Ion *IonSession) RegisteredChains(arg0 *big.Int) ([32]byte, error) { - return _Ion.Contract.RegisteredChains(&_Ion.CallOpts, arg0) -} - -// RegisteredChains is a free data retrieval call binding the contract method 0x200ab0d3. -// -// Solidity: function registeredChains( uint256) constant returns(bytes32) -func (_Ion *IonCallerSession) RegisteredChains(arg0 *big.Int) ([32]byte, error) { - return _Ion.Contract.RegisteredChains(&_Ion.CallOpts, arg0) -} - -// ValidationAddr is a free data retrieval call binding the contract method 0x261e5073. -// -// Solidity: function validation_addr( bytes32) constant returns(address) -func (_Ion *IonCaller) ValidationAddr(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { - var ( - ret0 = new(common.Address) - ) - out := ret0 - err := _Ion.contract.Call(opts, out, "validation_addr", arg0) - return *ret0, err -} - -// ValidationAddr is a free data retrieval call binding the contract method 0x261e5073. -// -// Solidity: function validation_addr( bytes32) constant returns(address) -func (_Ion *IonSession) ValidationAddr(arg0 [32]byte) (common.Address, error) { - return _Ion.Contract.ValidationAddr(&_Ion.CallOpts, arg0) -} - -// ValidationAddr is a free data retrieval call binding the contract method 0x261e5073. -// -// Solidity: function validation_addr( bytes32) constant returns(address) -func (_Ion *IonCallerSession) ValidationAddr(arg0 [32]byte) (common.Address, error) { - return _Ion.Contract.ValidationAddr(&_Ion.CallOpts, arg0) -} - -// CheckReceiptProof is a paid mutator transaction binding the contract method 0xbec205b9. -// -// Solidity: function CheckReceiptProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) -func (_Ion *IonTransactor) CheckReceiptProof(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { - return _Ion.contract.Transact(opts, "CheckReceiptProof", _id, _blockHash, _value, _parentNodes, _path) -} - -// CheckReceiptProof is a paid mutator transaction binding the contract method 0xbec205b9. -// -// Solidity: function CheckReceiptProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) -func (_Ion *IonSession) CheckReceiptProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { - return _Ion.Contract.CheckReceiptProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) -} - -// CheckReceiptProof is a paid mutator transaction binding the contract method 0xbec205b9. -// -// Solidity: function CheckReceiptProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) -func (_Ion *IonTransactorSession) CheckReceiptProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { - return _Ion.Contract.CheckReceiptProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) -} - -// CheckRootsProof is a paid mutator transaction binding the contract method 0xf484c1f7. -// -// Solidity: function CheckRootsProof(_id bytes32, _blockHash bytes32, _txNodes bytes, _receiptNodes bytes) returns(bool) -func (_Ion *IonTransactor) CheckRootsProof(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _txNodes []byte, _receiptNodes []byte) (*types.Transaction, error) { - return _Ion.contract.Transact(opts, "CheckRootsProof", _id, _blockHash, _txNodes, _receiptNodes) -} - -// CheckRootsProof is a paid mutator transaction binding the contract method 0xf484c1f7. -// -// Solidity: function CheckRootsProof(_id bytes32, _blockHash bytes32, _txNodes bytes, _receiptNodes bytes) returns(bool) -func (_Ion *IonSession) CheckRootsProof(_id [32]byte, _blockHash [32]byte, _txNodes []byte, _receiptNodes []byte) (*types.Transaction, error) { - return _Ion.Contract.CheckRootsProof(&_Ion.TransactOpts, _id, _blockHash, _txNodes, _receiptNodes) -} - -// CheckRootsProof is a paid mutator transaction binding the contract method 0xf484c1f7. -// -// Solidity: function CheckRootsProof(_id bytes32, _blockHash bytes32, _txNodes bytes, _receiptNodes bytes) returns(bool) -func (_Ion *IonTransactorSession) CheckRootsProof(_id [32]byte, _blockHash [32]byte, _txNodes []byte, _receiptNodes []byte) (*types.Transaction, error) { - return _Ion.Contract.CheckRootsProof(&_Ion.TransactOpts, _id, _blockHash, _txNodes, _receiptNodes) -} - -// CheckTxProof is a paid mutator transaction binding the contract method 0xaffd8be9. -// -// Solidity: function CheckTxProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) -func (_Ion *IonTransactor) CheckTxProof(opts *bind.TransactOpts, _id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { - return _Ion.contract.Transact(opts, "CheckTxProof", _id, _blockHash, _value, _parentNodes, _path) -} - -// CheckTxProof is a paid mutator transaction binding the contract method 0xaffd8be9. -// -// Solidity: function CheckTxProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) -func (_Ion *IonSession) CheckTxProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { - return _Ion.Contract.CheckTxProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) -} - -// CheckTxProof is a paid mutator transaction binding the contract method 0xaffd8be9. -// -// Solidity: function CheckTxProof(_id bytes32, _blockHash bytes32, _value bytes, _parentNodes bytes, _path bytes) returns(bool) -func (_Ion *IonTransactorSession) CheckTxProof(_id [32]byte, _blockHash [32]byte, _value []byte, _parentNodes []byte, _path []byte) (*types.Transaction, error) { - return _Ion.Contract.CheckTxProof(&_Ion.TransactOpts, _id, _blockHash, _value, _parentNodes, _path) -} - -// RegisterChain is a paid mutator transaction binding the contract method 0x7558a01a. -// -// Solidity: function RegisterChain(_id bytes32, validationAddr address, _validators address[], _genesisHash bytes32) returns() -func (_Ion *IonTransactor) RegisterChain(opts *bind.TransactOpts, _id [32]byte, validationAddr common.Address, _validators []common.Address, _genesisHash [32]byte) (*types.Transaction, error) { - return _Ion.contract.Transact(opts, "RegisterChain", _id, validationAddr, _validators, _genesisHash) -} - -// RegisterChain is a paid mutator transaction binding the contract method 0x7558a01a. -// -// Solidity: function RegisterChain(_id bytes32, validationAddr address, _validators address[], _genesisHash bytes32) returns() -func (_Ion *IonSession) RegisterChain(_id [32]byte, validationAddr common.Address, _validators []common.Address, _genesisHash [32]byte) (*types.Transaction, error) { - return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id, validationAddr, _validators, _genesisHash) -} - -// RegisterChain is a paid mutator transaction binding the contract method 0x7558a01a. -// -// Solidity: function RegisterChain(_id bytes32, validationAddr address, _validators address[], _genesisHash bytes32) returns() -func (_Ion *IonTransactorSession) RegisterChain(_id [32]byte, validationAddr common.Address, _validators []common.Address, _genesisHash [32]byte) (*types.Transaction, error) { - return _Ion.Contract.RegisterChain(&_Ion.TransactOpts, _id, validationAddr, _validators, _genesisHash) -} - -// SubmitBlock is a paid mutator transaction binding the contract method 0x52824374. -// -// Solidity: function SubmitBlock(_id bytes32, _rlpBlockHeader bytes, _rlpSignedBlockHeader bytes) returns() -func (_Ion *IonTransactor) SubmitBlock(opts *bind.TransactOpts, _id [32]byte, _rlpBlockHeader []byte, _rlpSignedBlockHeader []byte) (*types.Transaction, error) { - return _Ion.contract.Transact(opts, "SubmitBlock", _id, _rlpBlockHeader, _rlpSignedBlockHeader) -} - -// SubmitBlock is a paid mutator transaction binding the contract method 0x52824374. -// -// Solidity: function SubmitBlock(_id bytes32, _rlpBlockHeader bytes, _rlpSignedBlockHeader bytes) returns() -func (_Ion *IonSession) SubmitBlock(_id [32]byte, _rlpBlockHeader []byte, _rlpSignedBlockHeader []byte) (*types.Transaction, error) { - return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _rlpBlockHeader, _rlpSignedBlockHeader) -} - -// SubmitBlock is a paid mutator transaction binding the contract method 0x52824374. -// -// Solidity: function SubmitBlock(_id bytes32, _rlpBlockHeader bytes, _rlpSignedBlockHeader bytes) returns() -func (_Ion *IonTransactorSession) SubmitBlock(_id [32]byte, _rlpBlockHeader []byte, _rlpSignedBlockHeader []byte) (*types.Transaction, error) { - return _Ion.Contract.SubmitBlock(&_Ion.TransactOpts, _id, _rlpBlockHeader, _rlpSignedBlockHeader) -} - -// IonVerifiedProofIterator is returned from FilterVerifiedProof and is used to iterate over the raw logs and unpacked data for VerifiedProof events raised by the Ion contract. -type IonVerifiedProofIterator struct { - Event *IonVerifiedProof // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IonVerifiedProofIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IonVerifiedProof) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IonVerifiedProof) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IonVerifiedProofIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IonVerifiedProofIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// IonVerifiedProof represents a VerifiedProof event raised by the Ion contract. -type IonVerifiedProof struct { - ChainId [32]byte - BlockHash [32]byte - ProofType *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterVerifiedProof is a free log retrieval operation binding the contract event 0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046. -// -// Solidity: e VerifiedProof(chainId bytes32, blockHash bytes32, proofType uint256) -func (_Ion *IonFilterer) FilterVerifiedProof(opts *bind.FilterOpts) (*IonVerifiedProofIterator, error) { - - logs, sub, err := _Ion.contract.FilterLogs(opts, "VerifiedProof") - if err != nil { - return nil, err - } - return &IonVerifiedProofIterator{contract: _Ion.contract, event: "VerifiedProof", logs: logs, sub: sub}, nil -} - -// WatchVerifiedProof is a free log subscription operation binding the contract event 0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046. -// -// Solidity: e VerifiedProof(chainId bytes32, blockHash bytes32, proofType uint256) -func (_Ion *IonFilterer) WatchVerifiedProof(opts *bind.WatchOpts, sink chan<- *IonVerifiedProof) (event.Subscription, error) { - - logs, sub, err := _Ion.contract.WatchLogs(opts, "VerifiedProof") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IonVerifiedProof) - if err := _Ion.contract.UnpackLog(event, "VerifiedProof", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// IonBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Ion contract. -type IonBroadcastHashIterator struct { - Event *IonBroadcastHash // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IonBroadcastHashIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IonBroadcastHash) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IonBroadcastHash) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IonBroadcastHashIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IonBroadcastHashIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// IonBroadcastHash represents a BroadcastHash event raised by the Ion contract. -type IonBroadcastHash struct { - BlockHash [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBroadcastHash is a free log retrieval operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. -// -// Solidity: e broadcastHash(blockHash bytes32) -func (_Ion *IonFilterer) FilterBroadcastHash(opts *bind.FilterOpts) (*IonBroadcastHashIterator, error) { - - logs, sub, err := _Ion.contract.FilterLogs(opts, "broadcastHash") - if err != nil { - return nil, err - } - return &IonBroadcastHashIterator{contract: _Ion.contract, event: "broadcastHash", logs: logs, sub: sub}, nil -} - -// WatchBroadcastHash is a free log subscription operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. -// -// Solidity: e broadcastHash(blockHash bytes32) -func (_Ion *IonFilterer) WatchBroadcastHash(opts *bind.WatchOpts, sink chan<- *IonBroadcastHash) (event.Subscription, error) { - - logs, sub, err := _Ion.contract.WatchLogs(opts, "broadcastHash") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IonBroadcastHash) - if err := _Ion.contract.UnpackLog(event, "broadcastHash", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// IonBroadcastSignatureIterator is returned from FilterBroadcastSignature and is used to iterate over the raw logs and unpacked data for BroadcastSignature events raised by the Ion contract. -type IonBroadcastSignatureIterator struct { - Event *IonBroadcastSignature // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IonBroadcastSignatureIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IonBroadcastSignature) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IonBroadcastSignature) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IonBroadcastSignatureIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IonBroadcastSignatureIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// IonBroadcastSignature represents a BroadcastSignature event raised by the Ion contract. -type IonBroadcastSignature struct { - Signer common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBroadcastSignature is a free log retrieval operation binding the contract event 0x3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef43. -// -// Solidity: e broadcastSignature(signer address) -func (_Ion *IonFilterer) FilterBroadcastSignature(opts *bind.FilterOpts) (*IonBroadcastSignatureIterator, error) { - - logs, sub, err := _Ion.contract.FilterLogs(opts, "broadcastSignature") - if err != nil { - return nil, err - } - return &IonBroadcastSignatureIterator{contract: _Ion.contract, event: "broadcastSignature", logs: logs, sub: sub}, nil -} - -// WatchBroadcastSignature is a free log subscription operation binding the contract event 0x3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef43. -// -// Solidity: e broadcastSignature(signer address) -func (_Ion *IonFilterer) WatchBroadcastSignature(opts *bind.WatchOpts, sink chan<- *IonBroadcastSignature) (event.Subscription, error) { - - logs, sub, err := _Ion.contract.WatchLogs(opts, "broadcastSignature") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IonBroadcastSignature) - if err := _Ion.contract.UnpackLog(event, "broadcastSignature", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} diff --git a/ion-cli/contracts/ion_test.go b/ion-cli/contracts/ion_test.go index 6421190..55c10b0 100644 --- a/ion-cli/contracts/ion_test.go +++ b/ion-cli/contracts/ion_test.go @@ -1,20 +1,7 @@ package contract import ( - "encoding/hex" - "encoding/json" - "fmt" - "log" - "math/big" - "testing" - - "github.com/clearmatics/ion/ion-cli/utils" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/assert" ) var CLIENT = "http://127.0.0.1:8501" @@ -32,219 +19,219 @@ var TEST_PARENT_NODES = `0xf8c3f851a0448f4ee6a987bf17a91096e25247c3d7d78dbd08afd // NOTE: These tests are skipped if go test -short is called // Ensure that Ion is deployed as expected -func Test_IonDeployement(t *testing.T) { - // Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} - blockchain := backends.NewSimulatedBackend(alloc) - - patriciaAddress, _, _, err := DeployPatriciaTrie( - auth, - blockchain, - ) - if err != nil { - log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) - } - - // Register id of another chain - deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - - _, _, ion, err := LinkDeployIon( - auth, - blockchain, - deployedChainID, - patriciaAddress, - "__./contracts/libraries/PatriciaTrie.s__", - ) - if err != nil { - log.Fatalf("Failed to link and deploy Ion: %v", err) - } - - // commit all pending transactions - blockchain.Commit() - - chainID, err := ion.ChainId(nil) - if err != nil { - log.Fatalf("Failed to retrieve chainID: %v", err) - } - - // Transform into string - CHAINID := fmt.Sprintf("%x", chainID) - assert.Equal(t, DEPLOYEDCHAINID, CHAINID) -} - -// Ensure chains are registered correctly -func Test_RegisterChain(t *testing.T) { - // Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} - blockchain := backends.NewSimulatedBackend(alloc) - - patriciaAddress, _, _, err := DeployPatriciaTrie( - auth, - blockchain, - ) - if err != nil { - log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) - } - - // Register id of another chain - deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - - _, _, ion, err := LinkDeployIon( - auth, - blockchain, - deployedChainID, - patriciaAddress, - "__./contracts/libraries/PatriciaTrie.s__", - ) - if err != nil { - log.Fatalf("Failed to link and deploy Ion: %v", err) - } - - // commit all pending transactions - blockchain.Commit() - - testChainID, _ := utils.StringToBytes32(TESTCHAINID) - - // Register an alternate chain - _, err = ion.RegisterChain(auth, testChainID) - if err != nil { - log.Fatalf("Failed to register chain: %v", err) - } - - // commit all pending transactions - blockchain.Commit() - - // Find deployed chainId - chain, err := ion.Chains(nil, big.NewInt(0)) - if err != nil { - log.Fatalf("Failed to retrieve chainID: %v", err) - } - - // Transform into string - CHAIN := fmt.Sprintf("%x", chain) - assert.Equal(t, TESTCHAINID, CHAIN) - -} - -// Fail if chain is registered more than once -func Test_FailRegisterChain(t *testing.T) { - // Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} - blockchain := backends.NewSimulatedBackend(alloc) - - patriciaAddress, _, _, err := DeployPatriciaTrie( - auth, - blockchain, - ) - if err != nil { - log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) - } - - // Register id of another chain - deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - - _, _, ion, err := LinkDeployIon( - auth, - blockchain, - deployedChainID, - patriciaAddress, - "__./contracts/libraries/PatriciaTrie.s__", - ) - if err != nil { - log.Fatalf("Failed to link and deploy Ion: %v", err) - } - - // commit all pending transactions - blockchain.Commit() - - testChainID, _ := utils.StringToBytes32(TESTCHAINID) - - // Register an alternate chain - _, err = ion.RegisterChain(auth, testChainID) - if err != nil { - log.Fatalf("Failed to register chain: %v", err) - } - - // commit all pending transactions - blockchain.Commit() - - // Register the same chain again - _, err = ion.RegisterChain(auth, testChainID) - assert.NotEqual(t, nil, err) -} - -// Ensure chains are registered correctly -func Test_SubmitBlock(t *testing.T) { - // Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000000000000)} - auth.GasPrice = big.NewInt(1) - auth.GasLimit = uint64(1000000) - blockchain := backends.NewSimulatedBackend(alloc) - - patriciaAddress, _, _, err := DeployPatriciaTrie( - auth, - blockchain, - ) - if err != nil { - log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) - } - - // Register id of another chain - deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - - _, _, ion, err := LinkDeployIon( - auth, - blockchain, - deployedChainID, - patriciaAddress, - "__./contracts/libraries/PatriciaTrie.s__", - ) - if err != nil { - log.Fatalf("Failed to link and deploy Ion: %v", err) - } - - // commit all pending transactions - blockchain.Commit() - - testChainID, _ := utils.StringToBytes32(TESTCHAINID) - - // Register an alternate chain - _, err = ion.RegisterChain(auth, testChainID) - if err != nil { - log.Fatalf("Failed to register chain: %v", err) - } - - // commit all pending transactions - blockchain.Commit() - - // Submit block - var blockHeader utils.Header - err = json.Unmarshal([]byte(TESTBLOCK), &blockHeader) - if err != nil { - log.Fatal("Unmarshal failed", err) - } - blockHash, _ := utils.StringToBytes32(blockHeader.Root) - // blockParentHash, _ := utils.StringToBytes32(blockHeader.ParentHash) - // blockTxHash, _ := utils.StringToBytes32(blockHeader.TxHash) - // blockReceiptHash, _ := utils.StringToBytes32(blockHeader.ReceiptHash) - - rlpEncodingBytes, err := hex.DecodeString(TESTRLPENCODING) - - _, err = ion.SubmitBlock(auth, testChainID, blockHash, rlpEncodingBytes) - if err != nil { - log.Fatalf("Failed to submit block: %v", err) - } - -} +// func Test_IonDeployement(t *testing.T) { +// // Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} +// blockchain := backends.NewSimulatedBackend(alloc) + +// patriciaAddress, _, _, err := DeployPatricia( +// auth, +// blockchain, +// ) +// if err != nil { +// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) +// } + +// // Register id of another chain +// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) + +// _, _, ion, err := LinkDeployIon( +// auth, +// blockchain, +// deployedChainID, +// patriciaAddress, +// "__./contracts/libraries/PatriciaTrie.s__", +// ) +// if err != nil { +// log.Fatalf("Failed to link and deploy Ion: %v", err) +// } + +// // commit all pending transactions +// blockchain.Commit() + +// chainID, err := ion.ChainId(nil) +// if err != nil { +// log.Fatalf("Failed to retrieve chainID: %v", err) +// } + +// // Transform into string +// CHAINID := fmt.Sprintf("%x", chainID) +// assert.Equal(t, DEPLOYEDCHAINID, CHAINID) +// } + +// // Ensure chains are registered correctly +// func Test_RegisterChain(t *testing.T) { +// // Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} +// blockchain := backends.NewSimulatedBackend(alloc) + +// patriciaAddress, _, _, err := DeployPatricia( +// auth, +// blockchain, +// ) +// if err != nil { +// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) +// } + +// // Register id of another chain +// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) + +// _, _, ion, err := LinkDeployIon( +// auth, +// blockchain, +// deployedChainID, +// patriciaAddress, +// "__./contracts/libraries/PatriciaTrie.s__", +// ) +// if err != nil { +// log.Fatalf("Failed to link and deploy Ion: %v", err) +// } + +// // commit all pending transactions +// blockchain.Commit() + +// testChainID, _ := utils.StringToBytes32(TESTCHAINID) + +// // Register an alternate chain +// _, err = ion.RegisterChain(auth, testChainID) +// if err != nil { +// log.Fatalf("Failed to register chain: %v", err) +// } + +// // commit all pending transactions +// blockchain.Commit() + +// // Find deployed chainId +// chain, err := ion.Chains(nil, big.NewInt(0)) +// if err != nil { +// log.Fatalf("Failed to retrieve chainID: %v", err) +// } + +// // Transform into string +// CHAIN := fmt.Sprintf("%x", chain) +// assert.Equal(t, TESTCHAINID, CHAIN) + +// } + +// // Fail if chain is registered more than once +// func Test_FailRegisterChain(t *testing.T) { +// // Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} +// blockchain := backends.NewSimulatedBackend(alloc) + +// patriciaAddress, _, _, err := DeployPatricia( +// auth, +// blockchain, +// ) +// if err != nil { +// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) +// } + +// // Register id of another chain +// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) + +// _, _, ion, err := LinkDeployIon( +// auth, +// blockchain, +// deployedChainID, +// patriciaAddress, +// "__./contracts/libraries/PatriciaTrie.s__", +// ) +// if err != nil { +// log.Fatalf("Failed to link and deploy Ion: %v", err) +// } + +// // commit all pending transactions +// blockchain.Commit() + +// testChainID, _ := utils.StringToBytes32(TESTCHAINID) + +// // Register an alternate chain +// _, err = ion.RegisterChain(auth, testChainID) +// if err != nil { +// log.Fatalf("Failed to register chain: %v", err) +// } + +// // commit all pending transactions +// blockchain.Commit() + +// // Register the same chain again +// _, err = ion.RegisterChain(auth, testChainID) +// assert.NotEqual(t, nil, err) +// } + +// // Ensure chains are registered correctly +// func Test_SubmitBlock(t *testing.T) { +// // Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000000000000)} +// auth.GasPrice = big.NewInt(1) +// auth.GasLimit = uint64(1000000) +// blockchain := backends.NewSimulatedBackend(alloc) + +// patriciaAddress, _, _, err := DeployPatricia( +// auth, +// blockchain, +// ) +// if err != nil { +// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) +// } + +// // Register id of another chain +// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) + +// _, _, ion, err := LinkDeployIon( +// auth, +// blockchain, +// deployedChainID, +// patriciaAddress, +// "__./contracts/libraries/PatriciaTrie.s__", +// ) +// if err != nil { +// log.Fatalf("Failed to link and deploy Ion: %v", err) +// } + +// // commit all pending transactions +// blockchain.Commit() + +// testChainID, _ := utils.StringToBytes32(TESTCHAINID) + +// // Register an alternate chain +// _, err = ion.RegisterChain(auth, testChainID) +// if err != nil { +// log.Fatalf("Failed to register chain: %v", err) +// } + +// // commit all pending transactions +// blockchain.Commit() + +// // Submit block +// var blockHeader utils.Header +// err = json.Unmarshal([]byte(TESTBLOCK), &blockHeader) +// if err != nil { +// log.Fatal("Unmarshal failed", err) +// } +// blockHash, _ := utils.StringToBytes32(blockHeader.Root) +// // blockParentHash, _ := utils.StringToBytes32(blockHeader.ParentHash) +// // blockTxHash, _ := utils.StringToBytes32(blockHeader.TxHash) +// // blockReceiptHash, _ := utils.StringToBytes32(blockHeader.ReceiptHash) + +// rlpEncodingBytes, err := hex.DecodeString(TESTRLPENCODING) + +// _, err = ion.SubmitBlock(auth, testChainID, blockHash, rlpEncodingBytes) +// if err != nil { +// log.Fatalf("Failed to submit block: %v", err) +// } + +// } diff --git a/ion-cli/contracts/patricia.go b/ion-cli/contracts/patricia.go deleted file mode 100644 index 755c612..0000000 --- a/ion-cli/contracts/patricia.go +++ /dev/null @@ -1,200 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contract - -import ( - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -// PatriciaTrieABI is the input ABI used to generate the binding from. -const PatriciaTrieABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"_value\",\"type\":\"bytes\"},{\"name\":\"_parentNodes\",\"type\":\"bytes\"},{\"name\":\"_path\",\"type\":\"bytes\"},{\"name\":\"_root\",\"type\":\"bytes32\"}],\"name\":\"verifyProof\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - -// PatriciaTrieBin is the compiled bytecode used for deploying new contracts. -const PatriciaTrieBin = `611278610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634f7142ad1461005d575b600080fd5b610151600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803560001916906020019092919050505061016b565b604051808215151515815260200191505060405180910390f35b60006101756111d5565b606060006060806000606060008060608061018f8f61060f565b9a5061019a8b61066a565b99508c9850600095506101ae8e6000610727565b9450600093505b89518410156105fb576101de8a858151811015156101cf57fe5b90602001906020020151610ad7565b9750876040518082805190602001908083835b60208310151561021657805182526020820191506020810190506020830392506101f1565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916896000191614151561025c5760009b506105fc565b61027c8a8581518110151561026d57fe5b9060200190602002015161066a565b9650601187511415610446578451861415610397578f6040518082805190602001908083835b6020831015156102c757805182526020820191506020810190506020830392506102a2565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661031988601081518110151561030a57fe5b90602001906020020151610ad7565b6040518082805190602001908083835b60208310151561034e5780518252602082019150602081019050602083039250610329565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141561038e5760019b506105fc565b60009b506105fc565b84868151811015156103a557fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250610439878461ffff1681518110151561042a57fe5b90602001906020020151610b3c565b98506001860195506105ee565b6002875114156105e45761047187600081518110151561046257fe5b90602001906020020151610b51565b915061047e826001610727565b51860195508451861415610592578f6040518082805190602001908083835b6020831015156104c2578051825260208201915060208101905060208303925061049d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661051488600181518110151561050557fe5b90602001906020020151610b51565b6040518082805190602001908083835b6020831015156105495780518252602082019150602081019050602083039250610524565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614156105895760019b506105fc565b60009b506105fc565b600061059f836001610727565b5114156105af5760009b506105fc565b6105d08760018151811015156105c157fe5b90602001906020020151610b51565b90506105dd816000610bc3565b98506105ed565b60009b506105fc565b5b83806001019450506101b5565b5b5050505050505050505050949350505050565b6106176111d5565b6000808351915060008214156106455760408051908101604052806000815260200160008152509250610663565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006106766111ef565b600061068185610ca1565b151561068c57600080fd5b61069585610cd3565b9250826040519080825280602002602001820160405280156106d157816020015b6106be611210565b8152602001906001900390816106b65790505b5093506106dd85610d4d565b91505b6106e982610d95565b1561071f576106f782610dbf565b848281518110151561070557fe5b9060200190602002018190525080806001019150506106e0565b505050919050565b60608060008061073561122a565b6060600060ff6040519080825280601f01601f19166020018201604052801561076d5781602001602082028038833980820191505090505b50955060009450600093505b88518410156109db576107e3898581518110151561079357fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002610e1b565b92508780156107f25750600084145b1561091a5760017f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561082a57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108b4575060037f01000000000000000000000000000000000000000000000000000000000000000283600060028110151561088b57fe5b60200201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b15610915578260016002811015156108c857fe5b6020020151868660ff168151811015156108de57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001850194505b6109ce565b82600060028110151561092957fe5b6020020151868660ff1681518110151561093f57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535082600160028110151561097e57fe5b6020020151866001870160ff1681518110151561099757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506002850194505b8380600101945050610779565b8460ff166040519080825280601f01601f191660200182016040528015610a115781602001602082028038833980820191505090505b509150600090505b8460ff16811015610ac8578581815181101515610a3257fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000028282815181101515610a8b57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050610a19565b81965050505050505092915050565b60606000826020015190506000811415610af057610b36565b806040519080825280601f01601f191660200182016040528015610b235781602001602082028038833980820191505090505b509150610b3583600001518383610f01565b5b50919050565b6000610b4782610f42565b6001029050919050565b6060600080610b5f84610f99565b1515610b6a57600080fd5b610b7384610fca565b8092508193505050806040519080825280601f01601f191660200182016040528015610bae5781602001602082028038833980820191505090505b509250610bbc828483610f01565b5050919050565b60008060008090505b6020811015610c96576008810260ff7f01000000000000000000000000000000000000000000000000000000000000000286838701815181101515610c0d57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600019169060020a9004821791508080600101915050610bcc565b819250505092915050565b600080600083602001511415610cba5760009150610ccd565b8260000151905060c0815160001a101591505b50919050565b600080600080600080610ce587610ca1565b1515610cf45760009550610d43565b86600001519350835160001a9450610d0b8761104b565b840192506001876020015185010391505b8183111515610d3f57610d2e836110d7565b830192508080600101915050610d1c565b8095505b5050505050919050565b610d556111ef565b6000610d6083610ca1565b1515610d6b57600080fd5b610d748361104b565b83600001510190508282600001819052508082602001818152505050919050565b6000610d9f6111d5565b826000015190508060200151816000015101836020015110915050919050565b610dc76111d5565b600080610dd384610d95565b15610e0f5783602001519150610de8826110d7565b90508183600001818152505080836020018181525050808201846020018181525050610e14565b600080fd5b5050919050565b610e2361122a565b600080610e31846004611171565b9150600f7f010000000000000000000000000000000000000000000000000000000000000002841690506040805190810160405280837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525092505050919050565b60006020601f83010484602085015b828414610f2f5760208402808301518183015260018501945050610f10565b6000865160200187015250505050505050565b6000806000610f5084610f99565b1515610f5b57600080fd5b610f6484610fca565b80925081935050506020811180610f7b5750600081145b15610f8557600080fd5b806020036101000a82510492505050919050565b600080600083602001511415610fb25760009150610fc4565b8260000151905060c0815160001a1091505b50919050565b6000806000806000610fdb86610f99565b1515610fe657600080fd5b85600001519150815160001a925060808310156110095781945060019350611043565b60b88310156110275760018660200151039350600182019450611042565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b6000806000808460200151141561106557600092506110d0565b83600001519050805160001a9150608082101561108557600092506110d0565b60b88210806110a1575060c082101580156110a0575060f882105b5b156110af57600192506110d0565b60c08210156110c657600160b783030192506110d0565b600160f783030192505b5050919050565b600080825160001a905060808110156110f3576001915061116b565b60b881101561110a5760016080820301915061116a565b60c08110156111345760b78103806020036101000a60018501510480820160010193505050611169565b60f881101561114b57600160c08203019150611168565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008160020a60ff16837f0100000000000000000000000000000000000000000000000000000000000000900460ff168115156111aa57fe5b047f010000000000000000000000000000000000000000000000000000000000000002905092915050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611203611210565b8152602001600081525090565b604080519081016040528060008152602001600081525090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a7230582027380a33dbfdf1a14b565c857047780931c383048b159e2e7117549db774476a0029` - -// DeployPatriciaTrie deploys a new Ethereum contract, binding an instance of PatriciaTrie to it. -func DeployPatriciaTrie(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *PatriciaTrie, error) { - parsed, err := abi.JSON(strings.NewReader(PatriciaTrieABI)) - if err != nil { - return common.Address{}, nil, nil, err - } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(PatriciaTrieBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &PatriciaTrie{PatriciaTrieCaller: PatriciaTrieCaller{contract: contract}, PatriciaTrieTransactor: PatriciaTrieTransactor{contract: contract}, PatriciaTrieFilterer: PatriciaTrieFilterer{contract: contract}}, nil -} - -// PatriciaTrie is an auto generated Go binding around an Ethereum contract. -type PatriciaTrie struct { - PatriciaTrieCaller // Read-only binding to the contract - PatriciaTrieTransactor // Write-only binding to the contract - PatriciaTrieFilterer // Log filterer for contract events -} - -// PatriciaTrieCaller is an auto generated read-only Go binding around an Ethereum contract. -type PatriciaTrieCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// PatriciaTrieTransactor is an auto generated write-only Go binding around an Ethereum contract. -type PatriciaTrieTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// PatriciaTrieFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type PatriciaTrieFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// PatriciaTrieSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type PatriciaTrieSession struct { - Contract *PatriciaTrie // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// PatriciaTrieCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type PatriciaTrieCallerSession struct { - Contract *PatriciaTrieCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// PatriciaTrieTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type PatriciaTrieTransactorSession struct { - Contract *PatriciaTrieTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// PatriciaTrieRaw is an auto generated low-level Go binding around an Ethereum contract. -type PatriciaTrieRaw struct { - Contract *PatriciaTrie // Generic contract binding to access the raw methods on -} - -// PatriciaTrieCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type PatriciaTrieCallerRaw struct { - Contract *PatriciaTrieCaller // Generic read-only contract binding to access the raw methods on -} - -// PatriciaTrieTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type PatriciaTrieTransactorRaw struct { - Contract *PatriciaTrieTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewPatriciaTrie creates a new instance of PatriciaTrie, bound to a specific deployed contract. -func NewPatriciaTrie(address common.Address, backend bind.ContractBackend) (*PatriciaTrie, error) { - contract, err := bindPatriciaTrie(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &PatriciaTrie{PatriciaTrieCaller: PatriciaTrieCaller{contract: contract}, PatriciaTrieTransactor: PatriciaTrieTransactor{contract: contract}, PatriciaTrieFilterer: PatriciaTrieFilterer{contract: contract}}, nil -} - -// NewPatriciaTrieCaller creates a new read-only instance of PatriciaTrie, bound to a specific deployed contract. -func NewPatriciaTrieCaller(address common.Address, caller bind.ContractCaller) (*PatriciaTrieCaller, error) { - contract, err := bindPatriciaTrie(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &PatriciaTrieCaller{contract: contract}, nil -} - -// NewPatriciaTrieTransactor creates a new write-only instance of PatriciaTrie, bound to a specific deployed contract. -func NewPatriciaTrieTransactor(address common.Address, transactor bind.ContractTransactor) (*PatriciaTrieTransactor, error) { - contract, err := bindPatriciaTrie(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &PatriciaTrieTransactor{contract: contract}, nil -} - -// NewPatriciaTrieFilterer creates a new log filterer instance of PatriciaTrie, bound to a specific deployed contract. -func NewPatriciaTrieFilterer(address common.Address, filterer bind.ContractFilterer) (*PatriciaTrieFilterer, error) { - contract, err := bindPatriciaTrie(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &PatriciaTrieFilterer{contract: contract}, nil -} - -// bindPatriciaTrie binds a generic wrapper to an already deployed contract. -func bindPatriciaTrie(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(PatriciaTrieABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_PatriciaTrie *PatriciaTrieRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _PatriciaTrie.Contract.PatriciaTrieCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_PatriciaTrie *PatriciaTrieRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PatriciaTrie.Contract.PatriciaTrieTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_PatriciaTrie *PatriciaTrieRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PatriciaTrie.Contract.PatriciaTrieTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_PatriciaTrie *PatriciaTrieCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _PatriciaTrie.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_PatriciaTrie *PatriciaTrieTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PatriciaTrie.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_PatriciaTrie *PatriciaTrieTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PatriciaTrie.Contract.contract.Transact(opts, method, params...) -} - -// VerifyProof is a free data retrieval call binding the contract method 0x4f7142ad. -// -// Solidity: function verifyProof(_value bytes, _parentNodes bytes, _path bytes, _root bytes32) constant returns(bool) -func (_PatriciaTrie *PatriciaTrieCaller) VerifyProof(opts *bind.CallOpts, _value []byte, _parentNodes []byte, _path []byte, _root [32]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _PatriciaTrie.contract.Call(opts, out, "verifyProof", _value, _parentNodes, _path, _root) - return *ret0, err -} - -// VerifyProof is a free data retrieval call binding the contract method 0x4f7142ad. -// -// Solidity: function verifyProof(_value bytes, _parentNodes bytes, _path bytes, _root bytes32) constant returns(bool) -func (_PatriciaTrie *PatriciaTrieSession) VerifyProof(_value []byte, _parentNodes []byte, _path []byte, _root [32]byte) (bool, error) { - return _PatriciaTrie.Contract.VerifyProof(&_PatriciaTrie.CallOpts, _value, _parentNodes, _path, _root) -} - -// VerifyProof is a free data retrieval call binding the contract method 0x4f7142ad. -// -// Solidity: function verifyProof(_value bytes, _parentNodes bytes, _path bytes, _root bytes32) constant returns(bool) -func (_PatriciaTrie *PatriciaTrieCallerSession) VerifyProof(_value []byte, _parentNodes []byte, _path []byte, _root [32]byte) (bool, error) { - return _PatriciaTrie.Contract.VerifyProof(&_PatriciaTrie.CallOpts, _value, _parentNodes, _path, _root) -} diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go deleted file mode 100644 index 2d9b10e..0000000 --- a/ion-cli/contracts/validation.go +++ /dev/null @@ -1,842 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contract - -import ( - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// ValidationABI is the input ABI used to generate the binding from. -const ValidationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"validators\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GetBlock\",\"outputs\":[{\"name\":\"_blockHash\",\"type\":\"bytes32\"},{\"name\":\"_prevBlockHash\",\"type\":\"bytes32\"},{\"name\":\"_blockHeight\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LatestBlock\",\"outputs\":[{\"name\":\"_latestBlock\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_header\",\"type\":\"bytes\"},{\"name\":\"prefixHeader\",\"type\":\"bytes\"},{\"name\":\"prefixExtraData\",\"type\":\"bytes\"}],\"name\":\"ValidateBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"m_blockheaders\",\"outputs\":[{\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"name\":\"prevBlockHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetValidators\",\"outputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_validators\",\"type\":\"address[]\"},{\"name\":\"genesisHash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"broadcastSig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"header\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"parentHash\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"rootHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHashData\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"name\":\"broadcastHash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"blockHash\",\"type\":\"bytes\"}],\"name\":\"broadcastHash2\",\"type\":\"event\"}]" - -// ValidationBin is the compiled bytecode used for deploying new contracts. -const ValidationBin = `608060405234801561001057600080fd5b50604051610ca4380380610ca483398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816003816000191690555081600460008081526020019081526020016000206000018160001916905550505050610adf806101c56000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806335aa2e441461007d57806340ce4b6c146100ea5780639db7d9f714610149578063aae933e41461017c578063c4cf3ed614610271578063d405af3d146102c9575b600080fd5b34801561008957600080fd5b506100a860048036038101908080359060200190929190505050610335565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100f657600080fd5b5061011560048036038101908080359060200190929190505050610373565b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390f35b34801561015557600080fd5b5061015e6103b6565b60405180826000191660001916815260200191505060405180910390f35b34801561018857600080fd5b5061026f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506103c0565b005b34801561027d57600080fd5b5061029c60048036038101908080359060200190929190505050610857565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b3480156102d557600080fd5b506102de61087b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610321578082015181840152602081019050610306565b505050509050019250505060405180910390f35b60018181548110151561034457fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000600460008581526020019081526020016000206000015492506004600085815260200190815260200160002060010154915060025490509193909250565b6000600354905090565b600080600060608060608060606000806103db8d6004610909565b9950600354600019168a6000191614151561045e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b8c5198508c6040518082805190602001908083835b6020831015156104985780518252602082019150602081019050602083039250610473565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f19166020018201604052801561053c5781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156105735781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156105aa5781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156105e15781602001602082028038833980820191505090505b5093506105f0878e600061091d565b600260218801600260208f016004610bb8fa50610611868e608c8c0361091d565b600160208701600160208e016004610bb8fa50610632848e602a8c0361091d565b61063d87878661093f565b9250826040518082805190602001908083835b6020831015156106755780518252602082019150602081019050602083039250610650565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506106b2858e606b8c0361091d565b6106bc82866109eb565b905060011515600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515610786576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b87600381600019169055506002600081548092919060010191905055508760046000600254815260200190815260200160002060000181600019169055508960046000600254815260200190815260200160002060010181600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050505050505050505050565b60046020528060005260406000206000915090508060000154908060010154905082565b606060018054806020026020016040519081016040528092919081815260200182805480156108ff57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116108b5575b5050505050905090565b600060208201915081830151905092915050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109a65781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a0157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a2c57601b810190505b601b8160ff161480610a415750601c8160ff16145b1515610a4c57600080fd5b610a5886828585610a63565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610aa657600080fd5b80925050509493505050505600a165627a7a72305820cf83fdc91c1477a7ff4a9251338903b37b04c10ccb8538af298dd16fece5a0ba0029` - -// DeployValidation deploys a new Ethereum contract, binding an instance of Validation to it. -func DeployValidation(auth *bind.TransactOpts, backend bind.ContractBackend, _validators []common.Address, genesisHash [32]byte) (common.Address, *types.Transaction, *Validation, error) { - parsed, err := abi.JSON(strings.NewReader(ValidationABI)) - if err != nil { - return common.Address{}, nil, nil, err - } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ValidationBin), backend, _validators, genesisHash) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Validation{ValidationCaller: ValidationCaller{contract: contract}, ValidationTransactor: ValidationTransactor{contract: contract}, ValidationFilterer: ValidationFilterer{contract: contract}}, nil -} - -// Validation is an auto generated Go binding around an Ethereum contract. -type Validation struct { - ValidationCaller // Read-only binding to the contract - ValidationTransactor // Write-only binding to the contract - ValidationFilterer // Log filterer for contract events -} - -// ValidationCaller is an auto generated read-only Go binding around an Ethereum contract. -type ValidationCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ValidationTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ValidationTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ValidationFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ValidationFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ValidationSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ValidationSession struct { - Contract *Validation // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ValidationCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ValidationCallerSession struct { - Contract *ValidationCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ValidationTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ValidationTransactorSession struct { - Contract *ValidationTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ValidationRaw is an auto generated low-level Go binding around an Ethereum contract. -type ValidationRaw struct { - Contract *Validation // Generic contract binding to access the raw methods on -} - -// ValidationCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ValidationCallerRaw struct { - Contract *ValidationCaller // Generic read-only contract binding to access the raw methods on -} - -// ValidationTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ValidationTransactorRaw struct { - Contract *ValidationTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewValidation creates a new instance of Validation, bound to a specific deployed contract. -func NewValidation(address common.Address, backend bind.ContractBackend) (*Validation, error) { - contract, err := bindValidation(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Validation{ValidationCaller: ValidationCaller{contract: contract}, ValidationTransactor: ValidationTransactor{contract: contract}, ValidationFilterer: ValidationFilterer{contract: contract}}, nil -} - -// NewValidationCaller creates a new read-only instance of Validation, bound to a specific deployed contract. -func NewValidationCaller(address common.Address, caller bind.ContractCaller) (*ValidationCaller, error) { - contract, err := bindValidation(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ValidationCaller{contract: contract}, nil -} - -// NewValidationTransactor creates a new write-only instance of Validation, bound to a specific deployed contract. -func NewValidationTransactor(address common.Address, transactor bind.ContractTransactor) (*ValidationTransactor, error) { - contract, err := bindValidation(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ValidationTransactor{contract: contract}, nil -} - -// NewValidationFilterer creates a new log filterer instance of Validation, bound to a specific deployed contract. -func NewValidationFilterer(address common.Address, filterer bind.ContractFilterer) (*ValidationFilterer, error) { - contract, err := bindValidation(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ValidationFilterer{contract: contract}, nil -} - -// bindValidation binds a generic wrapper to an already deployed contract. -func bindValidation(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(ValidationABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Validation *ValidationRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Validation.Contract.ValidationCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Validation *ValidationRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Validation.Contract.ValidationTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Validation *ValidationRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Validation.Contract.ValidationTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Validation *ValidationCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Validation.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Validation *ValidationTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Validation.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Validation *ValidationTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Validation.Contract.contract.Transact(opts, method, params...) -} - -// GetBlock is a free data retrieval call binding the contract method 0x40ce4b6c. -// -// Solidity: function GetBlock(blockNumber uint256) constant returns(_blockHash bytes32, _prevBlockHash bytes32, _blockHeight uint256) -func (_Validation *ValidationCaller) GetBlock(opts *bind.CallOpts, blockNumber *big.Int) (struct { - BlockHash [32]byte - PrevBlockHash [32]byte - BlockHeight *big.Int -}, error) { - ret := new(struct { - BlockHash [32]byte - PrevBlockHash [32]byte - BlockHeight *big.Int - }) - out := ret - err := _Validation.contract.Call(opts, out, "GetBlock", blockNumber) - return *ret, err -} - -// GetBlock is a free data retrieval call binding the contract method 0x40ce4b6c. -// -// Solidity: function GetBlock(blockNumber uint256) constant returns(_blockHash bytes32, _prevBlockHash bytes32, _blockHeight uint256) -func (_Validation *ValidationSession) GetBlock(blockNumber *big.Int) (struct { - BlockHash [32]byte - PrevBlockHash [32]byte - BlockHeight *big.Int -}, error) { - return _Validation.Contract.GetBlock(&_Validation.CallOpts, blockNumber) -} - -// GetBlock is a free data retrieval call binding the contract method 0x40ce4b6c. -// -// Solidity: function GetBlock(blockNumber uint256) constant returns(_blockHash bytes32, _prevBlockHash bytes32, _blockHeight uint256) -func (_Validation *ValidationCallerSession) GetBlock(blockNumber *big.Int) (struct { - BlockHash [32]byte - PrevBlockHash [32]byte - BlockHeight *big.Int -}, error) { - return _Validation.Contract.GetBlock(&_Validation.CallOpts, blockNumber) -} - -// GetValidators is a free data retrieval call binding the contract method 0xd405af3d. -// -// Solidity: function GetValidators() constant returns(_validators address[]) -func (_Validation *ValidationCaller) GetValidators(opts *bind.CallOpts) ([]common.Address, error) { - var ( - ret0 = new([]common.Address) - ) - out := ret0 - err := _Validation.contract.Call(opts, out, "GetValidators") - return *ret0, err -} - -// GetValidators is a free data retrieval call binding the contract method 0xd405af3d. -// -// Solidity: function GetValidators() constant returns(_validators address[]) -func (_Validation *ValidationSession) GetValidators() ([]common.Address, error) { - return _Validation.Contract.GetValidators(&_Validation.CallOpts) -} - -// GetValidators is a free data retrieval call binding the contract method 0xd405af3d. -// -// Solidity: function GetValidators() constant returns(_validators address[]) -func (_Validation *ValidationCallerSession) GetValidators() ([]common.Address, error) { - return _Validation.Contract.GetValidators(&_Validation.CallOpts) -} - -// LatestBlock is a free data retrieval call binding the contract method 0x9db7d9f7. -// -// Solidity: function LatestBlock() constant returns(_latestBlock bytes32) -func (_Validation *ValidationCaller) LatestBlock(opts *bind.CallOpts) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Validation.contract.Call(opts, out, "LatestBlock") - return *ret0, err -} - -// LatestBlock is a free data retrieval call binding the contract method 0x9db7d9f7. -// -// Solidity: function LatestBlock() constant returns(_latestBlock bytes32) -func (_Validation *ValidationSession) LatestBlock() ([32]byte, error) { - return _Validation.Contract.LatestBlock(&_Validation.CallOpts) -} - -// LatestBlock is a free data retrieval call binding the contract method 0x9db7d9f7. -// -// Solidity: function LatestBlock() constant returns(_latestBlock bytes32) -func (_Validation *ValidationCallerSession) LatestBlock() ([32]byte, error) { - return _Validation.Contract.LatestBlock(&_Validation.CallOpts) -} - -// MBlockheaders is a free data retrieval call binding the contract method 0xc4cf3ed6. -// -// Solidity: function m_blockheaders( uint256) constant returns(blockHash bytes32, prevBlockHash bytes32) -func (_Validation *ValidationCaller) MBlockheaders(opts *bind.CallOpts, arg0 *big.Int) (struct { - BlockHash [32]byte - PrevBlockHash [32]byte -}, error) { - ret := new(struct { - BlockHash [32]byte - PrevBlockHash [32]byte - }) - out := ret - err := _Validation.contract.Call(opts, out, "m_blockheaders", arg0) - return *ret, err -} - -// MBlockheaders is a free data retrieval call binding the contract method 0xc4cf3ed6. -// -// Solidity: function m_blockheaders( uint256) constant returns(blockHash bytes32, prevBlockHash bytes32) -func (_Validation *ValidationSession) MBlockheaders(arg0 *big.Int) (struct { - BlockHash [32]byte - PrevBlockHash [32]byte -}, error) { - return _Validation.Contract.MBlockheaders(&_Validation.CallOpts, arg0) -} - -// MBlockheaders is a free data retrieval call binding the contract method 0xc4cf3ed6. -// -// Solidity: function m_blockheaders( uint256) constant returns(blockHash bytes32, prevBlockHash bytes32) -func (_Validation *ValidationCallerSession) MBlockheaders(arg0 *big.Int) (struct { - BlockHash [32]byte - PrevBlockHash [32]byte -}, error) { - return _Validation.Contract.MBlockheaders(&_Validation.CallOpts, arg0) -} - -// Validators is a free data retrieval call binding the contract method 0x35aa2e44. -// -// Solidity: function validators( uint256) constant returns(address) -func (_Validation *ValidationCaller) Validators(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { - var ( - ret0 = new(common.Address) - ) - out := ret0 - err := _Validation.contract.Call(opts, out, "validators", arg0) - return *ret0, err -} - -// Validators is a free data retrieval call binding the contract method 0x35aa2e44. -// -// Solidity: function validators( uint256) constant returns(address) -func (_Validation *ValidationSession) Validators(arg0 *big.Int) (common.Address, error) { - return _Validation.Contract.Validators(&_Validation.CallOpts, arg0) -} - -// Validators is a free data retrieval call binding the contract method 0x35aa2e44. -// -// Solidity: function validators( uint256) constant returns(address) -func (_Validation *ValidationCallerSession) Validators(arg0 *big.Int) (common.Address, error) { - return _Validation.Contract.Validators(&_Validation.CallOpts, arg0) -} - -// ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. -// -// Solidity: function ValidateBlock(_header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactor) ValidateBlock(opts *bind.TransactOpts, _header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.contract.Transact(opts, "ValidateBlock", _header, prefixHeader, prefixExtraData) -} - -// ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. -// -// Solidity: function ValidateBlock(_header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationSession) ValidateBlock(_header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, _header, prefixHeader, prefixExtraData) -} - -// ValidateBlock is a paid mutator transaction binding the contract method 0xaae933e4. -// -// Solidity: function ValidateBlock(_header bytes, prefixHeader bytes, prefixExtraData bytes) returns() -func (_Validation *ValidationTransactorSession) ValidateBlock(_header []byte, prefixHeader []byte, prefixExtraData []byte) (*types.Transaction, error) { - return _Validation.Contract.ValidateBlock(&_Validation.TransactOpts, _header, prefixHeader, prefixExtraData) -} - -// ValidationBroadcastHashIterator is returned from FilterBroadcastHash and is used to iterate over the raw logs and unpacked data for BroadcastHash events raised by the Validation contract. -type ValidationBroadcastHashIterator struct { - Event *ValidationBroadcastHash // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ValidationBroadcastHashIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastHash) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastHash) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ValidationBroadcastHashIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ValidationBroadcastHashIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ValidationBroadcastHash represents a BroadcastHash event raised by the Validation contract. -type ValidationBroadcastHash struct { - BlockHash [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBroadcastHash is a free log retrieval operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. -// -// Solidity: event broadcastHash(blockHash bytes32) -func (_Validation *ValidationFilterer) FilterBroadcastHash(opts *bind.FilterOpts) (*ValidationBroadcastHashIterator, error) { - - logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastHash") - if err != nil { - return nil, err - } - return &ValidationBroadcastHashIterator{contract: _Validation.contract, event: "broadcastHash", logs: logs, sub: sub}, nil -} - -// WatchBroadcastHash is a free log subscription operation binding the contract event 0xcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf01. -// -// Solidity: event broadcastHash(blockHash bytes32) -func (_Validation *ValidationFilterer) WatchBroadcastHash(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastHash) (event.Subscription, error) { - - logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastHash") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ValidationBroadcastHash) - if err := _Validation.contract.UnpackLog(event, "broadcastHash", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ValidationBroadcastHash2Iterator is returned from FilterBroadcastHash2 and is used to iterate over the raw logs and unpacked data for BroadcastHash2 events raised by the Validation contract. -type ValidationBroadcastHash2Iterator struct { - Event *ValidationBroadcastHash2 // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ValidationBroadcastHash2Iterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastHash2) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastHash2) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ValidationBroadcastHash2Iterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ValidationBroadcastHash2Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ValidationBroadcastHash2 represents a BroadcastHash2 event raised by the Validation contract. -type ValidationBroadcastHash2 struct { - BlockHash []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBroadcastHash2 is a free log retrieval operation binding the contract event 0xd5796acb84f214e8b630fe40f93fdbf75c0a53b553e23be97a99e61152f174d2. -// -// Solidity: event broadcastHash2(blockHash bytes) -func (_Validation *ValidationFilterer) FilterBroadcastHash2(opts *bind.FilterOpts) (*ValidationBroadcastHash2Iterator, error) { - - logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastHash2") - if err != nil { - return nil, err - } - return &ValidationBroadcastHash2Iterator{contract: _Validation.contract, event: "broadcastHash2", logs: logs, sub: sub}, nil -} - -// WatchBroadcastHash2 is a free log subscription operation binding the contract event 0xd5796acb84f214e8b630fe40f93fdbf75c0a53b553e23be97a99e61152f174d2. -// -// Solidity: event broadcastHash2(blockHash bytes) -func (_Validation *ValidationFilterer) WatchBroadcastHash2(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastHash2) (event.Subscription, error) { - - logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastHash2") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ValidationBroadcastHash2) - if err := _Validation.contract.UnpackLog(event, "broadcastHash2", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ValidationBroadcastHashDataIterator is returned from FilterBroadcastHashData and is used to iterate over the raw logs and unpacked data for BroadcastHashData events raised by the Validation contract. -type ValidationBroadcastHashDataIterator struct { - Event *ValidationBroadcastHashData // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ValidationBroadcastHashDataIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastHashData) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastHashData) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ValidationBroadcastHashDataIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ValidationBroadcastHashDataIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ValidationBroadcastHashData represents a BroadcastHashData event raised by the Validation contract. -type ValidationBroadcastHashData struct { - Header []byte - ParentHash []byte - RootHash []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBroadcastHashData is a free log retrieval operation binding the contract event 0x8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c7. -// -// Solidity: event broadcastHashData(header bytes, parentHash bytes, rootHash bytes) -func (_Validation *ValidationFilterer) FilterBroadcastHashData(opts *bind.FilterOpts) (*ValidationBroadcastHashDataIterator, error) { - - logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastHashData") - if err != nil { - return nil, err - } - return &ValidationBroadcastHashDataIterator{contract: _Validation.contract, event: "broadcastHashData", logs: logs, sub: sub}, nil -} - -// WatchBroadcastHashData is a free log subscription operation binding the contract event 0x8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c7. -// -// Solidity: event broadcastHashData(header bytes, parentHash bytes, rootHash bytes) -func (_Validation *ValidationFilterer) WatchBroadcastHashData(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastHashData) (event.Subscription, error) { - - logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastHashData") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ValidationBroadcastHashData) - if err := _Validation.contract.UnpackLog(event, "broadcastHashData", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ValidationBroadcastSigIterator is returned from FilterBroadcastSig and is used to iterate over the raw logs and unpacked data for BroadcastSig events raised by the Validation contract. -type ValidationBroadcastSigIterator struct { - Event *ValidationBroadcastSig // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ValidationBroadcastSigIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastSig) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ValidationBroadcastSig) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ValidationBroadcastSigIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ValidationBroadcastSigIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ValidationBroadcastSig represents a BroadcastSig event raised by the Validation contract. -type ValidationBroadcastSig struct { - Owner common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBroadcastSig is a free log retrieval operation binding the contract event 0xba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5. -// -// Solidity: event broadcastSig(owner address) -func (_Validation *ValidationFilterer) FilterBroadcastSig(opts *bind.FilterOpts) (*ValidationBroadcastSigIterator, error) { - - logs, sub, err := _Validation.contract.FilterLogs(opts, "broadcastSig") - if err != nil { - return nil, err - } - return &ValidationBroadcastSigIterator{contract: _Validation.contract, event: "broadcastSig", logs: logs, sub: sub}, nil -} - -// WatchBroadcastSig is a free log subscription operation binding the contract event 0xba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5. -// -// Solidity: event broadcastSig(owner address) -func (_Validation *ValidationFilterer) WatchBroadcastSig(opts *bind.WatchOpts, sink chan<- *ValidationBroadcastSig) (event.Subscription, error) { - - logs, sub, err := _Validation.contract.WatchLogs(opts, "broadcastSig") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ValidationBroadcastSig) - if err := _Validation.contract.UnpackLog(event, "broadcastSig", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} diff --git a/ion-cli/contracts/validation_test.go b/ion-cli/contracts/validation_test.go index 33c7b8d..4c485be 100644 --- a/ion-cli/contracts/validation_test.go +++ b/ion-cli/contracts/validation_test.go @@ -1,16 +1,7 @@ package contract import ( - "log" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/assert" ) // Initialisation array @@ -21,121 +12,121 @@ var initValidators = []common.Address{val1, val2} var GENESISHASH = "c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28" // Test validation contract gets deployed correctly -func Test_DeployValidation(t *testing.T) { - - // Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} - blockchain := backends.NewSimulatedBackend(alloc) - - genesisHash := [32]byte{} - copy(genesisHash[:], []byte(GENESISHASH)) - - // Deploy contract - address, _, _, err := DeployValidation( - auth, - blockchain, - initValidators, - genesisHash, - ) - // commit all pending transactions - blockchain.Commit() - - if err != nil { - t.Fatalf("Failed to deploy the Validation contract: %v", err) - } - - if len(address.Bytes()) == 0 { - t.Error("Expected a valid deployment address. Received empty address byte array instead") - } - -} - -// Test inbox contract gets deployed correctly -func TestGetValidators(t *testing.T) { - - //Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} - blockchain := backends.NewSimulatedBackend(alloc) - - genesisHash := [32]byte{} - copy(genesisHash[:], []byte(GENESISHASH)) - - // Deploy contract - _, _, contract, _ := DeployValidation( - auth, - blockchain, - initValidators, - genesisHash, - ) - // commit all pending transactions - blockchain.Commit() - - validators, _ := contract.GetValidators(&bind.CallOpts{}) - assert.Equal(t, validators[0], val1) - assert.Equal(t, validators[1], val2) - -} - -// Test that the latest block returns the last submitted block hash -func Test_LatestBlock(t *testing.T) { - - //Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} - blockchain := backends.NewSimulatedBackend(alloc) - - genesisHash := [32]byte{} - copy(genesisHash[:], []byte(GENESISHASH)) - - // Deploy contract - _, _, contract, _ := DeployValidation( - auth, - blockchain, - initValidators, - genesisHash, - ) - // commit all pending transactions - blockchain.Commit() - - latestBlock, _ := contract.LatestBlock(&bind.CallOpts{}) - assert.Equal(t, latestBlock, genesisHash) -} - -// Test that the Validators is updated upon deployment -func Test_Validators(t *testing.T) { - - //Setup simulated block chain - key, _ := crypto.GenerateKey() - auth := bind.NewKeyedTransactor(key) - alloc := make(core.GenesisAlloc) - alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} - blockchain := backends.NewSimulatedBackend(alloc) - - genesisHash := [32]byte{} - copy(genesisHash[:], []byte(GENESISHASH)) - - // Deploy contract - _, _, contract, _ := DeployValidation( - auth, - blockchain, - initValidators, - genesisHash, - ) - // commit all pending transactions - blockchain.Commit() - - idx := big.NewInt(0) - validator, err := contract.Validators(&bind.CallOpts{}, idx) - if err != nil { - log.Fatalf("Failed to deploy new token contract: %v", err) - } - assert.Equal(t, initValidators[0], validator) -} +// func Test_DeployValidation(t *testing.T) { + +// // Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} +// blockchain := backends.NewSimulatedBackend(alloc) + +// genesisHash := [32]byte{} +// copy(genesisHash[:], []byte(GENESISHASH)) + +// // Deploy contract +// address, _, _, err := DeployValidation( +// auth, +// blockchain, +// initValidators, +// genesisHash, +// ) +// // commit all pending transactions +// blockchain.Commit() + +// if err != nil { +// t.Fatalf("Failed to deploy the Validation contract: %v", err) +// } + +// if len(address.Bytes()) == 0 { +// t.Error("Expected a valid deployment address. Received empty address byte array instead") +// } + +// } + +// // Test inbox contract gets deployed correctly +// func TestGetValidators(t *testing.T) { + +// //Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} +// blockchain := backends.NewSimulatedBackend(alloc) + +// genesisHash := [32]byte{} +// copy(genesisHash[:], []byte(GENESISHASH)) + +// // Deploy contract +// _, _, contract, _ := DeployValidation( +// auth, +// blockchain, +// initValidators, +// genesisHash, +// ) +// // commit all pending transactions +// blockchain.Commit() + +// validators, _ := contract.GetValidators(&bind.CallOpts{}) +// assert.Equal(t, validators[0], val1) +// assert.Equal(t, validators[1], val2) + +// } + +// // Test that the latest block returns the last submitted block hash +// func Test_LatestBlock(t *testing.T) { + +// //Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} +// blockchain := backends.NewSimulatedBackend(alloc) + +// genesisHash := [32]byte{} +// copy(genesisHash[:], []byte(GENESISHASH)) + +// // Deploy contract +// _, _, contract, _ := DeployValidation( +// auth, +// blockchain, +// initValidators, +// genesisHash, +// ) +// // commit all pending transactions +// blockchain.Commit() + +// latestBlock, _ := contract.LatestBlock(&bind.CallOpts{}) +// assert.Equal(t, latestBlock, genesisHash) +// } + +// // Test that the Validators is updated upon deployment +// func Test_Validators(t *testing.T) { + +// //Setup simulated block chain +// key, _ := crypto.GenerateKey() +// auth := bind.NewKeyedTransactor(key) +// alloc := make(core.GenesisAlloc) +// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} +// blockchain := backends.NewSimulatedBackend(alloc) + +// genesisHash := [32]byte{} +// copy(genesisHash[:], []byte(GENESISHASH)) + +// // Deploy contract +// _, _, contract, _ := DeployValidation( +// auth, +// blockchain, +// initValidators, +// genesisHash, +// ) +// // commit all pending transactions +// blockchain.Commit() + +// idx := big.NewInt(0) +// validator, err := contract.Validators(&bind.CallOpts{}, idx) +// if err != nil { +// log.Fatalf("Failed to deploy new token contract: %v", err) +// } +// assert.Equal(t, initValidators[0], validator) +// } diff --git a/package.json b/package.json index e07b9b2..0f9288f 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "coverage": "solidity-coverage", "lint": "solhint contracts/**/*.sol", "genbin": "solc --overwrite --bin ./contracts/*.sol -o abi", - "genabi": "solc --overwrite --abi ./contracts/*.sol -o abi", - "abigen": "abigen --bin=abi/Validation.bin --abi=abi/Validation.abi --pkg=validation --out=validation.go" + "genabi": "solc --overwrite --abi ./contracts/*.sol -o abi" } } diff --git a/test/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol index 05cec67..bfa4319 100644 --- a/test/PatriciaTrieTest.sol +++ b/test/PatriciaTrieTest.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.23; import "truffle/Assert.sol"; import "truffle/DeployedAddresses.sol"; -import "./libraries/PatriciaTrie.sol"; +import "../contracts/libraries/PatriciaTrie.sol"; contract PatriciaTrieTest { PatriciaTrie instance; From dd54a794f78ae230dcc12da1a14c364643f5959d Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Tue, 31 Jul 2018 10:39:54 +0100 Subject: [PATCH 089/203] ignore generated files --- .gitignore | 1 + abi/ECVerify.bin | 2 +- abi/Ion.abi | 2 +- abi/Ion.bin | 2 +- abi/Migrations.bin | 2 +- abi/PatriciaTrie.abi | 2 +- abi/PatriciaTrie.bin | 2 +- abi/RLP.bin | 2 +- abi/Recover.bin | 2 +- abi/SolUtils.bin | 2 +- abi/Validation.abi | 2 +- abi/Validation.bin | 2 +- 12 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 1e1b7f3..b5d2e58 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /build +/abi /dist /chaindata /node_modules diff --git a/abi/ECVerify.bin b/abi/ECVerify.bin index 00a99b8..238d37d 100644 --- a/abi/ECVerify.bin +++ b/abi/ECVerify.bin @@ -1 +1 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a723058203848e9525cfafe47477ce5b2a3e1938d84ef6fbf2c7bed546cf353193efee3f70029 \ No newline at end of file +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a723058208e1c8ba19be860f3aa351d762983d3a55c9767caa5d799ecd56a5235704eff9c0029 \ No newline at end of file diff --git a/abi/Ion.abi b/abi/Ion.abi index a70cf5d..78824c7 100644 --- a/abi/Ion.abi +++ b/abi/Ion.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"chains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CheckReceiptProof","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_blockHash","type":"bytes32"}],"name":"getBlockHeader","outputs":[{"name":"","type":"bytes32[3]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"CheckRootsProof","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"VerifiedTxProof","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"validation_addr","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"validators","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"validationAddr","type":"address"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckReceiptProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_txNodes","type":"bytes"},{"name":"_receiptNodes","type":"bytes"}],"name":"CheckRootsProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"},{"indexed":false,"name":"proofType","type":"uint256"}],"name":"VerifiedProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin index eb52a59..5dce528 100644 --- a/abi/Ion.bin +++ b/abi/Ion.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b5060405160208061101a8339810160405251600055610fe6806100346000396000f3006080604052600436106100a35763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663550325b581146100a857806359349832146100d25780635a0235e4146100e95780636b4f9b9d14610149578063927a32e3146101995780639a8a0592146101cf5780639e43d86b146101e4578063affd8be9146101fc578063e318df54146100d2578063fecc37c3146102ec575b600080fd5b3480156100b457600080fd5b506100c0600435610307565b60408051918252519081900360200190f35b3480156100de57600080fd5b506100e7610326565b005b3480156100f557600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526100e79482359460248035953695946064949201919081908401838280828437509497506103289650505050505050565b34801561015557600080fd5b506101616004356104bf565b6040518082606080838360005b8381101561018657818101518382015260200161016e565b5050505090500191505060405180910390f35b3480156101a557600080fd5b506101b1600435610506565b60408051938452602084019290925282820152519081900360600190f35b3480156101db57600080fd5b506100c0610527565b3480156101f057600080fd5b506100e760043561052d565b34801561020857600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102d894823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975061066c9650505050505050565b604080519115158252519081900360200190f35b3480156102f857600080fd5b506100c0600435602435610a68565b600180548290811061031557fe5b600091825260209091200154905081565b565b60606000808581805b60015481101561036d57600180548290811061034957fe5b600091825260209091200154831415610365576001915061036d565b600101610331565b8115156103c4576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b6103d56103d088610a98565b610aeb565b9550866040518082805190602001908083835b602083106104075780518252601f1990920191602091820191016103e8565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060008e815260039092529281208b51939a509850610470945061046993508a92909150811061045a57fe5b90602001906020020151610ba0565b6001610bf4565b8455855161048990610469908890600490811061045a57fe5b600185015585516104a590610469908890600590811061045a57fe5b60028501556104b48989610c82565b505050505050505050565b6104c7610f63565b50600081815260036020908152604091829020825160608101845281548152600182015492810192909252600281015492820192909252905b50919050565b60036020526000908152604090208054600182015460029092015490919083565b60005481565b600080548214156105ae576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060005b6001548110156106375760018054839190839081106105cd57fe5b600091825260209091200154141561062f576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b6001016105b2565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155565b6000808681805b6001548110156106af57600180548290811061068b57fe5b6000918252602090912001548314156106a757600191506106af565b600101610673565b811515610706576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b60008a815260026020908152604080832080548251818502810185019093528083528e948e9490936060938593919290919083018282801561076857602002820191906000526020600020905b81548152600190910190602001808311610753575b50505050509150600090505b81518110156107ad57818181518110151561078b57fe5b602090810290910101518414156107a557600192506107ad565b600101610774565b821515610804576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b600360008f60001916600019168152602001908152602001600020985073__./contracts/libraries/PatriciaTrie.s__634f7142ad8e8e8e8d600101546040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b838110156108c15781810151838201526020016108a9565b50505050905090810190601f1680156108ee5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610921578181015183820152602001610909565b50505050905090810190601f16801561094e5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610981578181015183820152602001610969565b50505050905090810190601f1680156109ae5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d60208110156109fa57600080fd5b50511515610a0457fe5b7f202dc9388a5d69cb591d889833cb0b5cd344fd68afaffc1aaffa5bfe8e79c6a18f8f60405180836000191660001916815260200182600019166000191681526020019250505060405180910390a15060019e9d5050505050505050505050505050565b600260205281600052604060002081815481101515610a8357fe5b90600052602060002001600091509150505481565b610aa0610f82565b81516000811515610ac65760408051808201909152600080825260208201529250610ae4565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610af7610f99565b6000610b0285610ce2565b1515610b0d57600080fd5b610b1685610d0c565b925082604051908082528060200260200182016040528015610b5257816020015b610b3f610f82565b815260200190600190039081610b375790505b509350610b5e85610d7c565b91505b610b6a82610db5565b15610b9857610b7882610dd4565b8482815181101515610b8657fe5b60209081029091010152600101610b61565b505050919050565b6020810151606090801515610bb457610500565b806040519080825280601f01601f191660200182016040528015610be2578160200160208202803883390190505b50915061050083600001518383610e16565b600080805b6020811015610c7a578060080285828601815181101515610c1657fe5b60209101015160029190910a7f0100000000000000000000000000000000000000000000000000000000000000918290049091027fff0000000000000000000000000000000000000000000000000000000000000016049190911790600101610bf9565b509392505050565b6000828152600260205260408120905b8154811015610cca5781548390839083908110610cab57fe5b6000918252602090912001541415610cc257600080fd5b600101610c92565b50805460018101825560009182526020909120015550565b600080826020015160001415610cfb5760009150610500565b5050515160c060009190911a101590565b600080600080600080610d1e87610ce2565b1515610d2d5760009550610d72565b8651805160001a95509350610d4187610e56565b840192506001876020015185010391505b818311610d6e57610d6283610ed6565b90920191600101610d52565b8095505b5050505050919050565b610d84610f99565b6000610d8f83610ce2565b1515610d9a57600080fd5b610da383610e56565b83519383529092016020820152919050565b6000610dbf610f82565b50508051602080820151915192015191011190565b610ddc610f82565b600080610de884610db5565b156100a35783602001519150610dfd82610ed6565b8284526020808501829052838201908601529050610ae4565b60006020601f83010484602085015b828414610e4357602084028281015190820152600190930192610e25565b6000865160200187015250505050505050565b6000806000836020015160001415610e715760009250610ae4565b50508151805160001a906080821015610e8d5760009250610ae4565b60b8821080610ea8575060c08210158015610ea8575060f882105b15610eb65760019250610ae4565b60c0821015610ecb5760b51982019250610ae4565b5060f5190192915050565b8051600090811a6080811015610eef5760019150610500565b60b8811015610f0457607e1981019150610500565b60c0811015610f2d57600183015160b76020839003016101000a9004810160b519019150610500565b60f8811015610f425760be1981019150610500565b6001929092015160f76020849003016101000a900490910160f51901919050565b6060604051908101604052806003906020820280388339509192915050565b604080518082019091526000808252602082015290565b606060405190810160405280610fad610f82565b81526020016000815250905600a165627a7a723058206a4b9844b305800bce8a0a88fdcd6658383e8dd98c6de20e69edd6739e2e64e20029 \ No newline at end of file +608060405234801561001057600080fd5b506040516020806119ba8339810160405251600255611986806100346000396000f3006080604052600436106100cf5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663261e507381146100d457806335aa2e44146101085780634b35503014610120578063528243741461014f57806353fe62e6146101ed5780637558a01a146102115780639a8a05921461027a578063affd8be9146102a1578063bec205b91461037d578063c18de0ef14610459578063e79b136c14610471578063f22a195e146104b2578063f44ff712146104c7578063f484c1f7146104dc575b600080fd5b3480156100e057600080fd5b506100ec60043561057a565b60408051600160a060020a039092168252519081900360200190f35b34801561011457600080fd5b506100ec600435610595565b34801561012c57600080fd5b5061013b6004356024356105bd565b604080519115158252519081900360200190f35b34801561015b57600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526101eb95833595369560449491939091019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506105dd9650505050505050565b005b3480156101f957600080fd5b5061013b600435600160a060020a03602435166109ac565b34801561021d57600080fd5b5060408051602060046044358181013583810280860185019096528085526101eb9583359560248035600160a060020a03169636969560649593949201929182918501908490808284375094975050933594506109cc9350505050565b34801561028657600080fd5b5061028f610c80565b60408051918252519081900360200190f35b3480156102ad57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261013b94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610c869650505050505050565b34801561038957600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261013b94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610fa69650505050505050565b34801561046557600080fd5b5061013b60043561129d565b34801561047d57600080fd5b5061048c6004356024356112b2565b604080519485526020850193909352838301919091526060830152519081900360800190f35b3480156104be57600080fd5b5061028f6112e4565b3480156104d357600080fd5b5061028f6112ea565b3480156104e857600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261013b94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506112f09650505050505050565b600560205260009081526040902054600160a060020a031681565b60008054829081106105a357fe5b600091825260209091200154600160a060020a0316905081565b600660209081526000928352604080842090915290825290205460ff1681565b600083815260046020526040812054606091829181908190819081908a9060ff161515610642576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b61065361064e8b611455565b6114a8565b975061066161064e8a611455565b9650600560008c6000191660001916815260200190815260200160002060009054906101000a9004600160a060020a0316955085945084600160a060020a03166309fbd5368c8c8c6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101561072357818101518382015260200161070b565b50505050905090810190601f1680156107505780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561078357818101518382015260200161076b565b50505050905090810190601f1680156107b05780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1580156107d257600080fd5b505af11580156107e6573d6000803e3d6000fd5b5050505061081561080e8960008151811015156107ff57fe5b9060200190602002015161155d565b60016115b7565b9350886040518082805190602001908083835b602083106108475780518252601f199092019160209182019101610828565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209250600760008c600019166000191681526020019081526020016000206000856000191660001916815260200190815260200160002060000154600101915081600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206000018190555083600760008d6000191660001916815260200190815260200160002060008560001916600019168152602001908152602001600020600101816000191690555061094461080e8960048151811015156107ff57fe5b60008c815260076020908152604080832087845290915290206002015587516109789061080e908a9060059081106107ff57fe5b60008c815260076020908152604080832087845290915290206003015561099f8b846115bf565b5050505050505050505050565b600860209081526000928352604080842090915290825290205460ff1681565b6002546000908190861415610a51576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b60008681526004602052604090205460ff1615610ab8576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b6000868152600460205260408120805460ff1916600117905591505b8351821015610b3b576000868152600860205260408120855160019290879086908110610afd57fe5b602090810291909101810151600160a060020a03168252810191909152604001600020805460ff191691151591909117905560019190910190610ad4565b5060008581526006602090815260408083208584528252808320805460ff19166001179055878352600782528083208584528252808320839055517f0b5abdd000000000000000000000000000000000000000000000000000000000815260048101888152604482018690526060602483019081528751606484015287518995600160a060020a03871695630b5abdd0958d958c958c95919490936084909301928781019202908190849084905b83811015610c01578181015183820152602001610be9565b50505050905001945050505050600060405180830381600087803b158015610c2857600080fd5b505af1158015610c3c573d6000803e3d6000fd5b50505060009687525050600560205250506040909220805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039290921691909117905550565b60025481565b6000858152600460205260408120548190879060ff161515610ce0576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b60008881526006602090815260408083208a84529091529020548890889060ff161515610d57576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b60008a81526007602090815260408083208c84528252808320600281015491517f4f7142ad000000000000000000000000000000000000000000000000000000008152606481018390526080600482019081528d5160848301528d5192995073__contracts/libraries/PatriciaTrie.sol__95634f7142ad958f958f958f9591949384936024840193604481019360a490910192918b01918190849084905b83811015610e10578181015183820152602001610df8565b50505050905090810190601f168015610e3d5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610e70578181015183820152602001610e58565b50505050905090810190601f168015610e9d5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610ed0578181015183820152602001610eb8565b50505050905090810190601f168015610efd5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610f1f57600080fd5b505af4158015610f33573d6000803e3d6000fd5b505050506040513d6020811015610f4957600080fd5b50511515610f5357fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a60005b60408051938452602084019290925282820152519081900360600190a15060019998505050505050505050565b6000858152600460205260408120548190879060ff161515611000576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b60008881526006602090815260408083208a84529091529020548890889060ff161515611077576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b60008a81526007602090815260408083208c84528252808320600381015491517f4f7142ad000000000000000000000000000000000000000000000000000000008152606481018390526080600482019081528d5160848301528d5192995073__contracts/libraries/PatriciaTrie.sol__95634f7142ad958f958f958f9591949384936024840193604481019360a490910192918b01918190849084905b83811015611130578181015183820152602001611118565b50505050905090810190601f16801561115d5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015611190578181015183820152602001611178565b50505050905090810190601f1680156111bd5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156111f05781810151838201526020016111d8565b50505050905090810190601f16801561121d5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561123f57600080fd5b505af4158015611253573d6000803e3d6000fd5b505050506040513d602081101561126957600080fd5b5051151561127357fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a6001610f79565b60046020526000908152604090205460ff1681565b600760209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b60015481565b60035481565b6000848152600460205260408120548190869060ff16151561134a576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b60008781526006602090815260408083208984529091529020548790879060ff1615156113c1576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b60008981526007602090815260408083208b8452909152902093506113e5876115e5565b6002850154146113f157fe5b6113fa866115e5565b60038501541461140657fe5b604080518a8152602081018a905260028183015290517ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870469181900360600190a150600198975050505050505050565b61145d611902565b8151600081151561148357604080518082019091526000808252602082015292506114a1565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006114b4611919565b60006114bf85611681565b15156114ca57600080fd5b6114d3856116ab565b92508260405190808252806020026020018201604052801561150f57816020015b6114fc611902565b8152602001906001900390816114f45790505b50935061151b8561171b565b91505b61152782611754565b156115555761153582611773565b848281518110151561154357fe5b6020908102909101015260010161151e565b505050919050565b6020810151606090801515611571576115b1565b806040519080825280601f01601f19166020018201604052801561159f578160200160208202803883390190505b5091506115b1836000015183836117b5565b50919050565b016020015190565b60009182526006602090815260408084209284529190529020805460ff19166001179055565b60006115ef611902565b6060806115fb85611455565b9250611606836114a8565b915061161a8260008151811015156107ff57fe5b9050806040518082805190602001908083835b6020831061164c5780518252601f19909201916020918201910161162d565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912098975050505050505050565b60008082602001516000141561169a57600091506115b1565b5050515160c060009190911a101590565b6000806000806000806116bd87611681565b15156116cc5760009550611711565b8651805160001a955093506116e0876117f5565b840192506001876020015185010391505b81831161170d5761170183611875565b909201916001016116f1565b8095505b5050505050919050565b611723611919565b600061172e83611681565b151561173957600080fd5b611742836117f5565b83519383529092016020820152919050565b600061175e611902565b50508051602080820151915192015191011190565b61177b611902565b60008061178784611754565b156100cf578360200151915061179c82611875565b82845260208085018290528382019086015290506114a1565b60006020601f83010484602085015b8284146117e2576020840282810151908201526001909301926117c4565b6000865160200187015250505050505050565b600080600083602001516000141561181057600092506114a1565b50508151805160001a90608082101561182c57600092506114a1565b60b8821080611847575060c08210158015611847575060f882105b1561185557600192506114a1565b60c082101561186a5760b519820192506114a1565b5060f5190192915050565b8051600090811a608081101561188e57600191506115b1565b60b88110156118a357607e19810191506115b1565b60c08110156118cc57600183015160b76020839003016101000a9004810160b5190191506115b1565b60f88110156118e15760be19810191506115b1565b6001929092015160f76020849003016101000a900490910160f51901919050565b604080518082019091526000808252602082015290565b60606040519081016040528061192d611902565b81526020016000815250905600436861696e206973206e6f742072656769737465726564000000000000000000a165627a7a72305820368b3f9e818bfca0b6da2350e6ca878b6474546f2b0b4bbdf24a9833141ba1de0029 \ No newline at end of file diff --git a/abi/Migrations.bin b/abi/Migrations.bin index fa2aea7..85a1083 100644 --- a/abi/Migrations.bin +++ b/abi/Migrations.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f8806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100aa5780638da5cb5b146100d5578063fdacd5761461012c575b600080fd5b34801561007357600080fd5b506100a8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610159565b005b3480156100b657600080fd5b506100bf610241565b6040518082815260200191505060405180910390f35b3480156100e157600080fd5b506100ea610247565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561013857600080fd5b506101576004803603810190808035906020019092919050505061026c565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023d578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561022457600080fd5b505af1158015610238573d6000803e3d6000fd5b505050505b5050565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102c957806001819055505b505600a165627a7a723058200a67aaa415eddfae294772076b091bbc158e31aab6b566bdf4b502ef8707113e0029 \ No newline at end of file +608060405234801561001057600080fd5b5060008054600160a060020a0319163317905561023c806100326000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630900f0108114610066578063445df0ac146100965780638da5cb5b146100bd578063fdacd576146100fb575b600080fd5b34801561007257600080fd5b5061009473ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100a257600080fd5b506100ab6101c5565b60408051918252519081900360200190f35b3480156100c957600080fd5b506100d26101cb565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561010757600080fd5b506100946004356101e7565b6000805473ffffffffffffffffffffffffffffffffffffffff163314156101c1578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b1580156101a857600080fd5b505af11580156101bc573d6000803e3d6000fd5b505050505b5050565b60015481565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff1633141561020d5760018190555b505600a165627a7a72305820a2096bb3adee99b20659755793c51b2227b1bc34c4835a86cd9f30ee2f3f88330029 \ No newline at end of file diff --git a/abi/PatriciaTrie.abi b/abi/PatriciaTrie.abi index faa17e8..b404658 100644 --- a/abi/PatriciaTrie.abi +++ b/abi/PatriciaTrie.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"},{"name":"_root","type":"bytes32"}],"name":"verifyProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"},{"name":"_root","type":"bytes32"}],"name":"verifyProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/abi/PatriciaTrie.bin b/abi/PatriciaTrie.bin index 5735ee3..19db8ec 100644 --- a/abi/PatriciaTrie.bin +++ b/abi/PatriciaTrie.bin @@ -1 +1 @@ -610d76610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600436106100575763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634f7142ad811461005c575b600080fd5b6040805160206004803580820135601f810184900484028501840190955284845261012694369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750509335945061013a9350505050565b604080519115158252519081900360200190f35b6000610144610cf7565b606060006060806000606060008060608061015e8f6104aa565b9a506101698b6104fd565b99508c98506000955061017d8e60006105b2565b9450600093505b8951841015610497576101ad8a8581518110151561019e57fe5b906020019060200201516107c9565b9750876040518082805190602001908083835b602083106101df5780518252601f1990920191602091820191016101c0565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091208c14925061021c9150505760009b50610497565b61023c8a8581518110151561022d57fe5b906020019060200201516104fd565b965086516011141561039757845186141561033c578f6040518082805190602001908083835b602083106102815780518252601f199092019160209182019101610262565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166102c488601081518110151561019e57fe5b6040518082805190602001908083835b602083106102f35780518252601f1990920191602091820191016102d4565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614156103335760019b50610497565b60009b50610497565b848681518110151561034a57fe5b90602001015160f860020a900460f860020a0260f860020a9004925061038a878461ffff1681518110151561037b57fe5b90602001906020020151610823565b985060018601955061048c565b865160021415610333576103c28760008151811015156103b357fe5b90602001906020020151610834565b91506103cf8260016105b2565b51855196019586141561044f578f6040518082805190602001908083835b6020831061040c5780518252601f1990920191602091820191016103ed565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166102c48860018151811015156103b357fe5b61045a8260016105b2565b51151561046a5760009b50610497565b61047c8760018151811015156103b357fe5b9050610489816000610897565b98505b600190930192610184565b5050505050505050505050949350505050565b6104b2610cf7565b815160008115156104d857604080518082019091526000808252602082015292506104f6565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610509610d0e565b6000610514856108f1565b151561051f57600080fd5b6105288561091b565b92508260405190808252806020026020018201604052801561056457816020015b610551610cf7565b8152602001906001900390816105495790505b5093506105708561098b565b91505b61057c826109c4565b156105aa5761058a826109e3565b848281518110151561059857fe5b60209081029091010152600101610573565b505050919050565b6060806000806105c0610d2f565b6040805160ff80825261012082019092526060916000919060208201611fe08038833901905050955060009450600093505b885184101561072a57610624898581518110151561060c57fe5b90602001015160f860020a900460f860020a02610a25565b9250878015610631575083155b156106bc578251600160f860020a03191660f860020a148061067d57508251600160f860020a0319167f0300000000000000000000000000000000000000000000000000000000000000145b156106b75760208301518651879060ff881690811061069857fe5b906020010190600160f860020a031916908160001a9053506001850194505b61071f565b82518651879060ff88169081106106cf57fe5b906020010190600160f860020a031916908160001a90535060208301518651879060ff600189011690811061070057fe5b906020010190600160f860020a031916908160001a9053506002850194505b6001909301926105f2565b8460ff166040519080825280601f01601f19166020018201604052801561075b578160200160208202803883390190505b509150600090505b8460ff168110156107bd57858181518110151561077c57fe5b90602001015160f860020a900460f860020a02828281518110151561079d57fe5b906020010190600160f860020a031916908160001a905350600101610763565b50979650505050505050565b60208101516060908015156107dd5761081d565b806040519080825280601f01601f19166020018201604052801561080b578160200160208202803883390190505b50915061081d83600001518383610a86565b50919050565b600061082e82610ac6565b92915050565b606060008061084284610b18565b151561084d57600080fd5b61085684610b41565b60408051828152601f19601f84011681016020019091529193509150818015610889578160200160208202803883390190505b5092506104f6828483610a86565b600080805b60208110156108e95780600802858286018151811015156108b957fe5b60209101015160029190910a60f860020a91829004909102600160f860020a03191604919091179060010161089c565b509392505050565b60008082602001516000141561090a576000915061081d565b5050515160c060009190911a101590565b60008060008060008061092d876108f1565b151561093c5760009550610981565b8651805160001a9550935061095087610bbe565b840192506001876020015185010391505b81831161097d5761097183610c3e565b90920191600101610961565b8095505b5050505050919050565b610993610d0e565b600061099e836108f1565b15156109a957600080fd5b6109b283610bbe565b83519383529092016020820152919050565b60006109ce610cf7565b50508051602080820151915192015191011190565b6109eb610cf7565b6000806109f7846109c4565b156100575783602001519150610a0c82610c3e565b82845260208085018290528382019086015290506104f6565b610a2d610d2f565b600080610a3b846004610ccb565b60408051808201909152600160f860020a03199190911681527f0f00000000000000000000000000000000000000000000000000000000000000949094166020850152509192915050565b60006020601f83010484602085015b828414610ab357602084028281015190820152600190930192610a95565b6000865160200187015250505050505050565b6000806000610ad484610b18565b1515610adf57600080fd5b610ae884610b41565b90925090506020811180610afa575080155b15610b0457600080fd5b806020036101000a82510492505050919050565b600080826020015160001415610b31576000915061081d565b5050515160c060009190911a1090565b6000806000806000610b5286610b18565b1515610b5d57600080fd5b8551805160001a935091506080831015610b7d5781945060019350610bb6565b60b8831015610b9b5760018660200151039350816001019450610bb6565b60b78303905080600187602001510303935080820160010194505b505050915091565b6000806000836020015160001415610bd957600092506104f6565b50508151805160001a906080821015610bf557600092506104f6565b60b8821080610c10575060c08210158015610c10575060f882105b15610c1e57600192506104f6565b60c0821015610c335760b519820192506104f6565b5060f5190192915050565b8051600090811a6080811015610c57576001915061081d565b60b8811015610c6c57607e198101915061081d565b60c0811015610c9557600183015160b76020839003016101000a9004810160b51901915061081d565b60f8811015610caa5760be198101915061081d565b6001929092015160f76020849003016101000a900490910160f51901919050565b60008160020a60ff168360f860020a900460ff16811515610ce857fe5b0460f860020a02905092915050565b604080518082019091526000808252602082015290565b606060405190810160405280610d22610cf7565b8152602001600081525090565b604080518082018252906002908290803883395091929150505600a165627a7a72305820acd21e373b0647728c7c4b49443ccc199017257ba462c48699cc1d28528f8b700029 \ No newline at end of file +610e29610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600436106100575763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634f7142ad811461005c575b600080fd5b81801561006857600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261013394369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975050933594506101479350505050565b604080519115158252519081900360200190f35b6000610151610daa565b60606000806060600060606101658b6102ad565b965061017087610300565b9550889450600093506101848a60006103b5565b9250600091505b855182101561029e576101b486838151811015156101a557fe5b906020019060200201516105cc565b6040518082805190602001908083835b602083106101e35780518252601f1990920191602091820191016101c4565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912088149250610220915050576000975061029e565b610240868381518110151561023157fe5b90602001906020020151610300565b9050805160111415610262576102588185858f610626565b9095509350610281565b805160021415610278576102588185858f610725565b6000975061029e565b8415156102935783600114975061029e565b60019091019061018b565b50505050505050949350505050565b6102b5610daa565b815160008115156102db57604080518082019091526000808252602082015292506102f9565b60208401905060408051908101604052808281526020018381525092505b5050919050565b6060600061030c610dc1565b6000610317856107bd565b151561032257600080fd5b61032b856107e7565b92508260405190808252806020026020018201604052801561036757816020015b610354610daa565b81526020019060019003908161034c5790505b50935061037385610857565b91505b61037f82610890565b156103ad5761038d826108af565b848281518110151561039b57fe5b60209081029091010152600101610376565b505050919050565b6060806000806103c3610de2565b6040805160ff80825261012082019092526060916000919060208201611fe08038833901905050955060009450600093505b885184101561052d57610427898581518110151561040f57fe5b90602001015160f860020a900460f860020a026108f1565b9250878015610434575083155b156104bf578251600160f860020a03191660f860020a148061048057508251600160f860020a0319167f0300000000000000000000000000000000000000000000000000000000000000145b156104ba5760208301518651879060ff881690811061049b57fe5b906020010190600160f860020a031916908160001a9053506001850194505b610522565b82518651879060ff88169081106104d257fe5b906020010190600160f860020a031916908160001a90535060208301518651879060ff600189011690811061050357fe5b906020010190600160f860020a031916908160001a9053506002850194505b6001909301926103f5565b8460ff166040519080825280601f01601f19166020018201604052801561055e578160200160208202803883390190505b509150600090505b8460ff168110156105c057858181518110151561057f57fe5b90602001015160f860020a900460f860020a0282828151811015156105a057fe5b906020010190600160f860020a031916908160001a905350600101610566565b50979650505050505050565b60208101516060908015156105e057610620565b806040519080825280601f01601f19166020018201604052801561060e578160200160208202803883390190505b50915061062083600001518383610952565b50919050565b6000806000610633610daa565b6000865188141561067657600061065b876106568c60108151811015156101a557fe5b610992565b610666576000610669565b60015b90955060ff169350610719565b868881518110151561068457fe5b90602001015160f860020a900460f860020a0260f860020a90049250888361ffff168151811015156106b257fe5b90602001906020020151915060018801975060206106cf836105cc565b5110156106eb576106e282898989610a54565b98509050610712565b61070f898461ffff1681518110151561070057fe5b90602001906020020151610aab565b90505b8088945094505b50505094509492505050565b600080606080600061074e89600081518110151561073f57fe5b90602001906020020151610abc565b925061075b8360016103b5565b51875198019788141561078057600061065b876106568c600181518110151561073f57fe5b61078b8360016103b5565b51151561079e5760009450849350610719565b6107b089600181518110151561073f57fe5b915061070f826000610b1f565b6000808260200151600014156107d65760009150610620565b5050515160c060009190911a101590565b6000806000806000806107f9876107bd565b1515610808576000955061084d565b8651805160001a9550935061081c87610b79565b840192506001876020015185010391505b8183116108495761083d83610bf9565b9092019160010161082d565b8095505b5050505050919050565b61085f610dc1565b600061086a836107bd565b151561087557600080fd5b61087e83610b79565b83519383529092016020820152919050565b600061089a610daa565b50508051602080820151915192015191011190565b6108b7610daa565b6000806108c384610890565b1561005757836020015191506108d882610bf9565b82845260208085018290528382019086015290506102f9565b6108f9610de2565b600080610907846004610c86565b60408051808201909152600160f860020a03199190911681527f0f00000000000000000000000000000000000000000000000000000000000000949094166020850152509192915050565b60006020601f83010484602085015b82841461097f57602084028281015190820152600190930192610961565b6000865160200187015250505050505050565b6000816040518082805190602001908083835b602083106109c45780518252601f1990920191602091820191016109a5565b51815160209384036101000a6000190180199092169116179052604051919093018190038120885190955088945090928392508401908083835b60208310610a1d5780518252601f1990920191602091820191016109fe565b5181516020939093036101000a60001901801990911692169190911790526040519201829003909120939093149695505050505050565b6000806060610a6287610300565b9050805160111415610a8357610a7a81878787610626565b92509250610aa1565b805160021415610a9957610a7a81878787610725565b600092508291505b5094509492505050565b6000610ab682610cb2565b92915050565b6060600080610aca84610d04565b1515610ad557600080fd5b610ade84610d2d565b60408051828152601f19601f84011681016020019091529193509150818015610b11578160200160208202803883390190505b5092506102f9828483610952565b600080805b6020811015610b71578060080285828601815181101515610b4157fe5b60209101015160029190910a60f860020a91829004909102600160f860020a031916049190911790600101610b24565b509392505050565b6000806000836020015160001415610b9457600092506102f9565b50508151805160001a906080821015610bb057600092506102f9565b60b8821080610bcb575060c08210158015610bcb575060f882105b15610bd957600192506102f9565b60c0821015610bee5760b519820192506102f9565b5060f5190192915050565b8051600090811a6080811015610c125760019150610620565b60b8811015610c2757607e1981019150610620565b60c0811015610c5057600183015160b76020839003016101000a9004810160b519019150610620565b60f8811015610c655760be1981019150610620565b6001929092015160f76020849003016101000a900490910160f51901919050565b60008160020a60ff168360f860020a900460ff16811515610ca357fe5b0460f860020a02905092915050565b6000806000610cc084610d04565b1515610ccb57600080fd5b610cd484610d2d565b90925090506020811180610ce6575080155b15610cf057600080fd5b806020036101000a82510492505050919050565b600080826020015160001415610d1d5760009150610620565b5050515160c060009190911a1090565b6000806000806000610d3e86610d04565b1515610d4957600080fd5b8551805160001a935091506080831015610d695781945060019350610da2565b60b8831015610d875760018660200151039350816001019450610da2565b60b78303905080600187602001510303935080820160010194505b505050915091565b604080518082019091526000808252602082015290565b606060405190810160405280610dd5610daa565b8152602001600081525090565b604080518082018252906002908290803883395091929150505600a165627a7a72305820e05e82a0edbba09d7c85c9a3ac2c0b233ed4e4ecd2fd0413588c2ae2a1395cbd0029 \ No newline at end of file diff --git a/abi/RLP.bin b/abi/RLP.bin index 1bc8155..9191f9f 100644 --- a/abi/RLP.bin +++ b/abi/RLP.bin @@ -1 +1 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820c3ab6c04b83b440abb681106d8efa4dc64fdbfaa7cd538c013391b28f976a1590029 \ No newline at end of file +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820da2966cf4d37b9763adceaf5dfb029ef12949f9118e5d09f19bcacd63d179dc10029 \ No newline at end of file diff --git a/abi/Recover.bin b/abi/Recover.bin index 4a249fb..f9cf0b2 100644 --- a/abi/Recover.bin +++ b/abi/Recover.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b11806100606000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b0e7308f1461005c578063d09ca90414610151578063fdace1be14610200575b600080fd5b34801561006857600080fd5b5061014f600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610277565b005b34801561015d57600080fd5b506101fe600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061055e565b005b34801561020c57600080fd5b506102756004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610840565b005b60008060608060608060606000808b5198508b6040518082805190602001908083835b6020831015156102bf578051825260208201915060208101905060208303925061029a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156103635781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f19166020018201604052801561039a5781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156103d15781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f1916602001820160405280156104085781602001602082028038833980820191505090505b509350610419878d60008a516108b6565b600260218801600260208e016004610bb8fa5061043c868d608c8c0389516108b6565b600160208701600160208d016004610bb8fa5061045f848d602a8c0387516108b6565b61046a878786610971565b9250826040518082805190602001908083835b6020831015156104a2578051825260208201915060208101905060208303925061047d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506104e1858d606b8c0388516108b6565b6104eb8286610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050505050505050565b600080606080856040518082805190602001908083835b60208310151561059a5780518252602082019150602081019050602083039250610575565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093506105d38486610a1d565b925060206040519080825280601f01601f1916602001820160405280156106095781602001602082028038833980820191505090505b50915060206040519080825280601f01601f1916602001820160405280156106405781602001602082028038833980820191505090505b5090506106518287600460206108b6565b61065f8187605b60206108b6565b7f8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c786838360405180806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106cb5780820151818401526020810190506106b0565b50505050905090810190601f1680156106f85780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b83811015610731578082015181840152602081019050610716565b50505050905090810190601f16801561075e5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b8381101561079757808201518184015260208101905061077c565b50505050905090810190601f1680156107c45780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a17fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a583604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b600061084c8383610a1d565b90507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b60008090505b8181101561096a57838184018151811015156108d457fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002858281518110151561092d57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506108bc565b5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156109d85781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b60008060008060418551141515610a3357600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff161015610a5e57601b810190505b601b8160ff161480610a735750601c8160ff16145b1515610a7e57600080fd5b610a8a86828585610a95565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9250805191505060011515821515141515610ad857600080fd5b80925050509493505050505600a165627a7a72305820a11a9087d66f1111b554ccbcf88a2ff4ea9ae3f00754d8e38ca36404c16b46740029 \ No newline at end of file +608060405234801561001057600080fd5b5060008054600160a060020a0319163317905561099b806100326000396000f3006080604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b0e7308f811461005b578063d09ca90414610132578063fdace1be146101c9575b600080fd5b34801561006757600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261013094369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506102279650505050505050565b005b34801561013e57600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261013094369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506104929650505050505050565b3480156101d557600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526101309583359536956044949193909101919081908401838280828437509497506107179650505050505050565b60008060608060608060606000808b5198508b6040518082805190602001908083835b602083106102695780518252601f19909201916020918201910161024a565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208083529351939d507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf0195509083900301925050a1608d89036040519080825280601f01601f1916602001820160405280156102f5578160200160208202803883390190505b5060408051601f808252818301909252919850602082016103e08038833950506040805160418082526080820190925292985090506020820161082080388339505060408051602a808252606082019092529297509050602082016105408038833901905050935061036b878d60008a51610775565b600260218801600260208e016004610bb8fa5061038e868d608c8c038951610775565b600160208701600160208d016004610bb8fa506103b1848d602a8c038751610775565b6103bc878786610828565b9250826040518082805190602001908083835b602083106103ee5780518252601f1990920191602091820191016103cf565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020915061042d858d606b8c038851610775565b61043782866108bf565b6040805173ffffffffffffffffffffffffffffffffffffffff8316815290519192507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5919081900360200190a1505050505050505050505050565b600080606080856040518082805190602001908083835b602083106104c85780518252601f1990920191602091820191016104a9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020935061050184866108bf565b604080516020808252818301909252919450808201610400803883395050604080516020808252818301909252929450905080820161040080388339019050509050610551828760046020610775565b61055f8187605b6020610775565b7f8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c786838360405180806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156105c85781810151838201526020016105b0565b50505050905090810190601f1680156105f55780820380516001836020036101000a031916815260200191505b50848103835286518152865160209182019188019080838360005b83811015610628578181015183820152602001610610565b50505050905090810190601f1680156106555780820380516001836020036101000a031916815260200191505b50848103825285518152855160209182019187019080838360005b83811015610688578181015183820152602001610670565b50505050905090810190601f1680156106b55780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a16040805173ffffffffffffffffffffffffffffffffffffffff8516815290517fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a59181900360200190a1505050505050565b600061072383836108bf565b6040805173ffffffffffffffffffffffffffffffffffffffff8316815290519192507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5919081900360200190a1505050565b60005b81811015610821578381840181518110151561079057fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f01000000000000000000000000000000000000000000000000000000000000000285828151811015156107e957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101610778565b5050505050565b82518251825160408051600284860180850191820180845260206021909301601f191684018301909452606096959491860193919260229091019190879082801561087d578160200160208202803883390190505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa509a9950505050505050505050565b600080600080845160411415156108d557600080fd5b50505060208201516040830151606084015160001a601b60ff821610156108fa57601b015b8060ff16601b148061090f57508060ff16601c145b151561091a57600080fd5b61092686828585610930565b9695505050505050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9051909250905060018215151461092657600080fd00a165627a7a7230582038abea0db89b85cbff9e376e2e5f70ae6b7a141a79352619d845b07f7c4ce8eb0029 \ No newline at end of file diff --git a/abi/SolUtils.bin b/abi/SolUtils.bin index fb34f75..874e86f 100644 --- a/abi/SolUtils.bin +++ b/abi/SolUtils.bin @@ -1 +1 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820602c8fca3c4100237db35e105165edbc9431f78a5900fd59cd51162ef1d541010029 \ No newline at end of file +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820fe8ba14d3aab8b6b7911647c344b383a91b505bf83660943ef60ef4f2d2c3d1e0029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi index 670dcf1..056ae8a 100644 --- a/abi/Validation.abi +++ b/abi/Validation.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"blockNumber","type":"uint256"}],"name":"GetBlock","outputs":[{"name":"_blockHash","type":"bytes32"},{"name":"_prevBlockHash","type":"bytes32"},{"name":"_blockHeight","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LatestBlock","outputs":[{"name":"_latestBlock","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"m_blockheaders","outputs":[{"name":"blockHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GetValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_validators","type":"address[]"},{"name":"genesisHash","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"InitChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin index 17b549d..229a99b 100644 --- a/abi/Validation.bin +++ b/abi/Validation.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051610b26380380610b2683398101806040528101908080518201929190602001805190602001909291905050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600090505b825181101561018957600183828151811015156100a057fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600160056000858481518110151561012157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610087565b816003816000191690555081600460008081526020019081526020016000206000018160001916905550505050610961806101c56000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806340ce4b6c146100725780639db7d9f7146100d1578063aae933e414610104578063c4cf3ed6146101f9578063d405af3d14610251575b600080fd5b34801561007e57600080fd5b5061009d600480360381019080803590602001909291905050506102bd565b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390f35b3480156100dd57600080fd5b506100e6610300565b60405180826000191660001916815260200191505060405180910390f35b34801561011057600080fd5b506101f7600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061030a565b005b34801561020557600080fd5b50610224600480360381019080803590602001909291905050506106d9565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b34801561025d57600080fd5b506102666106fd565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102a957808201518184015260208101905061028e565b505050509050019250505060405180910390f35b6000806000600460008581526020019081526020016000206000015492506004600085815260200190815260200160002060010154915060025490509193909250565b6000600354905090565b600080600060608060608060606000806103258d600461078b565b9950600354600019168a600019161415156103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b8c5198508c6040518082805190602001908083835b6020831015156103e257805182526020820191506020810190506020830392506103bd565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902097507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018860405180826000191660001916815260200191505060405180910390a1608d89036040519080825280601f01601f1916602001820160405280156104865781602001602082028038833980820191505090505b509650601f6040519080825280601f01601f1916602001820160405280156104bd5781602001602082028038833980820191505090505b50955060416040519080825280601f01601f1916602001820160405280156104f45781602001602082028038833980820191505090505b509450602a6040519080825280601f01601f19166020018201604052801561052b5781602001602082028038833980820191505090505b50935061053a878e600061079f565b600260218801600260208f016004610bb8fa5061055b868e608c8c0361079f565b600160208701600160208e016004610bb8fa5061057c848e602a8c0361079f565b6105878787866107c1565b9250826040518082805190602001908083835b6020831015156105bf578051825260208201915060208101905060208303925061059a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506105fc858e606b8c0361079f565b610606828661086d565b905087600381600019169055506002600081548092919060010191905055508760046000600254815260200190815260200160002060000181600019169055508960046000600254815260200190815260200160002060010181600019169055507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050505050505050505050565b60046020528060005260406000206000915090508060000154908060010154905082565b6060600180548060200260200160405190810160405280929190818152602001828054801561078157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610737575b5050505050905090565b600060208201915081830151905092915050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b606060008060008060008060608a5196508951955060208701945088519350600260208888010101925060028487890101019150816040519080825280601f01601f1916602001820160405280156108285781602001602082028038833980820191505090505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa50809750505050505050509392505050565b6000806000806041855114151561088357600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff1610156108ae57601b810190505b601b8160ff1614806108c35750601c8160ff16145b15156108ce57600080fd5b6108da868285856108e5565b935050505092915050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561092857600080fd5b80925050509493505050505600a165627a7a72305820973e5581400dbd7323a6c24b4d15a6562cc416ea892009c1044fe9318ebb62c90029 \ No newline at end of file +608060405234801561001057600080fd5b50604051602080610f75833981016040525160008054600160a060020a03191633179055600155610f2f806100466000396000f3006080604052600436106100985763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166309fbd536811461009d5780630b5abdd01461013b5780634b3550301461019757806353fe62e6146101c657806359a53331146101f75780638da5cb5b14610221578063927a32e31461025f5780639a8a059214610295578063c18de0ef146102aa575b600080fd5b3480156100a957600080fd5b5060408051602060046024803582810135601f810185900485028601850190965285855261013995833595369560449491939091019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506102c29650505050505050565b005b34801561014757600080fd5b5060408051602060046024803582810135848102808701860190975280865261013996843596369660449591949091019291829185019084908082843750949750509335945061062a9350505050565b3480156101a357600080fd5b506101b26004356024356107bd565b604080519115158252519081900360200190f35b3480156101d257600080fd5b506101b260043573ffffffffffffffffffffffffffffffffffffffff602435166107dd565b34801561020357600080fd5b5061020f6004356107fd565b60408051918252519081900360200190f35b34801561022d57600080fd5b5061023661080f565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561026b57600080fd5b5061027760043561082b565b60408051938452602084019290925282820152519081900360600190f35b3480156102a157600080fd5b5061020f61084c565b3480156102b657600080fd5b506101b2600435610852565b600083815260036020526040812054606091829181908190889060ff161515610335576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61034661034189610867565b6108ba565b955061035461034188610867565b9450600093505b84518410156104c55783600c1415610372576104ba565b610392858581518110151561038357fe5b9060200190602002015161096f565b6040518082805190602001908083835b602083106103c15780518252601f1990920191602091820191016103a2565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916610403878681518110151561038357fe5b6040518082805190602001908083835b602083106104325780518252601f199092019160209182019101610413565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019161415156104ba576040805160e560020a62461bcd02815260206004820152601a60248201527f486561646572206461746120646f65736e2774206d6174636821000000000000604482015290519081900360640190fd5b60019093019261035b565b6104e16104da87600081518110151561038357fe5b60016109c9565b60008a815260056020526040902060010154909350831461054c576040805160e560020a62461bcd02815260206004820152601c60248201527f4e6f74206368696c64206f662070726576696f757320626c6f636b2100000000604482015290519081900360640190fd5b866040518082805190602001908083835b6020831061057c5780518252601f19909201916020918201910161055d565b51815160209384036101000a60001901801990921691161790526040805192909401829003822080835293519397507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf0195509083900301925050a16105f3896105ed87600c81518110151561038357fe5b8a6109d1565b6000898152600560205260409020805460019081018255810183905560020183905561061f8983610b52565b505050505050505050565b6001546000908414156106ad576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b60008481526003602052604090205460ff1615610714576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b506000838152600360205260408120805460ff191660011790555b825181101561079f57600084815260066020526040812084516001929086908590811061075857fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020805460ff191691151591909117905560010161072f565b50600092835260056020526040832092835560019092019190915550565b600460209081526000928352604080842090915290825290205460ff1681565b600660209081526000928352604080842090915290825290205460ff1681565b60026020526000908152604090205481565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60056020526000908152604090208054600182015460029092015490919083565b60015481565b60036020526000908152604090205460ff1681565b61086f610ecb565b8151600081151561089557604080518082019091526000808252602082015292506108b3565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006108c6610ee2565b60006108d185610b78565b15156108dc57600080fd5b6108e585610ba2565b92508260405190808252806020026020018201604052801561092157816020015b61090e610ecb565b8152602001906001900390816109065790505b50935061092d85610c12565b91505b61093982610c4b565b156109675761094782610c6a565b848281518110151561095557fe5b60209081029091010152600101610930565b505050919050565b6020810151606090801515610983576109c3565b806040519080825280601f01601f1916602001820160405280156109b1578160200160208202803883390190505b5091506109c383600001518383610cac565b50919050565b016020015190565b604080516041808252608082019092526060916000918291602082016108208038833901905050925084519150610a0c838660418503610cec565b610a72846040518082805190602001908083835b60208310610a3f5780518252601f199092019160209182019101610a20565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902084610d0e565b600087815260066020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205490915060ff161515600114610b01576040805160e560020a62461bcd02815260206004820152601760248201527f5369676e6572206e6f7420612076616c696461746f7221000000000000000000604482015290519081900360640190fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8316815290517f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef439181900360200190a1505050505050565b60009182526004602090815260408084209284529190529020805460ff19166001179055565b600080826020015160001415610b9157600091506109c3565b5050515160c060009190911a101590565b600080600080600080610bb487610b78565b1515610bc35760009550610c08565b8651805160001a95509350610bd787610d7f565b840192506001876020015185010391505b818311610c0457610bf883610dff565b90920191600101610be8565b8095505b5050505050919050565b610c1a610ee2565b6000610c2583610b78565b1515610c3057600080fd5b610c3983610d7f565b83519383529092016020820152919050565b6000610c55610ecb565b50508051602080820151915192015191011190565b610c72610ecb565b600080610c7e84610c4b565b156100985783602001519150610c9382610dff565b82845260208085018290528382019086015290506108b3565b60006020601f83010484602085015b828414610cd957602084028281015190820152600190930192610cbb565b6000865160200187015250505050505050565b6000835190508160200191508060208501828486016004610bb8fa5050505050565b60008060008084516041141515610d2457600080fd5b50505060208201516040830151606084015160001a601b60ff82161015610d4957601b015b8060ff16601b1480610d5e57508060ff16601c145b1515610d6957600080fd5b610d7586828585610e8c565b9695505050505050565b6000806000836020015160001415610d9a57600092506108b3565b50508151805160001a906080821015610db657600092506108b3565b60b8821080610dd1575060c08210158015610dd1575060f882105b15610ddf57600192506108b3565b60c0821015610df45760b519820192506108b3565b5060f5190192915050565b8051600090811a6080811015610e1857600191506109c3565b60b8811015610e2d57607e19810191506109c3565b60c0811015610e5657600183015160b76020839003016101000a9004810160b5190191506109c3565b60f8811015610e6b5760be19810191506109c3565b6001929092015160f76020849003016101000a900490910160f51901919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa90519092509050600182151514610d7557600080fd5b604080518082019091526000808252602082015290565b606060405190810160405280610ef6610ecb565b81526020016000815250905600a165627a7a72305820ab6bccffa86e84dabc81baf91b02d1cf2a595b879d1bc27c37bec5670a2ce0710029 \ No newline at end of file From d94179b4f9ff062e9e17033a5aba979cbdb76fe5 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Tue, 31 Jul 2018 10:40:08 +0100 Subject: [PATCH 090/203] ignore generated files --- abi/ECVerify.abi | 1 - abi/ECVerify.bin | 1 - abi/Ion.abi | 1 - abi/Ion.bin | 1 - abi/Migrations.abi | 1 - abi/Migrations.bin | 1 - abi/PatriciaTrie.abi | 1 - abi/PatriciaTrie.bin | 1 - abi/RLP.abi | 1 - abi/RLP.bin | 1 - abi/Recover.abi | 1 - abi/Recover.bin | 1 - abi/SolUtils.abi | 1 - abi/SolUtils.bin | 1 - abi/Validation.abi | 1 - abi/Validation.bin | 1 - 16 files changed, 16 deletions(-) delete mode 100644 abi/ECVerify.abi delete mode 100644 abi/ECVerify.bin delete mode 100644 abi/Ion.abi delete mode 100644 abi/Ion.bin delete mode 100644 abi/Migrations.abi delete mode 100644 abi/Migrations.bin delete mode 100644 abi/PatriciaTrie.abi delete mode 100644 abi/PatriciaTrie.bin delete mode 100644 abi/RLP.abi delete mode 100644 abi/RLP.bin delete mode 100644 abi/Recover.abi delete mode 100644 abi/Recover.bin delete mode 100644 abi/SolUtils.abi delete mode 100644 abi/SolUtils.bin delete mode 100644 abi/Validation.abi delete mode 100644 abi/Validation.bin diff --git a/abi/ECVerify.abi b/abi/ECVerify.abi deleted file mode 100644 index 0637a08..0000000 --- a/abi/ECVerify.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/abi/ECVerify.bin b/abi/ECVerify.bin deleted file mode 100644 index 238d37d..0000000 --- a/abi/ECVerify.bin +++ /dev/null @@ -1 +0,0 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a723058208e1c8ba19be860f3aa351d762983d3a55c9767caa5d799ecd56a5235704eff9c0029 \ No newline at end of file diff --git a/abi/Ion.abi b/abi/Ion.abi deleted file mode 100644 index 78824c7..0000000 --- a/abi/Ion.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"validation_addr","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"validators","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"validationAddr","type":"address"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckReceiptProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_txNodes","type":"bytes"},{"name":"_receiptNodes","type":"bytes"}],"name":"CheckRootsProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"},{"indexed":false,"name":"proofType","type":"uint256"}],"name":"VerifiedProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin deleted file mode 100644 index 5dce528..0000000 --- a/abi/Ion.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b506040516020806119ba8339810160405251600255611986806100346000396000f3006080604052600436106100cf5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663261e507381146100d457806335aa2e44146101085780634b35503014610120578063528243741461014f57806353fe62e6146101ed5780637558a01a146102115780639a8a05921461027a578063affd8be9146102a1578063bec205b91461037d578063c18de0ef14610459578063e79b136c14610471578063f22a195e146104b2578063f44ff712146104c7578063f484c1f7146104dc575b600080fd5b3480156100e057600080fd5b506100ec60043561057a565b60408051600160a060020a039092168252519081900360200190f35b34801561011457600080fd5b506100ec600435610595565b34801561012c57600080fd5b5061013b6004356024356105bd565b604080519115158252519081900360200190f35b34801561015b57600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526101eb95833595369560449491939091019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506105dd9650505050505050565b005b3480156101f957600080fd5b5061013b600435600160a060020a03602435166109ac565b34801561021d57600080fd5b5060408051602060046044358181013583810280860185019096528085526101eb9583359560248035600160a060020a03169636969560649593949201929182918501908490808284375094975050933594506109cc9350505050565b34801561028657600080fd5b5061028f610c80565b60408051918252519081900360200190f35b3480156102ad57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261013b94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610c869650505050505050565b34801561038957600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261013b94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610fa69650505050505050565b34801561046557600080fd5b5061013b60043561129d565b34801561047d57600080fd5b5061048c6004356024356112b2565b604080519485526020850193909352838301919091526060830152519081900360800190f35b3480156104be57600080fd5b5061028f6112e4565b3480156104d357600080fd5b5061028f6112ea565b3480156104e857600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261013b94823594602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506112f09650505050505050565b600560205260009081526040902054600160a060020a031681565b60008054829081106105a357fe5b600091825260209091200154600160a060020a0316905081565b600660209081526000928352604080842090915290825290205460ff1681565b600083815260046020526040812054606091829181908190819081908a9060ff161515610642576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b61065361064e8b611455565b6114a8565b975061066161064e8a611455565b9650600560008c6000191660001916815260200190815260200160002060009054906101000a9004600160a060020a0316955085945084600160a060020a03166309fbd5368c8c8c6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101561072357818101518382015260200161070b565b50505050905090810190601f1680156107505780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561078357818101518382015260200161076b565b50505050905090810190601f1680156107b05780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1580156107d257600080fd5b505af11580156107e6573d6000803e3d6000fd5b5050505061081561080e8960008151811015156107ff57fe5b9060200190602002015161155d565b60016115b7565b9350886040518082805190602001908083835b602083106108475780518252601f199092019160209182019101610828565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209250600760008c600019166000191681526020019081526020016000206000856000191660001916815260200190815260200160002060000154600101915081600760008d60001916600019168152602001908152602001600020600085600019166000191681526020019081526020016000206000018190555083600760008d6000191660001916815260200190815260200160002060008560001916600019168152602001908152602001600020600101816000191690555061094461080e8960048151811015156107ff57fe5b60008c815260076020908152604080832087845290915290206002015587516109789061080e908a9060059081106107ff57fe5b60008c815260076020908152604080832087845290915290206003015561099f8b846115bf565b5050505050505050505050565b600860209081526000928352604080842090915290825290205460ff1681565b6002546000908190861415610a51576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b60008681526004602052604090205460ff1615610ab8576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b6000868152600460205260408120805460ff1916600117905591505b8351821015610b3b576000868152600860205260408120855160019290879086908110610afd57fe5b602090810291909101810151600160a060020a03168252810191909152604001600020805460ff191691151591909117905560019190910190610ad4565b5060008581526006602090815260408083208584528252808320805460ff19166001179055878352600782528083208584528252808320839055517f0b5abdd000000000000000000000000000000000000000000000000000000000815260048101888152604482018690526060602483019081528751606484015287518995600160a060020a03871695630b5abdd0958d958c958c95919490936084909301928781019202908190849084905b83811015610c01578181015183820152602001610be9565b50505050905001945050505050600060405180830381600087803b158015610c2857600080fd5b505af1158015610c3c573d6000803e3d6000fd5b50505060009687525050600560205250506040909220805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039290921691909117905550565b60025481565b6000858152600460205260408120548190879060ff161515610ce0576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b60008881526006602090815260408083208a84529091529020548890889060ff161515610d57576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b60008a81526007602090815260408083208c84528252808320600281015491517f4f7142ad000000000000000000000000000000000000000000000000000000008152606481018390526080600482019081528d5160848301528d5192995073__contracts/libraries/PatriciaTrie.sol__95634f7142ad958f958f958f9591949384936024840193604481019360a490910192918b01918190849084905b83811015610e10578181015183820152602001610df8565b50505050905090810190601f168015610e3d5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610e70578181015183820152602001610e58565b50505050905090810190601f168015610e9d5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015610ed0578181015183820152602001610eb8565b50505050905090810190601f168015610efd5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610f1f57600080fd5b505af4158015610f33573d6000803e3d6000fd5b505050506040513d6020811015610f4957600080fd5b50511515610f5357fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a60005b60408051938452602084019290925282820152519081900360600190a15060019998505050505050505050565b6000858152600460205260408120548190879060ff161515611000576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b60008881526006602090815260408083208a84529091529020548890889060ff161515611077576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b60008a81526007602090815260408083208c84528252808320600381015491517f4f7142ad000000000000000000000000000000000000000000000000000000008152606481018390526080600482019081528d5160848301528d5192995073__contracts/libraries/PatriciaTrie.sol__95634f7142ad958f958f958f9591949384936024840193604481019360a490910192918b01918190849084905b83811015611130578181015183820152602001611118565b50505050905090810190601f16801561115d5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015611190578181015183820152602001611178565b50505050905090810190601f1680156111bd5780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b838110156111f05781810151838201526020016111d8565b50505050905090810190601f16801561121d5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561123f57600080fd5b505af4158015611253573d6000803e3d6000fd5b505050506040513d602081101561126957600080fd5b5051151561127357fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468a8a6001610f79565b60046020526000908152604090205460ff1681565b600760209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b60015481565b60035481565b6000848152600460205260408120548190869060ff16151561134a576040805160e560020a62461bcd028152602060048201526017602482015260008051602061193b833981519152604482015290519081900360640190fd5b60008781526006602090815260408083208984529091529020548790879060ff1615156113c1576040805160e560020a62461bcd02815260206004820152601e60248201527f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e0000604482015290519081900360640190fd5b60008981526007602090815260408083208b8452909152902093506113e5876115e5565b6002850154146113f157fe5b6113fa866115e5565b60038501541461140657fe5b604080518a8152602081018a905260028183015290517ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870469181900360600190a150600198975050505050505050565b61145d611902565b8151600081151561148357604080518082019091526000808252602082015292506114a1565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006114b4611919565b60006114bf85611681565b15156114ca57600080fd5b6114d3856116ab565b92508260405190808252806020026020018201604052801561150f57816020015b6114fc611902565b8152602001906001900390816114f45790505b50935061151b8561171b565b91505b61152782611754565b156115555761153582611773565b848281518110151561154357fe5b6020908102909101015260010161151e565b505050919050565b6020810151606090801515611571576115b1565b806040519080825280601f01601f19166020018201604052801561159f578160200160208202803883390190505b5091506115b1836000015183836117b5565b50919050565b016020015190565b60009182526006602090815260408084209284529190529020805460ff19166001179055565b60006115ef611902565b6060806115fb85611455565b9250611606836114a8565b915061161a8260008151811015156107ff57fe5b9050806040518082805190602001908083835b6020831061164c5780518252601f19909201916020918201910161162d565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912098975050505050505050565b60008082602001516000141561169a57600091506115b1565b5050515160c060009190911a101590565b6000806000806000806116bd87611681565b15156116cc5760009550611711565b8651805160001a955093506116e0876117f5565b840192506001876020015185010391505b81831161170d5761170183611875565b909201916001016116f1565b8095505b5050505050919050565b611723611919565b600061172e83611681565b151561173957600080fd5b611742836117f5565b83519383529092016020820152919050565b600061175e611902565b50508051602080820151915192015191011190565b61177b611902565b60008061178784611754565b156100cf578360200151915061179c82611875565b82845260208085018290528382019086015290506114a1565b60006020601f83010484602085015b8284146117e2576020840282810151908201526001909301926117c4565b6000865160200187015250505050505050565b600080600083602001516000141561181057600092506114a1565b50508151805160001a90608082101561182c57600092506114a1565b60b8821080611847575060c08210158015611847575060f882105b1561185557600192506114a1565b60c082101561186a5760b519820192506114a1565b5060f5190192915050565b8051600090811a608081101561188e57600191506115b1565b60b88110156118a357607e19810191506115b1565b60c08110156118cc57600183015160b76020839003016101000a9004810160b5190191506115b1565b60f88110156118e15760be19810191506115b1565b6001929092015160f76020849003016101000a900490910160f51901919050565b604080518082019091526000808252602082015290565b60606040519081016040528061192d611902565b81526020016000815250905600436861696e206973206e6f742072656769737465726564000000000000000000a165627a7a72305820368b3f9e818bfca0b6da2350e6ca878b6474546f2b0b4bbdf24a9833141ba1de0029 \ No newline at end of file diff --git a/abi/Migrations.abi b/abi/Migrations.abi deleted file mode 100644 index 79cea67..0000000 --- a/abi/Migrations.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"new_address","type":"address"}],"name":"upgrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"last_completed_migration","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"completed","type":"uint256"}],"name":"setCompleted","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] \ No newline at end of file diff --git a/abi/Migrations.bin b/abi/Migrations.bin deleted file mode 100644 index 85a1083..0000000 --- a/abi/Migrations.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b5060008054600160a060020a0319163317905561023c806100326000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630900f0108114610066578063445df0ac146100965780638da5cb5b146100bd578063fdacd576146100fb575b600080fd5b34801561007257600080fd5b5061009473ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100a257600080fd5b506100ab6101c5565b60408051918252519081900360200190f35b3480156100c957600080fd5b506100d26101cb565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561010757600080fd5b506100946004356101e7565b6000805473ffffffffffffffffffffffffffffffffffffffff163314156101c1578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b1580156101a857600080fd5b505af11580156101bc573d6000803e3d6000fd5b505050505b5050565b60015481565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff1633141561020d5760018190555b505600a165627a7a72305820a2096bb3adee99b20659755793c51b2227b1bc34c4835a86cd9f30ee2f3f88330029 \ No newline at end of file diff --git a/abi/PatriciaTrie.abi b/abi/PatriciaTrie.abi deleted file mode 100644 index b404658..0000000 --- a/abi/PatriciaTrie.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"},{"name":"_root","type":"bytes32"}],"name":"verifyProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/abi/PatriciaTrie.bin b/abi/PatriciaTrie.bin deleted file mode 100644 index 19db8ec..0000000 --- a/abi/PatriciaTrie.bin +++ /dev/null @@ -1 +0,0 @@ -610e29610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600436106100575763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634f7142ad811461005c575b600080fd5b81801561006857600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261013394369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975050933594506101479350505050565b604080519115158252519081900360200190f35b6000610151610daa565b60606000806060600060606101658b6102ad565b965061017087610300565b9550889450600093506101848a60006103b5565b9250600091505b855182101561029e576101b486838151811015156101a557fe5b906020019060200201516105cc565b6040518082805190602001908083835b602083106101e35780518252601f1990920191602091820191016101c4565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912088149250610220915050576000975061029e565b610240868381518110151561023157fe5b90602001906020020151610300565b9050805160111415610262576102588185858f610626565b9095509350610281565b805160021415610278576102588185858f610725565b6000975061029e565b8415156102935783600114975061029e565b60019091019061018b565b50505050505050949350505050565b6102b5610daa565b815160008115156102db57604080518082019091526000808252602082015292506102f9565b60208401905060408051908101604052808281526020018381525092505b5050919050565b6060600061030c610dc1565b6000610317856107bd565b151561032257600080fd5b61032b856107e7565b92508260405190808252806020026020018201604052801561036757816020015b610354610daa565b81526020019060019003908161034c5790505b50935061037385610857565b91505b61037f82610890565b156103ad5761038d826108af565b848281518110151561039b57fe5b60209081029091010152600101610376565b505050919050565b6060806000806103c3610de2565b6040805160ff80825261012082019092526060916000919060208201611fe08038833901905050955060009450600093505b885184101561052d57610427898581518110151561040f57fe5b90602001015160f860020a900460f860020a026108f1565b9250878015610434575083155b156104bf578251600160f860020a03191660f860020a148061048057508251600160f860020a0319167f0300000000000000000000000000000000000000000000000000000000000000145b156104ba5760208301518651879060ff881690811061049b57fe5b906020010190600160f860020a031916908160001a9053506001850194505b610522565b82518651879060ff88169081106104d257fe5b906020010190600160f860020a031916908160001a90535060208301518651879060ff600189011690811061050357fe5b906020010190600160f860020a031916908160001a9053506002850194505b6001909301926103f5565b8460ff166040519080825280601f01601f19166020018201604052801561055e578160200160208202803883390190505b509150600090505b8460ff168110156105c057858181518110151561057f57fe5b90602001015160f860020a900460f860020a0282828151811015156105a057fe5b906020010190600160f860020a031916908160001a905350600101610566565b50979650505050505050565b60208101516060908015156105e057610620565b806040519080825280601f01601f19166020018201604052801561060e578160200160208202803883390190505b50915061062083600001518383610952565b50919050565b6000806000610633610daa565b6000865188141561067657600061065b876106568c60108151811015156101a557fe5b610992565b610666576000610669565b60015b90955060ff169350610719565b868881518110151561068457fe5b90602001015160f860020a900460f860020a0260f860020a90049250888361ffff168151811015156106b257fe5b90602001906020020151915060018801975060206106cf836105cc565b5110156106eb576106e282898989610a54565b98509050610712565b61070f898461ffff1681518110151561070057fe5b90602001906020020151610aab565b90505b8088945094505b50505094509492505050565b600080606080600061074e89600081518110151561073f57fe5b90602001906020020151610abc565b925061075b8360016103b5565b51875198019788141561078057600061065b876106568c600181518110151561073f57fe5b61078b8360016103b5565b51151561079e5760009450849350610719565b6107b089600181518110151561073f57fe5b915061070f826000610b1f565b6000808260200151600014156107d65760009150610620565b5050515160c060009190911a101590565b6000806000806000806107f9876107bd565b1515610808576000955061084d565b8651805160001a9550935061081c87610b79565b840192506001876020015185010391505b8183116108495761083d83610bf9565b9092019160010161082d565b8095505b5050505050919050565b61085f610dc1565b600061086a836107bd565b151561087557600080fd5b61087e83610b79565b83519383529092016020820152919050565b600061089a610daa565b50508051602080820151915192015191011190565b6108b7610daa565b6000806108c384610890565b1561005757836020015191506108d882610bf9565b82845260208085018290528382019086015290506102f9565b6108f9610de2565b600080610907846004610c86565b60408051808201909152600160f860020a03199190911681527f0f00000000000000000000000000000000000000000000000000000000000000949094166020850152509192915050565b60006020601f83010484602085015b82841461097f57602084028281015190820152600190930192610961565b6000865160200187015250505050505050565b6000816040518082805190602001908083835b602083106109c45780518252601f1990920191602091820191016109a5565b51815160209384036101000a6000190180199092169116179052604051919093018190038120885190955088945090928392508401908083835b60208310610a1d5780518252601f1990920191602091820191016109fe565b5181516020939093036101000a60001901801990911692169190911790526040519201829003909120939093149695505050505050565b6000806060610a6287610300565b9050805160111415610a8357610a7a81878787610626565b92509250610aa1565b805160021415610a9957610a7a81878787610725565b600092508291505b5094509492505050565b6000610ab682610cb2565b92915050565b6060600080610aca84610d04565b1515610ad557600080fd5b610ade84610d2d565b60408051828152601f19601f84011681016020019091529193509150818015610b11578160200160208202803883390190505b5092506102f9828483610952565b600080805b6020811015610b71578060080285828601815181101515610b4157fe5b60209101015160029190910a60f860020a91829004909102600160f860020a031916049190911790600101610b24565b509392505050565b6000806000836020015160001415610b9457600092506102f9565b50508151805160001a906080821015610bb057600092506102f9565b60b8821080610bcb575060c08210158015610bcb575060f882105b15610bd957600192506102f9565b60c0821015610bee5760b519820192506102f9565b5060f5190192915050565b8051600090811a6080811015610c125760019150610620565b60b8811015610c2757607e1981019150610620565b60c0811015610c5057600183015160b76020839003016101000a9004810160b519019150610620565b60f8811015610c655760be1981019150610620565b6001929092015160f76020849003016101000a900490910160f51901919050565b60008160020a60ff168360f860020a900460ff16811515610ca357fe5b0460f860020a02905092915050565b6000806000610cc084610d04565b1515610ccb57600080fd5b610cd484610d2d565b90925090506020811180610ce6575080155b15610cf057600080fd5b806020036101000a82510492505050919050565b600080826020015160001415610d1d5760009150610620565b5050515160c060009190911a1090565b6000806000806000610d3e86610d04565b1515610d4957600080fd5b8551805160001a935091506080831015610d695781945060019350610da2565b60b8831015610d875760018660200151039350816001019450610da2565b60b78303905080600187602001510303935080820160010194505b505050915091565b604080518082019091526000808252602082015290565b606060405190810160405280610dd5610daa565b8152602001600081525090565b604080518082018252906002908290803883395091929150505600a165627a7a72305820e05e82a0edbba09d7c85c9a3ac2c0b233ed4e4ecd2fd0413588c2ae2a1395cbd0029 \ No newline at end of file diff --git a/abi/RLP.abi b/abi/RLP.abi deleted file mode 100644 index 0637a08..0000000 --- a/abi/RLP.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/abi/RLP.bin b/abi/RLP.bin deleted file mode 100644 index 9191f9f..0000000 --- a/abi/RLP.bin +++ /dev/null @@ -1 +0,0 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820da2966cf4d37b9763adceaf5dfb029ef12949f9118e5d09f19bcacd63d179dc10029 \ No newline at end of file diff --git a/abi/Recover.abi b/abi/Recover.abi deleted file mode 100644 index 49fac10..0000000 --- a/abi/Recover.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"prefixHeader","type":"bytes"},{"name":"prefixExtraData","type":"bytes"}],"name":"ExtractHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"header","type":"bytes"},{"name":"sig","type":"bytes"}],"name":"VerifyBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"data","type":"bytes32"},{"name":"sig","type":"bytes"}],"name":"VerifyHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"}],"name":"broadcastSig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"},{"indexed":false,"name":"parentHash","type":"bytes"},{"indexed":false,"name":"rootHash","type":"bytes"}],"name":"broadcastHashData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"header","type":"bytes"}],"name":"test","type":"event"}] \ No newline at end of file diff --git a/abi/Recover.bin b/abi/Recover.bin deleted file mode 100644 index f9cf0b2..0000000 --- a/abi/Recover.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b5060008054600160a060020a0319163317905561099b806100326000396000f3006080604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b0e7308f811461005b578063d09ca90414610132578063fdace1be146101c9575b600080fd5b34801561006757600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261013094369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506102279650505050505050565b005b34801561013e57600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261013094369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506104929650505050505050565b3480156101d557600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526101309583359536956044949193909101919081908401838280828437509497506107179650505050505050565b60008060608060608060606000808b5198508b6040518082805190602001908083835b602083106102695780518252601f19909201916020918201910161024a565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208083529351939d507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf0195509083900301925050a1608d89036040519080825280601f01601f1916602001820160405280156102f5578160200160208202803883390190505b5060408051601f808252818301909252919850602082016103e08038833950506040805160418082526080820190925292985090506020820161082080388339505060408051602a808252606082019092529297509050602082016105408038833901905050935061036b878d60008a51610775565b600260218801600260208e016004610bb8fa5061038e868d608c8c038951610775565b600160208701600160208d016004610bb8fa506103b1848d602a8c038751610775565b6103bc878786610828565b9250826040518082805190602001908083835b602083106103ee5780518252601f1990920191602091820191016103cf565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020915061042d858d606b8c038851610775565b61043782866108bf565b6040805173ffffffffffffffffffffffffffffffffffffffff8316815290519192507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5919081900360200190a1505050505050505050505050565b600080606080856040518082805190602001908083835b602083106104c85780518252601f1990920191602091820191016104a9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020935061050184866108bf565b604080516020808252818301909252919450808201610400803883395050604080516020808252818301909252929450905080820161040080388339019050509050610551828760046020610775565b61055f8187605b6020610775565b7f8511795469a13c04a2bc22c3f1309fc0bd918a0a25a3e7e222a0417b719274c786838360405180806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156105c85781810151838201526020016105b0565b50505050905090810190601f1680156105f55780820380516001836020036101000a031916815260200191505b50848103835286518152865160209182019188019080838360005b83811015610628578181015183820152602001610610565b50505050905090810190601f1680156106555780820380516001836020036101000a031916815260200191505b50848103825285518152855160209182019187019080838360005b83811015610688578181015183820152602001610670565b50505050905090810190601f1680156106b55780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a16040805173ffffffffffffffffffffffffffffffffffffffff8516815290517fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a59181900360200190a1505050505050565b600061072383836108bf565b6040805173ffffffffffffffffffffffffffffffffffffffff8316815290519192507fba2fe28067a0918af64c5359b1579f887bf1479dd3163c7e5d456314168854a5919081900360200190a1505050565b60005b81811015610821578381840181518110151561079057fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f01000000000000000000000000000000000000000000000000000000000000000285828151811015156107e957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101610778565b5050505050565b82518251825160408051600284860180850191820180845260206021909301601f191684018301909452606096959491860193919260229091019190879082801561087d578160200160208202803883390190505b50905086602082018860208e016004610bb8fa50858582018760208d016004610bb8fa50838382018560208c016004610bb8fa509a9950505050505050505050565b600080600080845160411415156108d557600080fd5b50505060208201516040830151606084015160001a601b60ff821610156108fa57601b015b8060ff16601b148061090f57508060ff16601c145b151561091a57600080fd5b61092686828585610930565b9695505050505050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa9051909250905060018215151461092657600080fd00a165627a7a7230582038abea0db89b85cbff9e376e2e5f70ae6b7a141a79352619d845b07f7c4ce8eb0029 \ No newline at end of file diff --git a/abi/SolUtils.abi b/abi/SolUtils.abi deleted file mode 100644 index 0637a08..0000000 --- a/abi/SolUtils.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/abi/SolUtils.bin b/abi/SolUtils.bin deleted file mode 100644 index 874e86f..0000000 --- a/abi/SolUtils.bin +++ /dev/null @@ -1 +0,0 @@ -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820fe8ba14d3aab8b6b7911647c344b383a91b505bf83660943ef60ef4f2d2c3d1e0029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi deleted file mode 100644 index 056ae8a..0000000 --- a/abi/Validation.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"ValidateBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"InitChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin deleted file mode 100644 index 229a99b..0000000 --- a/abi/Validation.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50604051602080610f75833981016040525160008054600160a060020a03191633179055600155610f2f806100466000396000f3006080604052600436106100985763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166309fbd536811461009d5780630b5abdd01461013b5780634b3550301461019757806353fe62e6146101c657806359a53331146101f75780638da5cb5b14610221578063927a32e31461025f5780639a8a059214610295578063c18de0ef146102aa575b600080fd5b3480156100a957600080fd5b5060408051602060046024803582810135601f810185900485028601850190965285855261013995833595369560449491939091019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506102c29650505050505050565b005b34801561014757600080fd5b5060408051602060046024803582810135848102808701860190975280865261013996843596369660449591949091019291829185019084908082843750949750509335945061062a9350505050565b3480156101a357600080fd5b506101b26004356024356107bd565b604080519115158252519081900360200190f35b3480156101d257600080fd5b506101b260043573ffffffffffffffffffffffffffffffffffffffff602435166107dd565b34801561020357600080fd5b5061020f6004356107fd565b60408051918252519081900360200190f35b34801561022d57600080fd5b5061023661080f565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561026b57600080fd5b5061027760043561082b565b60408051938452602084019290925282820152519081900360600190f35b3480156102a157600080fd5b5061020f61084c565b3480156102b657600080fd5b506101b2600435610852565b600083815260036020526040812054606091829181908190889060ff161515610335576040805160e560020a62461bcd02815260206004820152601760248201527f436861696e206973206e6f742072656769737465726564000000000000000000604482015290519081900360640190fd5b61034661034189610867565b6108ba565b955061035461034188610867565b9450600093505b84518410156104c55783600c1415610372576104ba565b610392858581518110151561038357fe5b9060200190602002015161096f565b6040518082805190602001908083835b602083106103c15780518252601f1990920191602091820191016103a2565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916610403878681518110151561038357fe5b6040518082805190602001908083835b602083106104325780518252601f199092019160209182019101610413565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019161415156104ba576040805160e560020a62461bcd02815260206004820152601a60248201527f486561646572206461746120646f65736e2774206d6174636821000000000000604482015290519081900360640190fd5b60019093019261035b565b6104e16104da87600081518110151561038357fe5b60016109c9565b60008a815260056020526040902060010154909350831461054c576040805160e560020a62461bcd02815260206004820152601c60248201527f4e6f74206368696c64206f662070726576696f757320626c6f636b2100000000604482015290519081900360640190fd5b866040518082805190602001908083835b6020831061057c5780518252601f19909201916020918201910161055d565b51815160209384036101000a60001901801990921691161790526040805192909401829003822080835293519397507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf0195509083900301925050a16105f3896105ed87600c81518110151561038357fe5b8a6109d1565b6000898152600560205260409020805460019081018255810183905560020183905561061f8983610b52565b505050505050505050565b6001546000908414156106ad576040805160e560020a62461bcd02815260206004820152602a60248201527f43616e6e6f7420616464207468697320636861696e20696420746f206368616960448201527f6e20726567697374657200000000000000000000000000000000000000000000606482015290519081900360840190fd5b60008481526003602052604090205460ff1615610714576040805160e560020a62461bcd02815260206004820152601460248201527f436861696e20616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b506000838152600360205260408120805460ff191660011790555b825181101561079f57600084815260066020526040812084516001929086908590811061075857fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020805460ff191691151591909117905560010161072f565b50600092835260056020526040832092835560019092019190915550565b600460209081526000928352604080842090915290825290205460ff1681565b600660209081526000928352604080842090915290825290205460ff1681565b60026020526000908152604090205481565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60056020526000908152604090208054600182015460029092015490919083565b60015481565b60036020526000908152604090205460ff1681565b61086f610ecb565b8151600081151561089557604080518082019091526000808252602082015292506108b3565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006108c6610ee2565b60006108d185610b78565b15156108dc57600080fd5b6108e585610ba2565b92508260405190808252806020026020018201604052801561092157816020015b61090e610ecb565b8152602001906001900390816109065790505b50935061092d85610c12565b91505b61093982610c4b565b156109675761094782610c6a565b848281518110151561095557fe5b60209081029091010152600101610930565b505050919050565b6020810151606090801515610983576109c3565b806040519080825280601f01601f1916602001820160405280156109b1578160200160208202803883390190505b5091506109c383600001518383610cac565b50919050565b016020015190565b604080516041808252608082019092526060916000918291602082016108208038833901905050925084519150610a0c838660418503610cec565b610a72846040518082805190602001908083835b60208310610a3f5780518252601f199092019160209182019101610a20565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902084610d0e565b600087815260066020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205490915060ff161515600114610b01576040805160e560020a62461bcd02815260206004820152601760248201527f5369676e6572206e6f7420612076616c696461746f7221000000000000000000604482015290519081900360640190fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8316815290517f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef439181900360200190a1505050505050565b60009182526004602090815260408084209284529190529020805460ff19166001179055565b600080826020015160001415610b9157600091506109c3565b5050515160c060009190911a101590565b600080600080600080610bb487610b78565b1515610bc35760009550610c08565b8651805160001a95509350610bd787610d7f565b840192506001876020015185010391505b818311610c0457610bf883610dff565b90920191600101610be8565b8095505b5050505050919050565b610c1a610ee2565b6000610c2583610b78565b1515610c3057600080fd5b610c3983610d7f565b83519383529092016020820152919050565b6000610c55610ecb565b50508051602080820151915192015191011190565b610c72610ecb565b600080610c7e84610c4b565b156100985783602001519150610c9382610dff565b82845260208085018290528382019086015290506108b3565b60006020601f83010484602085015b828414610cd957602084028281015190820152600190930192610cbb565b6000865160200187015250505050505050565b6000835190508160200191508060208501828486016004610bb8fa5050505050565b60008060008084516041141515610d2457600080fd5b50505060208201516040830151606084015160001a601b60ff82161015610d4957601b015b8060ff16601b1480610d5e57508060ff16601c145b1515610d6957600080fd5b610d7586828585610e8c565b9695505050505050565b6000806000836020015160001415610d9a57600092506108b3565b50508151805160001a906080821015610db657600092506108b3565b60b8821080610dd1575060c08210158015610dd1575060f882105b15610ddf57600192506108b3565b60c0821015610df45760b519820192506108b3565b5060f5190192915050565b8051600090811a6080811015610e1857600191506109c3565b60b8811015610e2d57607e19810191506109c3565b60c0811015610e5657600183015160b76020839003016101000a9004810160b5190191506109c3565b60f8811015610e6b5760be19810191506109c3565b6001929092015160f76020849003016101000a900490910160f51901919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa90519092509050600182151514610d7557600080fd5b604080518082019091526000808252602082015290565b606060405190810160405280610ef6610ecb565b81526020016000815250905600a165627a7a72305820ab6bccffa86e84dabc81baf91b02d1cf2a595b879d1bc27c37bec5670a2ce0710029 \ No newline at end of file From e626058c39ad358fece9c77e649f04c1f7e5d99e Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Tue, 31 Jul 2018 12:04:55 +0100 Subject: [PATCH 091/203] reading contracts --- ion-cli/flow_test/flow_test.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/flow_test.go index 0b6b8f0..35247a1 100644 --- a/ion-cli/flow_test/flow_test.go +++ b/ion-cli/flow_test/flow_test.go @@ -3,12 +3,13 @@ package ionflow import ( "bytes" "context" + "io/ioutil" "math/big" + "os" "regexp" "strings" "testing" - contract "github.com/clearmatics/ion/ion-cli/contracts" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" @@ -90,6 +91,18 @@ func TestRawTransactionSimulated(t *testing.T) { // inspired by https://medium.com/@akshay_111meher/creating-offline-raw-transactions-with-go-ethereum-8d6cc8174c5d func TestDeployRawContract(t *testing.T) { + + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/abi/" + patriciaTrieABIPath := basePath + "PatriciaTrie.abi" + patriciaTrieBinPath := basePath + "PatriciaTrie.bin" + ionABIPath := basePath + "Ion.abi" + ionBinPath := basePath + "Ion.bin" + + patriciaTrieABIData, _ := ioutil.ReadFile(patriciaTrieABIPath) + patriciaTrieBinData, _ := ioutil.ReadFile(patriciaTrieBinPath) + ionABIData, _ := ioutil.ReadFile(ionABIPath) + ionBinData, _ := ioutil.ReadFile(ionBinPath) + ctx := context.Background() initialBalance := big.NewInt(1000000000) @@ -107,8 +120,8 @@ func TestDeployRawContract(t *testing.T) { // DEPLOY PATRICIA LIB ADDRESS // --------------------------------------------- // generate payload bytes (we are using PatriciaTrie in our example) - contractBinStr := contract.PatriciaTrieBin - contractABIStr := contract.PatriciaTrieABI + contractBinStr := string(patriciaTrieBinData) // contract.PatriciaTrieBin + contractABIStr := string(patriciaTrieABIData) // contract.PatriciaTrieABI bytecode := common.Hex2Bytes(contractBinStr) abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) if err != nil { @@ -161,8 +174,8 @@ func TestDeployRawContract(t *testing.T) { // generate payload bytes (we are using Ion in our example) // we added the key word Ion to make the variables different form the previous - contractIonBinStr := contract.IonBin - contractIonABIStr := contract.IonABI + contractIonBinStr := string(ionBinData) // contract.IonBin + contractIonABIStr := string(ionABIData) // contract.IonABI // add library address to Ion bytecode var re = regexp.MustCompile(`__.*PatriciaTrie.*__`) From 369e0cfa0667fdbac4c6e75e796c582e3f72d409 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Tue, 31 Jul 2018 12:55:25 +0100 Subject: [PATCH 092/203] added missing go-dep and package-lock files and started test flow of contracts in golanf --- ion-cli/flow_test/flow_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/flow_test.go index 35247a1..28a07c6 100644 --- a/ion-cli/flow_test/flow_test.go +++ b/ion-cli/flow_test/flow_test.go @@ -92,12 +92,12 @@ func TestRawTransactionSimulated(t *testing.T) { // inspired by https://medium.com/@akshay_111meher/creating-offline-raw-transactions-with-go-ethereum-8d6cc8174c5d func TestDeployRawContract(t *testing.T) { + // solidity compiled contracts ABI and Bin basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/abi/" patriciaTrieABIPath := basePath + "PatriciaTrie.abi" patriciaTrieBinPath := basePath + "PatriciaTrie.bin" ionABIPath := basePath + "Ion.abi" ionBinPath := basePath + "Ion.bin" - patriciaTrieABIData, _ := ioutil.ReadFile(patriciaTrieABIPath) patriciaTrieBinData, _ := ioutil.ReadFile(patriciaTrieBinPath) ionABIData, _ := ioutil.ReadFile(ionABIPath) From 2639b96a4ebdc017955e87f11d7f65be9b9f8d1b Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Tue, 31 Jul 2018 16:37:09 +0100 Subject: [PATCH 093/203] updated error message --- ion-cli/flow_test/flow_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/flow_test.go index 28a07c6..16c6737 100644 --- a/ion-cli/flow_test/flow_test.go +++ b/ion-cli/flow_test/flow_test.go @@ -184,7 +184,7 @@ func TestDeployRawContract(t *testing.T) { bytecodeIon := common.Hex2Bytes(contractIonBinStrWithLibAddr) abiIon, err := abi.JSON(strings.NewReader(contractIonABIStr)) if err != nil { - t.Fatal("ERROR reading PatriciaTrie ABI ", err) + t.Fatal("ERROR reading Ion ABI ", err) } constructorArg1Ion := crypto.Keccak256Hash([]byte("test argument")) // Ion argument From 16300ac573d8b3803183989e59ed48036d568a1d Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Tue, 31 Jul 2018 17:58:39 +0100 Subject: [PATCH 094/203] change to Ion.sol contract to allow blcokchain simulator to work --- contracts/Ion.sol | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 4d6e2a4..f3dc47c 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -182,7 +182,8 @@ contract Ion { // Connect to validation contract Validation validation = Validation(m_validation[_id]); bytes32 txRootHash = validation.getTxRootHash(_id, _blockHash); - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, txRootHash) ); + //assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, txRootHash) ); + verifyProof(_value, _parentNodes, _path, txRootHash); emit VerifiedProof(_id, _blockHash, uint(ProofType.TX)); return true; @@ -219,12 +220,21 @@ contract Ion { { Validation validation = Validation(m_validation[_id]); bytes32 receiptRootHash = validation.getReceiptRootHash(_id, _blockHash); - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, receiptRootHash) ); + // assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, receiptRootHash) ); + verifyProof(_value, _parentNodes, _path, receiptRootHash); emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); return true; } + /* + * Verify proof assertion to avoid stack to deep error (it doesn't show during compile time but it breaks + * blockchain simulator) + */ + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _hash) { + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, _hash) ); + } + /* * CheckRootsProof * param: _id (bytes32) Unique id of chain submitting block from From 9f0c20c23befe4bc2f0f219334384c88247efdd6 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 1 Aug 2018 10:19:10 +0100 Subject: [PATCH 095/203] Small fix to migrations file --- contracts/Ion.sol | 3 --- migrations/2_deploy_contracts.js | 1 - 2 files changed, 4 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 4d6e2a4..316b0c4 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -110,9 +110,6 @@ contract Ion { chains[_id] = true; registeredChains.push(_id); - // m_blockhashes[_id][_genesisHash] = true; - // m_blockheaders[_id][_genesisHash].blockHeight = 0; - // Create mapping of registered _id to the validation address m_validation[_id] = validationAddr; } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 2b3f6a4..08f8736 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -2,7 +2,6 @@ const Ion = artifacts.require("Ion"); const Recover = artifacts.require("Recover"); const Validation = artifacts.require("Validation"); const PatriciaTrie = artifacts.require("PatriciaTrie"); -const PatriciaTrieTest = artifacts.require("PatriciaTrieTest"); const EventFunction = artifacts.require("Function"); const EventVerifier = artifacts.require("EventVerifier"); From 34a1e1eff1c7d395e2d19c946eb762f237d76c37 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 1 Aug 2018 10:42:12 +0100 Subject: [PATCH 096/203] problem with package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 0f9288f..e9829db 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "babel-cli": "^6.26.0", "babel-polyfill": "^6.26.0", "babel-preset-env": "^1.6.1", - "babel-preset-es2015": "^6.24.1", "babel-register": "^6.26.0", "bluebird": "^3.5.1", "chai": "^4.1.2", From 36dc653717f9b1c13931989b79908d41d1cd4285 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Wed, 1 Aug 2018 11:55:00 +0100 Subject: [PATCH 097/203] added example of compiling solidity through go-ethereum --- .../{flow_test.go => raw_example_test.go} | 153 +++++++++++++++--- 1 file changed, 134 insertions(+), 19 deletions(-) rename ion-cli/flow_test/{flow_test.go => raw_example_test.go} (62%) diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/raw_example_test.go similarity index 62% rename from ion-cli/flow_test/flow_test.go rename to ion-cli/flow_test/raw_example_test.go index 16c6737..23625c4 100644 --- a/ion-cli/flow_test/flow_test.go +++ b/ion-cli/flow_test/raw_example_test.go @@ -3,7 +3,8 @@ package ionflow import ( "bytes" "context" - "io/ioutil" + "encoding/json" + "log" "math/big" "os" "regexp" @@ -14,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -89,19 +91,139 @@ func TestRawTransactionSimulated(t *testing.T) { } } +func TestCompileContract(t *testing.T) { + // --------------------------------------------- + // COMPILE ION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + ionContractPath := basePath + "Ion.sol" + + contracts, err := compiler.CompileSolidity("", ionContractPath) + if err != nil { + t.Fatal("ERROR failed to compile Ion.sol:", err) + } + + patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] + if patriciaTrieContract == nil { + log.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") + } + + patriciaTrieABIBytes, err := json.Marshal(patriciaTrieContract.Info.AbiDefinition) + if err != nil { + t.Fatal("ERROR marshalling PatriciaTrie ABI:", err) + } + contractBinStr := patriciaTrieContract.Code + contractABIStr := string(patriciaTrieABIBytes) + + // --------------------------------------------- + // START BLOCKCHAIN SIMULATOR + // --------------------------------------------- + ctx := context.Background() + initialBalance := big.NewInt(1000000000) + + userAKey, _ := crypto.GenerateKey() + userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) + + // start simulated blockchain + alloc := make(core.GenesisAlloc) + alloc[userAAddr] = core.GenesisAccount{ + Balance: initialBalance, + } + blockchain := backends.NewSimulatedBackend(alloc) + + // --------------------------------------------- + // DEPLOY PATRICIA LIB ADDRESS + // --------------------------------------------- + // generate payload bytes (we are using PatriciaTrie in our example) + bytecode := common.Hex2Bytes(contractBinStr) + abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) + if err != nil { + t.Fatal("ERROR reading PatriciaTrie ABI ", err) + } + // packedABI, err := abi.Pack("",arg1,arg2,arg3) // if there is construxtor + packedABI, err := abiPatriciaTrie.Pack("") + if err != nil { + t.Fatal("ERROR packing ABI ", err) + } + payloadBytecode := append(bytecode, packedABI...) + + // transaction parameters + from := userAAddr // useless variable, just to make clear who the signer is + nonce, err := blockchain.PendingNonceAt(ctx, from) // uint64(0) + if err != nil { + t.Fatal("Error getting pending nonce ", err) + } + amount := big.NewInt(0) // random amount + gasLimit := uint64(3000000) // random magic number (we could estimate) + gasPrice, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) + if err != nil { + t.Fatal("Error suggesting gas price ", err) + } + + // create contract transaction NewContractCreation is the same has NewTransaction with `to` == nil + // tx := types.NewTransaction(nonce, nil, amount, gasLimit, gasPrice, payloadBytecode) + tx := types.NewContractCreation(nonce, amount, gasLimit, gasPrice, payloadBytecode) + + // sign transaction + signer := types.HomesteadSigner{} + signedTx, err := types.SignTx(tx, signer, userAKey) + if err != nil { + t.Fatal("Error signing tx: ", err) + } + + err = blockchain.SendTransaction(ctx, signedTx) + if err != nil { + t.Fatal("ERROR sending contract transaction") + } + blockchain.Commit() + + txReceipt, err := blockchain.TransactionReceipt(ctx, signedTx.Hash()) + if err != nil { + t.Fatal("ERROR getting tx receipt", err) + } + if txReceipt.GasUsed == 0 || txReceipt.Status == 0 { + t.Fatal("ERROR contract did not deploy properly") + } +} + // inspired by https://medium.com/@akshay_111meher/creating-offline-raw-transactions-with-go-ethereum-8d6cc8174c5d func TestDeployRawContract(t *testing.T) { - // solidity compiled contracts ABI and Bin - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/abi/" - patriciaTrieABIPath := basePath + "PatriciaTrie.abi" - patriciaTrieBinPath := basePath + "PatriciaTrie.bin" - ionABIPath := basePath + "Ion.abi" - ionBinPath := basePath + "Ion.bin" - patriciaTrieABIData, _ := ioutil.ReadFile(patriciaTrieABIPath) - patriciaTrieBinData, _ := ioutil.ReadFile(patriciaTrieBinPath) - ionABIData, _ := ioutil.ReadFile(ionABIPath) - ionBinData, _ := ioutil.ReadFile(ionBinPath) + // --------------------------------------------- + // COMPILE ION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + ionContractPath := basePath + "Ion.sol" + + contracts, err := compiler.CompileSolidity("", ionContractPath) + if err != nil { + t.Fatal("ERROR failed to compile Ion.sol:", err) + } + + patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] + if patriciaTrieContract == nil { + log.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") + } + + patriciaTrieABIBytes, err := json.Marshal(patriciaTrieContract.Info.AbiDefinition) + if err != nil { + t.Fatal("ERROR marshalling PatriciaTrie ABI:", err) + } + + ionContract := contracts[basePath+"Ion.sol:Ion"] + ionABIBytes, err := json.Marshal(ionContract.Info.AbiDefinition) + if err != nil { + t.Fatal("ERROR marshalling Ion ABI:", err) + } + + contractBinStr := patriciaTrieContract.Code[2:] + contractABIStr := string(patriciaTrieABIBytes) + contractIonBinStr := ionContract.Code[2:] + contractIonABIStr := string(ionABIBytes) // contract.IonABI + + // --------------------------------------------- + // START BLOCKCHAIN SIMULATOR + // --------------------------------------------- ctx := context.Background() initialBalance := big.NewInt(1000000000) @@ -120,8 +242,6 @@ func TestDeployRawContract(t *testing.T) { // DEPLOY PATRICIA LIB ADDRESS // --------------------------------------------- // generate payload bytes (we are using PatriciaTrie in our example) - contractBinStr := string(patriciaTrieBinData) // contract.PatriciaTrieBin - contractABIStr := string(patriciaTrieABIData) // contract.PatriciaTrieABI bytecode := common.Hex2Bytes(contractBinStr) abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) if err != nil { @@ -172,13 +292,8 @@ func TestDeployRawContract(t *testing.T) { // after PatriciaTrie is deployed we deploy the Ion contract patriciaTrieLibAddr := txReceipt.ContractAddress - // generate payload bytes (we are using Ion in our example) - // we added the key word Ion to make the variables different form the previous - contractIonBinStr := string(ionBinData) // contract.IonBin - contractIonABIStr := string(ionABIData) // contract.IonABI - // add library address to Ion bytecode - var re = regexp.MustCompile(`__.*PatriciaTrie.*__`) + var re = regexp.MustCompile(`__.*__`) contractIonBinStrWithLibAddr := re.ReplaceAllString(contractIonBinStr, patriciaTrieLibAddr.Hex()[2:]) bytecodeIon := common.Hex2Bytes(contractIonBinStrWithLibAddr) From 75cc66ce8fdcafd5f633c3c1f704625d0e6afce1 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Wed, 1 Aug 2018 15:26:50 +0100 Subject: [PATCH 098/203] basic utils for deplolyment of ion contract --- ion-cli/flow_test/raw_example_test.go | 5 +- ion-cli/flow_test/utils.go | 185 ++++++++++++++++++++++++++ ion-cli/flow_test/utils_test.go | 39 ++++++ 3 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 ion-cli/flow_test/utils.go create mode 100644 ion-cli/flow_test/utils_test.go diff --git a/ion-cli/flow_test/raw_example_test.go b/ion-cli/flow_test/raw_example_test.go index 23625c4..04163d5 100644 --- a/ion-cli/flow_test/raw_example_test.go +++ b/ion-cli/flow_test/raw_example_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "log" "math/big" "os" "regexp" @@ -105,7 +104,7 @@ func TestCompileContract(t *testing.T) { patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] if patriciaTrieContract == nil { - log.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") + t.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") } patriciaTrieABIBytes, err := json.Marshal(patriciaTrieContract.Info.AbiDefinition) @@ -202,7 +201,7 @@ func TestDeployRawContract(t *testing.T) { patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] if patriciaTrieContract == nil { - log.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") + t.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") } patriciaTrieABIBytes, err := json.Marshal(patriciaTrieContract.Info.AbiDefinition) diff --git a/ion-cli/flow_test/utils.go b/ion-cli/flow_test/utils.go new file mode 100644 index 0000000..aefa300 --- /dev/null +++ b/ion-cli/flow_test/utils.go @@ -0,0 +1,185 @@ +package ionflow + +import ( + "context" + "crypto/ecdsa" + "encoding/json" + "log" + "math/big" + "os" + "regexp" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/compiler" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" +) + +func getContractBytecodeAndABI(c *compiler.Contract) (string, string) { + cABIBytes, err := json.Marshal(c.Info.AbiDefinition) + if err != nil { + log.Fatal("ERROR marshalling contract ABI:", err) + } + + contractBinStr := c.Code[2:] + contractABIStr := string(cABIBytes) + return contractBinStr, contractABIStr +} + +func generateContractPayload(contractBinStr string, contractABIStr string, constructorArgs ...interface{}) []byte { + bytecode := common.Hex2Bytes(contractBinStr) + abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) + if err != nil { + log.Fatal("ERROR reading contract ABI ", err) + } + packedABI, err := abiPatriciaTrie.Pack("", constructorArgs...) + if err != nil { + log.Fatal("ERROR packing ABI ", err) + } + payloadBytecode := append(bytecode, packedABI...) + return payloadBytecode +} + +func generateContractDeployTx( + ctx context.Context, + client bind.ContractTransactor, + from common.Address, + amount *big.Int, + gasLimit uint64, + payloadBytecode []byte, +) *types.Transaction { + + nonce, err := client.PendingNonceAt(ctx, from) // uint64(0) + if err != nil { + log.Fatal("Error getting pending nonce ", err) + } + gasPrice, err := client.SuggestGasPrice(ctx) //new(big.Int) + if err != nil { + log.Fatal("Error suggesting gas price ", err) + } + + // create contract transaction NewContractCreation is the same has NewTransaction with `to` == nil + // tx := types.NewTransaction(nonce, nil, amount, gasLimit, gasPrice, payloadBytecode) + tx := types.NewContractCreation(nonce, amount, gasLimit, gasPrice, payloadBytecode) + return tx +} + +// method created just to easily sign a tranasaction +func signTx(tx *types.Transaction, userKey *ecdsa.PrivateKey) *types.Transaction { + signer := types.HomesteadSigner{} // this functions makes it easier to change signer if needed + signedTx, err := types.SignTx(tx, signer, userKey) + if err != nil { + log.Fatal("Error signing tx: ", err) + } + return signedTx +} + +func compileAndDeployContract( + ctx context.Context, + client bind.ContractTransactor, + userKey *ecdsa.PrivateKey, + binStr string, + abiStr string, + amount *big.Int, + gasLimit uint64, + constructorArgs ...interface{}, +) *types.Transaction { + payload := generateContractPayload(binStr, abiStr, constructorArgs...) + userAddr := crypto.PubkeyToAddress(userKey.PublicKey) + tx := generateContractDeployTx(ctx, client, userAddr, amount, gasLimit, payload) + signedTx := signTx(tx, userKey) + + err := client.SendTransaction(ctx, signedTx) + if err != nil { + log.Fatal("ERROR sending contract deployment transaction") + } + return signedTx +} + +// ContractInstance is just an util type to output contract and address +type ContractInstance struct { + Contract *compiler.Contract + Address common.Address +} + +// CompileAndDeployIon specific compile and deploy ion contract +func CompileAndDeployIon(ctx context.Context, client bind.ContractTransactor, userKey *ecdsa.PrivateKey) <-chan ContractInstance { + // --------------------------------------------- + // COMPILE ION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + ionContractPath := basePath + "Ion.sol" + + contracts, err := compiler.CompileSolidity("", ionContractPath) + if err != nil { + log.Fatal("ERROR failed to compile Ion.sol:", err) + } + + patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] + patriciaTrieBinStr, patriciaTrieABIStr := getContractBytecodeAndABI(patriciaTrieContract) + + ionContract := contracts[basePath+"Ion.sol:Ion"] + ionBinStr, ionABIStr := getContractBytecodeAndABI(ionContract) + + // --------------------------------------------- + // DEPLOY PATRICIA LIB ADDRESS + // --------------------------------------------- + patriciaTrieSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + patriciaTrieBinStr, + patriciaTrieABIStr, + nil, + uint64(3000000), + ) + + resChan := make(chan ContractInstance) + + // TODO: make this a go routine + go func() { + defer close(resChan) + deployBackend := client.(bind.DeployBackend) + + // wait for PatriciaTrie library to be deployed + patriciaTrieAddr, err := bind.WaitDeployed(ctx, deployBackend, patriciaTrieSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // DEPLOY ION CONTRACT WITH PATRICIA LIB ADDRESS + // --------------------------------------------- + // replace palceholder with Prticia Trie Lib address + var re = regexp.MustCompile(`__.*__`) + ionBinStrWithLibAddr := re.ReplaceAllString(ionBinStr, patriciaTrieAddr.Hex()[2:]) + constructorArg1Ion := crypto.Keccak256Hash([]byte("test argument")) // Ion argument + ionSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + ionBinStrWithLibAddr, + ionABIStr, + nil, + uint64(3000000), + constructorArg1Ion, + ) + + // only stop blocking the first result after the Ion contract as been deploy + // this garuantees that it works well with the blockchain simulator Commit() + resChan <- ContractInstance{patriciaTrieContract, patriciaTrieAddr} + + // wait for Ion to be deployed + ionAddr, err := bind.WaitDeployed(ctx, deployBackend, ionSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + resChan <- ContractInstance{ionContract, ionAddr} + }() + + return resChan +} diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go new file mode 100644 index 0000000..42ebb9c --- /dev/null +++ b/ion-cli/flow_test/utils_test.go @@ -0,0 +1,39 @@ +package ionflow + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" +) + +func TestCompileAndDeployIon(t *testing.T) { + // --------------------------------------------- + // START BLOCKCHAIN SIMULATOR + // --------------------------------------------- + + ctx := context.Background() + initialBalance := big.NewInt(1000000000) + + userAKey, _ := crypto.GenerateKey() + userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) + + // start simulated blockchain + alloc := make(core.GenesisAlloc) + alloc[userAAddr] = core.GenesisAccount{ + Balance: initialBalance, + } + blockchain := backends.NewSimulatedBackend(alloc) + + contractChan := CompileAndDeployIon(ctx, blockchain, userAKey) + blockchain.Commit() + patriciaTrieContractInstance := <-contractChan + t.Log(patriciaTrieContractInstance) + + blockchain.Commit() + ionContractInstance := <-contractChan + t.Log(ionContractInstance) +} From f26926a2bc6b925cf4088620976554c27adacec4 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Wed, 1 Aug 2018 15:41:33 +0100 Subject: [PATCH 099/203] added chainID as argument --- ion-cli/flow_test/utils.go | 10 +++++----- ion-cli/flow_test/utils_test.go | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ion-cli/flow_test/utils.go b/ion-cli/flow_test/utils.go index aefa300..c64a8fa 100644 --- a/ion-cli/flow_test/utils.go +++ b/ion-cli/flow_test/utils.go @@ -106,7 +106,7 @@ type ContractInstance struct { } // CompileAndDeployIon specific compile and deploy ion contract -func CompileAndDeployIon(ctx context.Context, client bind.ContractTransactor, userKey *ecdsa.PrivateKey) <-chan ContractInstance { +func CompileAndDeployIon(ctx context.Context, client bind.ContractTransactor, userKey *ecdsa.PrivateKey, chainID interface{}) <-chan ContractInstance { // --------------------------------------------- // COMPILE ION AND DEPENDENCIES // --------------------------------------------- @@ -139,7 +139,8 @@ func CompileAndDeployIon(ctx context.Context, client bind.ContractTransactor, us resChan := make(chan ContractInstance) - // TODO: make this a go routine + // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed + // Ion depends on PatriciaTrie library go func() { defer close(resChan) deployBackend := client.(bind.DeployBackend) @@ -156,7 +157,6 @@ func CompileAndDeployIon(ctx context.Context, client bind.ContractTransactor, us // replace palceholder with Prticia Trie Lib address var re = regexp.MustCompile(`__.*__`) ionBinStrWithLibAddr := re.ReplaceAllString(ionBinStr, patriciaTrieAddr.Hex()[2:]) - constructorArg1Ion := crypto.Keccak256Hash([]byte("test argument")) // Ion argument ionSignedTx := compileAndDeployContract( ctx, client, @@ -165,11 +165,11 @@ func CompileAndDeployIon(ctx context.Context, client bind.ContractTransactor, us ionABIStr, nil, uint64(3000000), - constructorArg1Ion, + chainID, ) // only stop blocking the first result after the Ion contract as been deploy - // this garuantees that it works well with the blockchain simulator Commit() + // this guarantees that it works well with the blockchain simulator Commit() resChan <- ContractInstance{patriciaTrieContract, patriciaTrieAddr} // wait for Ion to be deployed diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index 42ebb9c..35c1740 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -28,7 +28,8 @@ func TestCompileAndDeployIon(t *testing.T) { } blockchain := backends.NewSimulatedBackend(alloc) - contractChan := CompileAndDeployIon(ctx, blockchain, userAKey) + chainID := crypto.Keccak256Hash([]byte("test argument")) // Ion argument + contractChan := CompileAndDeployIon(ctx, blockchain, userAKey, chainID) blockchain.Commit() patriciaTrieContractInstance := <-contractChan t.Log(patriciaTrieContractInstance) From 832ebc1827aff88166bc40e9ab7ebc493feee293 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Wed, 1 Aug 2018 16:19:48 +0100 Subject: [PATCH 100/203] test CompileAndDeployIon --- ion-cli/flow_test/utils.go | 54 ++++++++++++++++++++++++++++----- ion-cli/flow_test/utils_test.go | 21 +++++++++++-- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/ion-cli/flow_test/utils.go b/ion-cli/flow_test/utils.go index c64a8fa..42936b9 100644 --- a/ion-cli/flow_test/utils.go +++ b/ion-cli/flow_test/utils.go @@ -10,6 +10,7 @@ import ( "regexp" "strings" + ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -18,6 +19,12 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) +// ContractInstance is just an util type to output contract and address +type ContractInstance struct { + Contract *compiler.Contract + Address common.Address +} + func getContractBytecodeAndABI(c *compiler.Contract) (string, string) { cABIBytes, err := json.Marshal(c.Info.AbiDefinition) if err != nil { @@ -31,11 +38,11 @@ func getContractBytecodeAndABI(c *compiler.Contract) (string, string) { func generateContractPayload(contractBinStr string, contractABIStr string, constructorArgs ...interface{}) []byte { bytecode := common.Hex2Bytes(contractBinStr) - abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) + abiContract, err := abi.JSON(strings.NewReader(contractABIStr)) if err != nil { log.Fatal("ERROR reading contract ABI ", err) } - packedABI, err := abiPatriciaTrie.Pack("", constructorArgs...) + packedABI, err := abiContract.Pack("", constructorArgs...) if err != nil { log.Fatal("ERROR packing ABI ", err) } @@ -99,14 +106,47 @@ func compileAndDeployContract( return signedTx } -// ContractInstance is just an util type to output contract and address -type ContractInstance struct { - Contract *compiler.Contract - Address common.Address +// CallContract without changing the state +func CallContract( + ctx context.Context, + client bind.ContractCaller, + contract *compiler.Contract, + from, to common.Address, + methodName string, + out interface{}, +) { + abiStr, err := json.Marshal(contract.Info.AbiDefinition) + if err != nil { + log.Fatal("ERROR marshalling abi to string", err) + } + + abiContract, err := abi.JSON(strings.NewReader(string(abiStr))) + if err != nil { + log.Fatal("ERROR reading contract ABI ", err) + } + + input, err := abiContract.Pack(methodName) + if err != nil { + log.Fatal("ERROR packing the method name for the contract call", err) + } + msg := ethereum.CallMsg{From: from, To: &to, Data: input} + output, err := client.CallContract(ctx, msg, nil) + if err != nil { + log.Fatal("ERROR calling the Ion Contract", err) + } + err = abiContract.Unpack(out, methodName, output) + if err != nil { + log.Fatal("ERROR upacking the call", err) + } } // CompileAndDeployIon specific compile and deploy ion contract -func CompileAndDeployIon(ctx context.Context, client bind.ContractTransactor, userKey *ecdsa.PrivateKey, chainID interface{}) <-chan ContractInstance { +func CompileAndDeployIon( + ctx context.Context, + client bind.ContractTransactor, + userKey *ecdsa.PrivateKey, + chainID interface{}, +) <-chan ContractInstance { // --------------------------------------------- // COMPILE ION AND DEPENDENCIES // --------------------------------------------- diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index 35c1740..ab3c0b2 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -1,6 +1,7 @@ package ionflow import ( + "bytes" "context" "math/big" "testing" @@ -28,13 +29,27 @@ func TestCompileAndDeployIon(t *testing.T) { } blockchain := backends.NewSimulatedBackend(alloc) + // create a chain id chainID := crypto.Keccak256Hash([]byte("test argument")) // Ion argument + + // start compile and deploy ion contractChan := CompileAndDeployIon(ctx, blockchain, userAKey, chainID) + + // commit first block after sent transaction for deployment of patricia trie lib blockchain.Commit() - patriciaTrieContractInstance := <-contractChan - t.Log(patriciaTrieContractInstance) + // patriciaTrieContractInstance := <-contractChan + <-contractChan + // commit after transaction for deployment of Ion (with reference to Patricia Trie lib) as been sent blockchain.Commit() ionContractInstance := <-contractChan - t.Log(ionContractInstance) + + // call contract variable + methodName := "chainId" + out := new([32]byte) + CallContract(ctx, blockchain, ionContractInstance.Contract, userAAddr, ionContractInstance.Address, methodName, out) + + if !bytes.Equal((*out)[:], chainID.Bytes()) { + t.Fatal("ERROR chainID result from contract call, and sent to contract constructor differ") + } } From e94e905f98b85e95319e23abf1f95d66eabe20f9 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Wed, 1 Aug 2018 18:10:06 +0100 Subject: [PATCH 101/203] RegisterChain test --- ion-cli/flow_test/utils.go | 114 +++++++++++++++++++++++++++++--- ion-cli/flow_test/utils_test.go | 69 +++++++++++++++++++ 2 files changed, 175 insertions(+), 8 deletions(-) diff --git a/ion-cli/flow_test/utils.go b/ion-cli/flow_test/utils.go index 42936b9..f3f2c84 100644 --- a/ion-cli/flow_test/utils.go +++ b/ion-cli/flow_test/utils.go @@ -50,16 +50,16 @@ func generateContractPayload(contractBinStr string, contractABIStr string, const return payloadBytecode } -func generateContractDeployTx( +func newTx( ctx context.Context, client bind.ContractTransactor, - from common.Address, + from, to *common.Address, amount *big.Int, gasLimit uint64, payloadBytecode []byte, ) *types.Transaction { - nonce, err := client.PendingNonceAt(ctx, from) // uint64(0) + nonce, err := client.PendingNonceAt(ctx, *from) // uint64(0) if err != nil { log.Fatal("Error getting pending nonce ", err) } @@ -70,7 +70,12 @@ func generateContractDeployTx( // create contract transaction NewContractCreation is the same has NewTransaction with `to` == nil // tx := types.NewTransaction(nonce, nil, amount, gasLimit, gasPrice, payloadBytecode) - tx := types.NewContractCreation(nonce, amount, gasLimit, gasPrice, payloadBytecode) + var tx *types.Transaction + if to == nil { + tx = types.NewContractCreation(nonce, amount, gasLimit, gasPrice, payloadBytecode) + } else { + tx = types.NewTransaction(nonce, *to, amount, gasLimit, gasPrice, payloadBytecode) + } return tx } @@ -96,7 +101,7 @@ func compileAndDeployContract( ) *types.Transaction { payload := generateContractPayload(binStr, abiStr, constructorArgs...) userAddr := crypto.PubkeyToAddress(userKey.PublicKey) - tx := generateContractDeployTx(ctx, client, userAddr, amount, gasLimit, payload) + tx := newTx(ctx, client, &userAddr, nil, amount, gasLimit, payload) signedTx := signTx(tx, userKey) err := client.SendTransaction(ctx, signedTx) @@ -114,6 +119,7 @@ func CallContract( from, to common.Address, methodName string, out interface{}, + args ...interface{}, ) { abiStr, err := json.Marshal(contract.Info.AbiDefinition) if err != nil { @@ -125,9 +131,9 @@ func CallContract( log.Fatal("ERROR reading contract ABI ", err) } - input, err := abiContract.Pack(methodName) + input, err := abiContract.Pack(methodName, args...) if err != nil { - log.Fatal("ERROR packing the method name for the contract call", err) + log.Fatal("ERROR packing the method name for the contract call: ", err) } msg := ethereum.CallMsg{From: from, To: &to, Data: input} output, err := client.CallContract(ctx, msg, nil) @@ -136,10 +142,48 @@ func CallContract( } err = abiContract.Unpack(out, methodName, output) if err != nil { - log.Fatal("ERROR upacking the call", err) + log.Fatal("ERROR upacking the call: ", err) } } +// TransactionContract execute function in contract +func TransactionContract( + ctx context.Context, + client bind.ContractTransactor, + userKey *ecdsa.PrivateKey, + contract *compiler.Contract, + to common.Address, + amount *big.Int, + gasLimit uint64, + methodName string, + args ...interface{}, +) *types.Transaction { + abiStr, err := json.Marshal(contract.Info.AbiDefinition) + if err != nil { + log.Fatal("ERROR marshalling abi to string", err) + } + + abiContract, err := abi.JSON(strings.NewReader(string(abiStr))) + if err != nil { + log.Fatal("ERROR reading contract ABI ", err) + } + + payload, err := abiContract.Pack(methodName, args...) + if err != nil { + log.Fatal("ERROR packing the method name for the contract call: ", err) + } + + from := crypto.PubkeyToAddress(userKey.PublicKey) + tx := newTx(ctx, client, &from, &to, amount, gasLimit, payload) + signedTx := signTx(tx, userKey) + + err = client.SendTransaction(ctx, signedTx) + if err != nil { + log.Fatal("ERROR sending contract deployment transaction") + } + return signedTx +} + // CompileAndDeployIon specific compile and deploy ion contract func CompileAndDeployIon( ctx context.Context, @@ -223,3 +267,57 @@ func CompileAndDeployIon( return resChan } + +// CompileAndDeployValidation method +func CompileAndDeployValidation( + ctx context.Context, + client bind.ContractTransactor, + userKey *ecdsa.PrivateKey, + chainID interface{}, +) <-chan ContractInstance { + // --------------------------------------------- + // COMPILE VALIDATION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + validationContractPath := basePath + "Validation.sol" + + contracts, err := compiler.CompileSolidity("", validationContractPath) + if err != nil { + log.Fatal("ERROR failed to compile Ion.sol:", err) + } + + validationContract := contracts[basePath+"Validation.sol:Validation"] + validationBinStr, validationABIStr := getContractBytecodeAndABI(validationContract) + + // --------------------------------------------- + // DEPLOY VALIDATION CONTRACT + // --------------------------------------------- + validationSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + validationBinStr, + validationABIStr, + nil, + uint64(3000000), + chainID, + ) + + resChan := make(chan ContractInstance) + + // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed + // Ion depends on PatriciaTrie library + go func() { + defer close(resChan) + deployBackend := client.(bind.DeployBackend) + + // wait for PatriciaTrie library to be deployed + validationAddr, err := bind.WaitDeployed(ctx, deployBackend, validationSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + resChan <- ContractInstance{validationContract, validationAddr} + }() + + return resChan +} diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index ab3c0b2..c48c5ad 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -3,9 +3,11 @@ package ionflow import ( "bytes" "context" + "log" "math/big" "testing" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" @@ -53,3 +55,70 @@ func TestCompileAndDeployIon(t *testing.T) { t.Fatal("ERROR chainID result from contract call, and sent to contract constructor differ") } } + +func TestRegisterChain(t *testing.T) { + // check comments on TestCompileAndDeploy() + ctx := context.Background() + initialBalance := big.NewInt(1000000000) + userAKey, _ := crypto.GenerateKey() + userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) + alloc := make(core.GenesisAlloc) + alloc[userAAddr] = core.GenesisAccount{ + Balance: initialBalance, + } + blockchain := backends.NewSimulatedBackend(alloc) + var chainID [32]byte + copy(chainID[:], crypto.Keccak256Hash([]byte("DEPLOYEDCHAINID")).Bytes()) + contractChan := CompileAndDeployIon(ctx, blockchain, userAKey, chainID) + blockchain.Commit() + <-contractChan + blockchain.Commit() + ionContractInstance := <-contractChan + + // deploy validation contract + contractChan = CompileAndDeployValidation(ctx, blockchain, userAKey, chainID) + blockchain.Commit() + validationContractInstance := <-contractChan + + var chainIDA, addressArray [32]byte + copy(addressArray[:], validationContractInstance.Address.Bytes()) + copy(chainIDA[:], crypto.Keccak256Hash([]byte("TESTCHAINID")).Bytes()) + txRegisterChain := TransactionContract( + ctx, + blockchain, + userAKey, + ionContractInstance.Contract, + ionContractInstance.Address, + nil, + uint64(3000000), + "RegisterChain", + chainIDA, + addressArray, + ) + blockchain.Commit() + + registerChainReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChain) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + if registerChainReceipt.Status == 0 { + t.Fatalf("ERROR transaction of RegisterChain failed!: %#v\n", registerChainReceipt) + } + + methodName := "chains" + out := new(bool) + CallContract( + ctx, + blockchain, + ionContractInstance.Contract, + userAAddr, + ionContractInstance.Address, + methodName, + out, + chainIDA, + ) + + if !*out { + t.Log("ERROR expecting value of chains(validation.address) to be true, but it was ", *out) + } +} From 6b4038a937ff5694133a377f78bc0db7047aa5b3 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 2 Aug 2018 11:18:34 +0100 Subject: [PATCH 102/203] Ion CLI has functionality to interact with validation contract in current state --- IonCliScript.txt | 4 + abi/Function.bin | 2 +- abi/Ion.bin | 2 +- abi/IonCompatible.bin | 2 +- abi/Validation.abi | 2 +- abi/Validation.bin | 2 +- contracts/Validation.sol | 3 - ion-cli/block.json | 18 - ion-cli/cli/block.json | 17 + ion-cli/cli/cli.go | 134 +- ion-cli/cli/rpc.go | 63 +- ion-cli/cli/rpc_test.go | 88 +- ion-cli/config/config.go | 2 + ion-cli/config/init.go | 13 +- ion-cli/main.go | 19 +- ion-cli/rinkeby.json | 2 + migrations/2_deploy_contracts.js | 2 +- package-lock.json | 9377 ++++++++++++++++++++++++++++++ test/ion.js | 4 +- 19 files changed, 9583 insertions(+), 173 deletions(-) create mode 100644 IonCliScript.txt delete mode 100644 ion-cli/block.json create mode 100644 ion-cli/cli/block.json create mode 100644 package-lock.json diff --git a/IonCliScript.txt b/IonCliScript.txt new file mode 100644 index 0000000..28dcbe5 --- /dev/null +++ b/IonCliScript.txt @@ -0,0 +1,4 @@ +registerValidationChain: + chainId - 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 + validators - "["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"]" + genesis - 0x3471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35 diff --git a/abi/Function.bin b/abi/Function.bin index 310c8c5..daafd9a 100644 --- a/abi/Function.bin +++ b/abi/Function.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051604080610b28833981018060405281019080805190602001909291908051906020019092919050505081806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610a57806100d16000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d0fdb2b314610046575b600080fd5b34801561005257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff1916906020019092919050505061022d565b604051808215151515815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f484c1f78b8b88876040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180856000191660001916815260200184600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156102fb5780820151818401526020810190506102e0565b50505050905090810190601f1680156103285780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156103b157600080fd5b505af11580156103c5573d6000803e3d6000fd5b505050506040513d60208110156103db57600080fd5b810190808051906020019092919050505015156103f457fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663affd8be98b8b89898c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156104c55780820151818401526020810190506104aa565b50505050905090810190601f1680156104f25780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561052b578082015181840152602081019050610510565b50505050905090810190601f1680156105585780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015610591578082015181840152602081019050610576565b50505050905090810190601f1680156105be5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1580156105e357600080fd5b505af11580156105f7573d6000803e3d6000fd5b505050506040513d602081101561060d57600080fd5b8101908080519060200190929190505050151561062657fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bec205b98b8b87878c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106f75780820151818401526020810190506106dc565b50505050905090810190601f1680156107245780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561075d578082015181840152602081019050610742565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b838110156107c35780820151818401526020810190506107a8565b50505050905090810190601f1680156107f05780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b15801561081557600080fd5b505af1158015610829573d6000803e3d6000fd5b505050506040513d602081101561083f57600080fd5b8101908080519060200190929190505050151561085857fe5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357064c3d8986856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200180602001836bffffffffffffffffffffffff19166bffffffffffffffffffffffff19168152602001828103825284818151815260200191508051906020019080838360005b8381101561094c578082015181840152602081019050610931565b50505050905090810190601f1680156109795780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d60208110156109c457600080fd5b8101908080519060200190929190505050156109eb576109e26109fd565b600190506109f0565b600090505b9998505050505050505050565b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e60405160405180910390a15600a165627a7a723058208dce48a6acecdc2c29df28051d1eb880843a0e0958c7720b53ec0e0e5c21b4020029 \ No newline at end of file +608060405234801561001057600080fd5b50604051604080610b28833981018060405281019080805190602001909291908051906020019092919050505081806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610a57806100d16000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d0fdb2b314610046575b600080fd5b34801561005257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff1916906020019092919050505061022d565b604051808215151515815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f484c1f78b8b88876040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180856000191660001916815260200184600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156102fb5780820151818401526020810190506102e0565b50505050905090810190601f1680156103285780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156103b157600080fd5b505af11580156103c5573d6000803e3d6000fd5b505050506040513d60208110156103db57600080fd5b810190808051906020019092919050505015156103f457fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663affd8be98b8b89898c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156104c55780820151818401526020810190506104aa565b50505050905090810190601f1680156104f25780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561052b578082015181840152602081019050610510565b50505050905090810190601f1680156105585780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015610591578082015181840152602081019050610576565b50505050905090810190601f1680156105be5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1580156105e357600080fd5b505af11580156105f7573d6000803e3d6000fd5b505050506040513d602081101561060d57600080fd5b8101908080519060200190929190505050151561062657fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bec205b98b8b87878c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106f75780820151818401526020810190506106dc565b50505050905090810190601f1680156107245780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561075d578082015181840152602081019050610742565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b838110156107c35780820151818401526020810190506107a8565b50505050905090810190601f1680156107f05780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b15801561081557600080fd5b505af1158015610829573d6000803e3d6000fd5b505050506040513d602081101561083f57600080fd5b8101908080519060200190929190505050151561085857fe5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357064c3d8986856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200180602001836bffffffffffffffffffffffff19166bffffffffffffffffffffffff19168152602001828103825284818151815260200191508051906020019080838360005b8381101561094c578082015181840152602081019050610931565b50505050905090810190601f1680156109795780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d60208110156109c457600080fd5b8101908080519060200190929190505050156109eb576109e26109fd565b600190506109f0565b600090505b9998505050505050505050565b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e60405160405180910390a15600a165627a7a723058209ee022fb1f514b1f2780626ece41ad8a233f24fa4fe14d217ede8653e42ad6dc0029 \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin index b2e9bed..9ae5130 100644 --- a/abi/Ion.bin +++ b/abi/Ion.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051602080611fde83398101806040528101908080519060200190929190505050806001816000191690555050611f908061004e6000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100ca5780634b3550301461011357806353fe62e61461016a57806395b0ea00146101d35780639a8a059214610224578063affd8be914610257578063b64b633614610380578063bec205b9146103f1578063c18de0ef1461051a578063e79b136c14610563578063f22a195e146105e3578063f44ff71214610616578063f484c1f714610641575b600080fd5b3480156100d657600080fd5b506100f560048036038101908080359060200190929190505050610724565b60405180826000191660001916815260200191505060405180910390f35b34801561011f57600080fd5b5061015060048036038101908080356000191690602001909291908035600019169060200190929190505050610747565b604051808215151515815260200191505060405180910390f35b34801561017657600080fd5b506101b96004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610776565b604051808215151515815260200191505060405180910390f35b3480156101df57600080fd5b506102226004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107a5565b005b34801561023057600080fd5b506102396109af565b60405180826000191660001916815260200191505060405180910390f35b34801561026357600080fd5b5061036660048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506109b5565b604051808215151515815260200191505060405180910390f35b34801561038c57600080fd5b506103af6004803603810190808035600019169060200190929190505050610f45565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103fd57600080fd5b5061050060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610f78565b604051808215151515815260200191505060405180910390f35b34801561052657600080fd5b506105496004803603810190808035600019169060200190929190505050611508565b604051808215151515815260200191505060405180910390f35b34801561056f57600080fd5b506105a060048036038101908080356000191690602001909291908035600019169060200190929190505050611528565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b3480156105ef57600080fd5b506105f8611565565b60405180826000191660001916815260200191505060405180910390f35b34801561062257600080fd5b5061062b61156b565b6040518082815260200191505060405180910390f35b34801561064d57600080fd5b5061070a60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050611571565b604051808215151515815260200191505060405180910390f35b60028181548110151561073357fe5b906000526020600020016000915090505481565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6001546000191682600019161415151561084d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000836000191660001916815260200190815260200160002060009054906101000a900460ff161515156108eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555060028290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055508060056000846000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60015481565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610a58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610b2157600080fd5b505af1158015610b35573d6000803e3d6000fd5b505050506040513d6020811015610b4b57600080fd5b81019080805190602001909291905050501515610bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610c9557600080fd5b505af1158015610ca9573d6000803e3d6000fd5b505050506040513d6020811015610cbf57600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610d71578082015181840152602081019050610d56565b50505050905090810190601f168015610d9e5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610dd7578082015181840152602081019050610dbc565b50505050905090810190601f168015610e045780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610e3d578082015181840152602081019050610e22565b50505050905090810190601f168015610e6a5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610e8c57600080fd5b505af4158015610ea0573d6000803e3d6000fd5b505050506040513d6020811015610eb657600080fd5b81019080805190602001909291905050501515610ecf57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c60006002811115610eff57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561101b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156110e457600080fd5b505af11580156110f8573d6000803e3d6000fd5b505050506040513d602081101561110e57600080fd5b81019080805190602001909291905050501515611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561125857600080fd5b505af115801561126c573d6000803e3d6000fd5b505050506040513d602081101561128257600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611334578082015181840152602081019050611319565b50505050905090810190601f1680156113615780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b8381101561139a57808201518184015260208101905061137f565b50505050905090810190601f1680156113c75780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b838110156114005780820151818401526020810190506113e5565b50505050905090810190601f16801561142d5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561144f57600080fd5b505af4158015611463573d6000803e3d6000fd5b505050506040513d602081101561147957600080fd5b8101908080519060200190929190505050151561149257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c600160028111156114c257fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000806000808760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156116de57600080fd5b505af11580156116f2573d6000803e3d6000fd5b505050506040513d602081101561170857600080fd5b8101908080519060200190929190505050151561178d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1696508673ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561185257600080fd5b505af1158015611866573d6000803e3d6000fd5b505050506040513d602081101561187c57600080fd5b810190808051906020019092919050505095508673ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561191657600080fd5b505af115801561192a573d6000803e3d6000fd5b505050506040513d602081101561194057600080fd5b8101908080519060200190929190505050945061195c8a6119fe565b60001916866000191614151561196e57fe5b611977896119fe565b60001916856000191614151561198957fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c6002808111156119b857fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001975050505050505050949350505050565b6000611a08611f0f565b606080611a1485611ab1565b9250611a1f83611b0c565b9150611a42826000815181101515611a3357fe5b90602001906020020151611bc9565b9050806040518082805190602001908083835b602083101515611a7a5780518252602082019150602081019050602083039250611a55565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b611ab9611f0f565b600080835191506000821415611ae75760408051908101604052806000815260200160008152509250611b05565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611b18611f29565b6000611b2385611c2e565b1515611b2e57600080fd5b611b3785611c60565b925082604051908082528060200260200182016040528015611b7357816020015b611b60611f4a565b815260200190600190039081611b585790505b509350611b7f85611cda565b91505b611b8b82611d22565b15611bc157611b9982611d4c565b8482815181101515611ba757fe5b906020019060200201819052508080600101915050611b82565b505050919050565b60606000826020015190506000811415611be257611c28565b806040519080825280601f01601f191660200182016040528015611c155781602001602082028038833980820191505090505b509150611c2783600001518383611da8565b5b50919050565b600080600083602001511415611c475760009150611c5a565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611c7287611c2e565b1515611c815760009550611cd0565b86600001519350835160001a9450611c9887611de9565b840192506001876020015185010391505b8183111515611ccc57611cbb83611e75565b830192508080600101915050611ca9565b8095505b5050505050919050565b611ce2611f29565b6000611ced83611c2e565b1515611cf857600080fd5b611d0183611de9565b83600001510190508282600001819052508082602001818152505050919050565b6000611d2c611f0f565b826000015190508060200151816000015101836020015110915050919050565b611d54611f0f565b600080611d6084611d22565b15611d9c5783602001519150611d7582611e75565b90508183600001818152505080836020018181525050808201846020018181525050611da1565b600080fd5b5050919050565b60006020601f83010484602085015b828414611dd65760208402808301518183015260018501945050611db7565b6000865160200187015250505050505050565b60008060008084602001511415611e035760009250611e6e565b83600001519050805160001a91506080821015611e235760009250611e6e565b60b8821080611e3f575060c08210158015611e3e575060f882105b5b15611e4d5760019250611e6e565b60c0821015611e6457600160b78303019250611e6e565b600160f783030192505b5050919050565b600080825160001a90506080811015611e915760019150611f09565b60b8811015611ea857600160808203019150611f08565b60c0811015611ed25760b78103806020036101000a60018501510480820160010193505050611f07565b60f8811015611ee957600160c08203019150611f06565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611f3d611f4a565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820d6cf1288a129db81ed6bbc34f59ab6b76a8c79ff25da2ef9bb507004c96a65d10029 \ No newline at end of file +608060405234801561001057600080fd5b50604051602080611fde83398101806040528101908080519060200190929190505050806001816000191690555050611f908061004e6000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100ca5780634b3550301461011357806353fe62e61461016a57806395b0ea00146101d35780639a8a059214610224578063affd8be914610257578063b64b633614610380578063bec205b9146103f1578063c18de0ef1461051a578063e79b136c14610563578063f22a195e146105e3578063f44ff71214610616578063f484c1f714610641575b600080fd5b3480156100d657600080fd5b506100f560048036038101908080359060200190929190505050610724565b60405180826000191660001916815260200191505060405180910390f35b34801561011f57600080fd5b5061015060048036038101908080356000191690602001909291908035600019169060200190929190505050610747565b604051808215151515815260200191505060405180910390f35b34801561017657600080fd5b506101b96004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610776565b604051808215151515815260200191505060405180910390f35b3480156101df57600080fd5b506102226004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107a5565b005b34801561023057600080fd5b506102396109af565b60405180826000191660001916815260200191505060405180910390f35b34801561026357600080fd5b5061036660048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506109b5565b604051808215151515815260200191505060405180910390f35b34801561038c57600080fd5b506103af6004803603810190808035600019169060200190929190505050610f45565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103fd57600080fd5b5061050060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610f78565b604051808215151515815260200191505060405180910390f35b34801561052657600080fd5b506105496004803603810190808035600019169060200190929190505050611508565b604051808215151515815260200191505060405180910390f35b34801561056f57600080fd5b506105a060048036038101908080356000191690602001909291908035600019169060200190929190505050611528565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b3480156105ef57600080fd5b506105f8611565565b60405180826000191660001916815260200191505060405180910390f35b34801561062257600080fd5b5061062b61156b565b6040518082815260200191505060405180910390f35b34801561064d57600080fd5b5061070a60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050611571565b604051808215151515815260200191505060405180910390f35b60028181548110151561073357fe5b906000526020600020016000915090505481565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6001546000191682600019161415151561084d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000836000191660001916815260200190815260200160002060009054906101000a900460ff161515156108eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555060028290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055508060056000846000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60015481565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610a58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610b2157600080fd5b505af1158015610b35573d6000803e3d6000fd5b505050506040513d6020811015610b4b57600080fd5b81019080805190602001909291905050501515610bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610c9557600080fd5b505af1158015610ca9573d6000803e3d6000fd5b505050506040513d6020811015610cbf57600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610d71578082015181840152602081019050610d56565b50505050905090810190601f168015610d9e5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610dd7578082015181840152602081019050610dbc565b50505050905090810190601f168015610e045780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610e3d578082015181840152602081019050610e22565b50505050905090810190601f168015610e6a5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610e8c57600080fd5b505af4158015610ea0573d6000803e3d6000fd5b505050506040513d6020811015610eb657600080fd5b81019080805190602001909291905050501515610ecf57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c60006002811115610eff57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561101b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156110e457600080fd5b505af11580156110f8573d6000803e3d6000fd5b505050506040513d602081101561110e57600080fd5b81019080805190602001909291905050501515611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561125857600080fd5b505af115801561126c573d6000803e3d6000fd5b505050506040513d602081101561128257600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611334578082015181840152602081019050611319565b50505050905090810190601f1680156113615780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b8381101561139a57808201518184015260208101905061137f565b50505050905090810190601f1680156113c75780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b838110156114005780820151818401526020810190506113e5565b50505050905090810190601f16801561142d5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561144f57600080fd5b505af4158015611463573d6000803e3d6000fd5b505050506040513d602081101561147957600080fd5b8101908080519060200190929190505050151561149257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c600160028111156114c257fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000806000808760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156116de57600080fd5b505af11580156116f2573d6000803e3d6000fd5b505050506040513d602081101561170857600080fd5b8101908080519060200190929190505050151561178d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1696508673ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561185257600080fd5b505af1158015611866573d6000803e3d6000fd5b505050506040513d602081101561187c57600080fd5b810190808051906020019092919050505095508673ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561191657600080fd5b505af115801561192a573d6000803e3d6000fd5b505050506040513d602081101561194057600080fd5b8101908080519060200190929190505050945061195c8a6119fe565b60001916866000191614151561196e57fe5b611977896119fe565b60001916856000191614151561198957fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c6002808111156119b857fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001975050505050505050949350505050565b6000611a08611f0f565b606080611a1485611ab1565b9250611a1f83611b0c565b9150611a42826000815181101515611a3357fe5b90602001906020020151611bc9565b9050806040518082805190602001908083835b602083101515611a7a5780518252602082019150602081019050602083039250611a55565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b611ab9611f0f565b600080835191506000821415611ae75760408051908101604052806000815260200160008152509250611b05565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611b18611f29565b6000611b2385611c2e565b1515611b2e57600080fd5b611b3785611c60565b925082604051908082528060200260200182016040528015611b7357816020015b611b60611f4a565b815260200190600190039081611b585790505b509350611b7f85611cda565b91505b611b8b82611d22565b15611bc157611b9982611d4c565b8482815181101515611ba757fe5b906020019060200201819052508080600101915050611b82565b505050919050565b60606000826020015190506000811415611be257611c28565b806040519080825280601f01601f191660200182016040528015611c155781602001602082028038833980820191505090505b509150611c2783600001518383611da8565b5b50919050565b600080600083602001511415611c475760009150611c5a565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611c7287611c2e565b1515611c815760009550611cd0565b86600001519350835160001a9450611c9887611de9565b840192506001876020015185010391505b8183111515611ccc57611cbb83611e75565b830192508080600101915050611ca9565b8095505b5050505050919050565b611ce2611f29565b6000611ced83611c2e565b1515611cf857600080fd5b611d0183611de9565b83600001510190508282600001819052508082602001818152505050919050565b6000611d2c611f0f565b826000015190508060200151816000015101836020015110915050919050565b611d54611f0f565b600080611d6084611d22565b15611d9c5783602001519150611d7582611e75565b90508183600001818152505080836020018181525050808201846020018181525050611da1565b600080fd5b5050919050565b60006020601f83010484602085015b828414611dd65760208402808301518183015260018501945050611db7565b6000865160200187015250505050505050565b60008060008084602001511415611e035760009250611e6e565b83600001519050805160001a91506080821015611e235760009250611e6e565b60b8821080611e3f575060c08210158015611e3e575060f882105b5b15611e4d5760019250611e6e565b60c0821015611e6457600160b78303019250611e6e565b600160f783030192505b5050919050565b600080825160001a90506080811015611e915760019150611f09565b60b8811015611ea857600160808203019150611f08565b60c0811015611ed25760b78103806020036101000a60018501510480820160010193505050611f07565b60f8811015611ee957600160c08203019150611f06565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611f3d611f4a565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820c9e393c8db8d60d821761db3344bc3e16cce6df66586591bd3d2a43eaa4b2ee60029 \ No newline at end of file diff --git a/abi/IonCompatible.bin b/abi/IonCompatible.bin index 52cf03f..48b938a 100644 --- a/abi/IonCompatible.bin +++ b/abi/IonCompatible.bin @@ -1 +1 @@ -6080604052348015600f57600080fd5b5060405160208060b483398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050603580607f6000396000f3006080604052600080fd00a165627a7a7230582004a7d02edd9360be54604bf8d2702e8ec8cb90c5f32925f414bdc43d211679930029 \ No newline at end of file +6080604052348015600f57600080fd5b5060405160208060b483398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050603580607f6000396000f3006080604052600080fd00a165627a7a72305820265633b22444b9ca92bffc39cb488c8966ba05a699ce6a56592fdd1d2c589d9e0029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi index 283c820..fb12ac6 100644 --- a/abi/Validation.abi +++ b/abi/Validation.abi @@ -1 +1 @@ -[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getReceiptRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getTxRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getReceiptRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getTxRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin index 3ea00e2..19b95a7 100644 --- a/abi/Validation.bin +++ b/abi/Validation.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b5060405160208061189383398101806040528101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060018160001916905550506118058061008e6000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806307bff1b1146100a957806313d3babb1461010457806347bfc0a81461015f5780634b355030146101e1578063528243741461023857806353fe62e6146102f55780638da5cb5b1461035e5780639a8a0592146103b5578063c18de0ef146103e8578063e79b136c14610431575b600080fd5b3480156100b557600080fd5b506100e6600480360381019080803560001916906020019092919080356000191690602001909291905050506104c0565b60405180826000191660001916815260200191505060405180910390f35b34801561011057600080fd5b5061014160048036038101908080356000191690602001909291908035600019169060200190929190505050610502565b60405180826000191660001916815260200191505060405180910390f35b34801561016b57600080fd5b506101df6004803603810190808035600019169060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035600019169060200190929190505050610544565b005b3480156101ed57600080fd5b5061021e600480360381019080803560001916906020019092919080356000191690602001909291905050506107f3565b604051808215151515815260200191505060405180910390f35b34801561024457600080fd5b506102f36004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610822565b005b34801561030157600080fd5b506103446004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e10565b604051808215151515815260200191505060405180910390f35b34801561036a57600080fd5b50610373610e3f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103c157600080fd5b506103ca610e64565b60405180826000191660001916815260200191505060405180910390f35b3480156103f457600080fd5b506104176004803603810190808035600019169060200190929190505050610e6a565b604051808215151515815260200191505060405180910390f35b34801561043d57600080fd5b5061046e60048036038101908080356000191690602001909291908035600019169060200190929190505050610e8a565b6040518086815260200185600019166000191681526020018460001916600019168152602001836000191660001916815260200182600019166000191681526020019550505050505060405180910390f35b60006004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060040154905092915050565b60006004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060030154905092915050565b6000600154600019168460001916141515156105ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60026000856000191660001916815260200190815260200160002060009054906101000a900460ff1615151561068c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160026000866000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600090505b8251811015610763576001600560008660001916600019168152602001908152602001600020600085848151811015156106fb57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080806001019150506106c5565b6000600460008660001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555060016003600086600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555050505050565b60036020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008760026000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156108c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b6108d96108d489610ecd565b610f28565b95506108ec6108e788610ecd565b610f28565b9450600093505b8451841015610a9957600c84141561090a57610a8c565b61092a858581518110151561091b57fe5b90602001906020020151610fe5565b6040518082805190602001908083835b60208310151561095f578051825260208201915060208101905060208303925061093a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166109b087868151811015156109a157fe5b90602001906020020151610fe5565b6040518082805190602001908083835b6020831015156109e557805182526020820191506020810190506020830392506109c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141515610a8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486561646572206461746120646f65736e2774206d617463682100000000000081525060200191505060405180910390fd5b5b83806001019450506108f3565b610ac4610abd876000815181101515610aae57fe5b90602001906020020151610fe5565b600161104a565b9250600360008a600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060009054906101000a900460ff161515610b7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b866040518082805190602001908083835b602083101515610bb25780518252602082019150602081019050602083039250610b8d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018260405180826000191660001916815260200191505060405180910390a1610c4b89610c4587600c815181101515610c3657fe5b90602001906020020151610fe5565b8a61105e565b610c6c866008815181101515610c5d57fe5b9060200190602002015161125f565b600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555081600460008b6000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600101816000191690555082600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206002018160001916905550610d52610d4b876004815181101515610d3c57fe5b90602001906020020151610fe5565b600161104a565b600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206003018160001916905550610dbc610db5876005815181101515610da657fe5b90602001906020020151610fe5565b600161104a565b600460008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206004018160001916905550610e0589836112b6565b505050505050505050565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b60026020528060005260406000206000915054906101000a900460ff1681565b6004602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154908060040154905085565b610ed5611784565b600080835191506000821415610f035760408051908101604052806000815260200160008152509250610f21565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610f3461179e565b6000610f3f85611307565b1515610f4a57600080fd5b610f5385611339565b925082604051908082528060200260200182016040528015610f8f57816020015b610f7c6117bf565b815260200190600190039081610f745790505b509350610f9b856113b3565b91505b610fa7826113fb565b15610fdd57610fb582611425565b8482815181101515610fc357fe5b906020019060200201819052508080600101915050610f9e565b505050919050565b60606000826020015190506000811415610ffe57611044565b806040519080825280601f01601f1916602001820160405280156110315781602001602082028038833980820191505090505b50915061104383600001518383611481565b5b50919050565b600060208201915081830151905092915050565b606060008060416040519080825280601f01601f1916602001820160405280156110975781602001602082028038833980820191505090505b509250845191506110ac8386604185036114c2565b611118846040518082805190602001908083835b6020831015156110e557805182526020820191506020810190506020830392506110c0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020846114e4565b905060056000876000191660001916815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156111f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef4381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b600080600061126d8461155c565b151561127857600080fd5b6112818461158d565b809250819350505060208111806112985750600081145b156112a257600080fd5b806020036101000a82510492505050919050565b60016003600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000806000836020015114156113205760009150611333565b8260000151905060c0815160001a101591505b50919050565b60008060008060008061134b87611307565b151561135a57600095506113a9565b86600001519350835160001a94506113718761160e565b840192506001876020015185010391505b81831115156113a5576113948361169a565b830192508080600101915050611382565b8095505b5050505050919050565b6113bb61179e565b60006113c683611307565b15156113d157600080fd5b6113da8361160e565b83600001510190508282600001819052508082602001818152505050919050565b6000611405611784565b826000015190508060200151816000015101836020015110915050919050565b61142d611784565b600080611439846113fb565b15611475578360200151915061144e8261169a565b9050818360000181815250508083602001818152505080820184602001818152505061147a565b600080fd5b5050919050565b60006020601f83010484602085015b8284146114af5760208402808301518183015260018501945050611490565b6000865160200187015250505050505050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b600080600080604185511415156114fa57600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561152557601b810190505b601b8160ff16148061153a5750601c8160ff16145b151561154557600080fd5b61155186828585611734565b935050505092915050565b6000806000836020015114156115755760009150611587565b8260000151905060c0815160001a1091505b50919050565b600080600080600061159e8661155c565b15156115a957600080fd5b85600001519150815160001a925060808310156115cc5781945060019350611606565b60b88310156115ea5760018660200151039350600182019450611605565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b600080600080846020015114156116285760009250611693565b83600001519050805160001a915060808210156116485760009250611693565b60b8821080611664575060c08210158015611663575060f882105b5b156116725760019250611693565b60c082101561168957600160b78303019250611693565b600160f783030192505b5050919050565b600080825160001a905060808110156116b6576001915061172e565b60b88110156116cd5760016080820301915061172d565b60c08110156116f75760b78103806020036101000a6001850151048082016001019350505061172c565b60f881101561170e57600160c0820301915061172b565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561177757600080fd5b8092505050949350505050565b604080519081016040528060008152602001600081525090565b6060604051908101604052806117b26117bf565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a7230582080fcb68fb04bfab7a40966801cfb76a69a1bce4a52c2e6e779069869e7733eb40029 \ No newline at end of file +608060405234801561001057600080fd5b506040516020806117ca8339810180604052810190808051906020019092919050505080600081600019169055505061177c8061004e6000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806307bff1b11461009e57806313d3babb146100f957806347bfc0a8146101545780634b355030146101d6578063528243741461022d57806353fe62e6146102ea5780639a8a059214610353578063c18de0ef14610386578063e79b136c146103cf575b600080fd5b3480156100aa57600080fd5b506100db6004803603810190808035600019169060200190929190803560001916906020019092919050505061045e565b60405180826000191660001916815260200191505060405180910390f35b34801561010557600080fd5b50610136600480360381019080803560001916906020019092919080356000191690602001909291905050506104a0565b60405180826000191660001916815260200191505060405180910390f35b34801561016057600080fd5b506101d460048036038101908080356000191690602001909291908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080356000191690602001909291905050506104e2565b005b3480156101e257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919050505061078f565b604051808215151515815260200191505060405180910390f35b34801561023957600080fd5b506102e86004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506107be565b005b3480156102f657600080fd5b506103396004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610dac565b604051808215151515815260200191505060405180910390f35b34801561035f57600080fd5b50610368610ddb565b60405180826000191660001916815260200191505060405180910390f35b34801561039257600080fd5b506103b56004803603810190808035600019169060200190929190505050610de1565b604051808215151515815260200191505060405180910390f35b3480156103db57600080fd5b5061040c60048036038101908080356000191690602001909291908035600019169060200190929190505050610e01565b6040518086815260200185600019166000191681526020018460001916600019168152602001836000191660001916815260200182600019166000191681526020019550505050505060405180910390f35b60006003600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060040154905092915050565b60006003600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060030154905092915050565b600080546000191684600019161415151561058b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60016000856000191660001916815260200190815260200160002060009054906101000a900460ff16151515610629576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b6001806000866000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600090505b82518110156106ff5760016004600086600019166000191681526020019081526020016000206000858481518110151561069757fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610661565b6000600360008660001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555060016002600086600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555050505050565b60026020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008760016000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610864576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61087561087089610e44565b610e9f565b955061088861088388610e44565b610e9f565b9450600093505b8451841015610a3557600c8414156108a657610a28565b6108c685858151811015156108b757fe5b90602001906020020151610f5c565b6040518082805190602001908083835b6020831015156108fb57805182526020820191506020810190506020830392506108d6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661094c878681518110151561093d57fe5b90602001906020020151610f5c565b6040518082805190602001908083835b602083101515610981578051825260208201915060208101905060208303925061095c565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141515610a27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486561646572206461746120646f65736e2774206d617463682100000000000081525060200191505060405180910390fd5b5b838060010194505061088f565b610a60610a59876000815181101515610a4a57fe5b90602001906020020151610f5c565b6001610fc1565b9250600260008a600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060009054906101000a900460ff161515610b18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b866040518082805190602001908083835b602083101515610b4e5780518252602082019150602081019050602083039250610b29565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018260405180826000191660001916815260200191505060405180910390a1610be789610be187600c815181101515610bd257fe5b90602001906020020151610f5c565b8a610fd5565b610c08866008815181101515610bf957fe5b906020019060200201516111d6565b600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555081600360008b6000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600101816000191690555082600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206002018160001916905550610cee610ce7876004815181101515610cd857fe5b90602001906020020151610f5c565b6001610fc1565b600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206003018160001916905550610d58610d51876005815181101515610d4257fe5b90602001906020020151610f5c565b6001610fc1565b600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206004018160001916905550610da1898361122d565b505050505050505050565b60046020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60005481565b60016020528060005260406000206000915054906101000a900460ff1681565b6003602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154908060040154905085565b610e4c6116fb565b600080835191506000821415610e7a5760408051908101604052806000815260200160008152509250610e98565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610eab611715565b6000610eb68561127e565b1515610ec157600080fd5b610eca856112b0565b925082604051908082528060200260200182016040528015610f0657816020015b610ef3611736565b815260200190600190039081610eeb5790505b509350610f128561132a565b91505b610f1e82611372565b15610f5457610f2c8261139c565b8482815181101515610f3a57fe5b906020019060200201819052508080600101915050610f15565b505050919050565b60606000826020015190506000811415610f7557610fbb565b806040519080825280601f01601f191660200182016040528015610fa85781602001602082028038833980820191505090505b509150610fba836000015183836113f8565b5b50919050565b600060208201915081830151905092915050565b606060008060416040519080825280601f01601f19166020018201604052801561100e5781602001602082028038833980820191505090505b50925084519150611023838660418503611439565b61108f846040518082805190602001908083835b60208310151561105c5780518252602082019150602081019050602083039250611037565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390208461145b565b905060046000876000191660001916815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561116b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef4381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b60008060006111e4846114d3565b15156111ef57600080fd5b6111f884611504565b8092508193505050602081118061120f5750600081145b1561121957600080fd5b806020036101000a82510492505050919050565b60016002600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008060008360200151141561129757600091506112aa565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806112c28761127e565b15156112d15760009550611320565b86600001519350835160001a94506112e887611585565b840192506001876020015185010391505b818311151561131c5761130b83611611565b8301925080806001019150506112f9565b8095505b5050505050919050565b611332611715565b600061133d8361127e565b151561134857600080fd5b61135183611585565b83600001510190508282600001819052508082602001818152505050919050565b600061137c6116fb565b826000015190508060200151816000015101836020015110915050919050565b6113a46116fb565b6000806113b084611372565b156113ec57836020015191506113c582611611565b905081836000018181525050808360200181815250508082018460200181815250506113f1565b600080fd5b5050919050565b60006020601f83010484602085015b8284146114265760208402808301518183015260018501945050611407565b6000865160200187015250505050505050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b6000806000806041855114151561147157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561149c57601b810190505b601b8160ff1614806114b15750601c8160ff16145b15156114bc57600080fd5b6114c8868285856116ab565b935050505092915050565b6000806000836020015114156114ec57600091506114fe565b8260000151905060c0815160001a1091505b50919050565b6000806000806000611515866114d3565b151561152057600080fd5b85600001519150815160001a92506080831015611543578194506001935061157d565b60b8831015611561576001866020015103935060018201945061157c565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b6000806000808460200151141561159f576000925061160a565b83600001519050805160001a915060808210156115bf576000925061160a565b60b88210806115db575060c082101580156115da575060f882105b5b156115e9576001925061160a565b60c082101561160057600160b7830301925061160a565b600160f783030192505b5050919050565b600080825160001a9050608081101561162d57600191506116a5565b60b8811015611644576001608082030191506116a4565b60c081101561166e5760b78103806020036101000a600185015104808201600101935050506116a3565b60f881101561168557600160c082030191506116a2565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa92508051915050600115158215151415156116ee57600080fd5b8092505050949350505050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611729611736565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820c3755aed4d27c4e81346282c5970f9b444d3102512fa0460f13223a8fff7c83a0029 \ No newline at end of file diff --git a/contracts/Validation.sol b/contracts/Validation.sol index acf4ef5..c4402ac 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -11,7 +11,6 @@ contract Validation { using RLP for RLP.Iterator; using RLP for bytes; - address public owner; bytes32 public chainId; /* @@ -37,7 +36,6 @@ contract Validation { * @param _id genesis block of the blockchain where the contract is deployed */ constructor (bytes32 _id) public { - owner = msg.sender; chainId = _id; } @@ -146,7 +144,6 @@ contract Validation { return(m_blockheaders[_id][_hash].receiptRootHash); } - /* * onlyRegisteredChains * param: _id (bytes32) Unique id of chain supplied to function diff --git a/ion-cli/block.json b/ion-cli/block.json deleted file mode 100644 index f1ff951..0000000 --- a/ion-cli/block.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "parentHash": "0xb5567eddb3bf1b6d12af53e4f8983ee82684d48ce65afef8aa067bf6c59d801e", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "miner": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xdb37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dc", - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x2", - "number": "0x8", - "gasLimit": "0xfe01c8", - "gasUsed": "0x0", - "timestamp": "0x5b3252dc", - "extraData": "0xd78301080a846765746887676f312e392e33856c696e75780000000000000000af64d47b7b33960eff2eaedfd6fae84784e47f13c97df41498c81288c72fe63c2d0429d8692d756d1c7ccb84f68e20acc298465de6b841ee34edc2778b8af3ac00", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0xe65c9896678436a46b106b85cdea91a425e7df7c73128163f66125eefb27fa53" -} diff --git a/ion-cli/cli/block.json b/ion-cli/cli/block.json new file mode 100644 index 0000000..0acb09c --- /dev/null +++ b/ion-cli/cli/block.json @@ -0,0 +1,17 @@ +{ + "parentHash": "0x3471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x0000000000000000000000000000000000000000", + "stateRoot": "0xf526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444", + "transactionsRoot": "0x07f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586", + "receiptsRoot": "0x907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ff", + "logsBloom": "0x22440000020000090000000000000000041000080000008000088000080000000200000400000800000000000000400000000000000000000010000008020102000000000000080000000008800000000000022000000004000000010000000000080000000620400440100010200400082000000000000080040010000100020020000000000000080080000001000000000100000400480000000002000000002000080018000008108000100000000000000000020000050010001004000000000102000040004000000000000000000000004400000000000000000000000208000000000400008200020000004022400000000004000200848000000000", + "difficulty": "0x2", + "number": "0x288c8e", + "gasLimit": "0x7295a1", + "gasUsed": "0x2bffa2", + "timestamp": "0x5b4f6b1d", + "extraData": "0xd68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000" +} diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 9c5fd1e..76ca8a9 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -10,16 +10,19 @@ import ( "strconv" "strings" + "github.com/ethereum/go-ethereum/common" + "github.com/abiosoft/ishell" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/ethclient" "github.com/clearmatics/ion/ion-cli/config" contract "github.com/clearmatics/ion/ion-cli/contracts" + "github.com/clearmatics/ion/ion-cli/utils" ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientFrom *ethclient.Client, Ion *contract.Ion) { +func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contract.Validation, Ion *contract.Ion) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -69,81 +72,118 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Ion *contract.Ion) }) shell.AddCmd(&ishell.Cmd{ - Name: "ionChainId", - Help: "use: ionChainId \n\t\t\t\tdescription: Returns id of Ion chain", + Name: "registerChainValidation", + Help: "use: registerChainValidation \n\t\t\t\tdescription: Register new chain with validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) - if len(c.Args) == 0 { - result, err := Ion.ChainId(&bind.CallOpts{}) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Printf("Result:\t%x\n", result) - } else if len(c.Args) > 0 { - c.Println("Only enter single argument") + c.ShowPrompt(false) + defer c.ShowPrompt(true) // yes, revert after login. + + // Get the chainId + bytesChainId, err := utils.StringToBytes32(setup.ChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } + + // Get the validators array + c.Print("Enter Validators: ") + validatorString := c.ReadLine() + valArray := strings.Fields(validatorString) + var validators []common.Address + for _, val := range valArray { + validators = append(validators, common.HexToAddress(val)) + } + + // Get genesis hash + c.Print("Enter Genesis Hash: ") + genesis := c.ReadLine() + bytesGenesis, err := utils.StringToBytes32(genesis) + if err != nil { + c.Printf("Error: %s", err) + return } + + c.Printf("Running Command:\t%x\t%x\t%x\n", bytesChainId, validators, bytesGenesis) + tx, err := Validation.RegisterChain(auth, bytesChainId, validators, bytesGenesis) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Println(tx) c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ - Name: "ionRegisteredChains", - Help: "use: ionRegisteredChains \n\t\t\t\tdescription: Returns array of all registered chains", + Name: "checkBlockValidation", + Help: "use: checkBlockValidation [chainId] [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) - if len(c.Args) == 0 { - result, err := Ion.RegisteredChains(&bind.CallOpts{}, big.NewInt(0)) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Printf("Result:\t%s\n", result) - } else if len(c.Args) > 0 { - c.Println("Only enter single argument") + c.ShowPrompt(false) + defer c.ShowPrompt(true) // yes, revert after login. + + // Get the chainId + bytesChainId, err := utils.StringToBytes32(setup.ChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } + + // Get the blockHash + c.Print("Enter BlockHash: ") + blockHash := c.ReadLine() + bytesBlockHash, err := utils.StringToBytes32(blockHash) + if err != nil { + c.Printf("Error: %s", err) + return } + + result, err := Validation.MBlockhashes(&bind.CallOpts{}, bytesChainId, bytesBlockHash) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Println("Checking for valid block:") + c.Printf("ChainId:\t%x\nBlockHash:\t%x\nValid:\t\t%v\n", bytesChainId, bytesBlockHash, result) + c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ - Name: "ionRegisterChain", - Help: "use: ionRegisterChain \n\t\t\t\tdescription: Register chain with Ion contract", + Name: "submitBlockValidation", + Help: "use: submitBlockValidation [chainId] [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. // Get the chainId - c.Print("New ChainId: ") - chainId := c.ReadLine() + bytesChainId, err := utils.StringToBytes32(setup.ChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } - c.Printf("Running Command:\t%s\t%s", chainId) + // Get the block number + c.Print("Enter Block Number: ") + blockNum := c.ReadLine() + c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) + + signedBlock, unsignedBlock := calculateRlpEncoding(clientFrom, blockNum) + res, err := Validation.SubmitBlock(auth, bytesChainId, unsignedBlock, signedBlock) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) c.Println("===============================================================") }, }) - // shell.AddCmd(&ishell.Cmd{ - // Name: "getValidators", - // Help: "use: getValidators \n\t\t\t\tdescription: Returns the whitelist of validators from validator contract", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrFrom) - // result, err := Validation.GetValidators(&bind.CallOpts{}) - // if err != nil { - // fmt.Printf("Error: %s", err) - // return - // } - // c.Println("Validators Whitelist:") - // c.Printf("%x\n", result) - - // c.Println("===============================================================") - // }, - // }) - // shell.AddCmd(&ishell.Cmd{ // Name: "latestValidationBlock", // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index b476abb..89acf01 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -10,6 +10,7 @@ import ( "math/big" "reflect" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rlp" ) @@ -65,8 +66,8 @@ func getBlock(client *ethclient.Client, block string) { } // func calculateRlpEncoding(client *ethclient.Client, block string) { -func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []byte, prefixBlock []byte, prefixExtra []byte) { - var blockHeader header +func calculateRlpEncoding(client *ethclient.Client, block string) (rlpSignedBlock []byte, rlpUnsignedBlock []byte) { + // var blockHeader header blockNum := new(big.Int) blockNum.SetString(block, 10) @@ -77,61 +78,45 @@ func calculateRlpEncoding(client *ethclient.Client, block string) (rlpBlock []by } // Encode the orginal block header - rlpBlock, err = rlp.EncodeToBytes(&lastBlock) + _, err = rlp.EncodeToBytes(&lastBlock) if err != nil { fmt.Println("can't RLP encode requested block:", err) return } - fmt.Printf("\nEncoded Block Header:\n%+x\n", rlpBlock) - - // Marshal block into a JSON to allow manipulation of specific fields - b, err := json.MarshalIndent(lastBlock, "", " ") - if err != nil { - fmt.Printf("Error: %s", err) - return - } - fmt.Printf("\n%+x\n", b) - err = json.Unmarshal([]byte(b), &blockHeader) - if err != nil { - latestBlock(client) - fmt.Printf("Error: %s", err) - return - } - fmt.Printf("\n%v\n", blockHeader) // Generate an interface to encode the blockheader without the signature in the extraData - prefixBlock = encodeBlock(blockHeader) - fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", prefixBlock) + rlpSignedBlock = encodeSignedBlock(lastBlock) + fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", rlpSignedBlock) + rlpUnsignedBlock = encodeUnsignedBlock(lastBlock) + fmt.Printf("\nUnsigned Block Header Prefix:\n%+x\n", rlpUnsignedBlock) - // Generate an interface to encode the blockheader without the signature in the extraData - prefixExtra = encodeExtraData(blockHeader) - fmt.Printf("\nExtraData Field Prefix:\n%+x\n", prefixExtra) - - return rlpBlock, prefixBlock, prefixExtra + return rlpSignedBlock, rlpUnsignedBlock } // EncodePrefix calculate prefix of the entire signed block -func encodePrefix(blockHeader header) (prefix []byte) { - blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] - blockInterface := GenerateInterface(blockHeader) - encodedPrefixBlock := encodeBlock(blockInterface) +func encodeUnsignedBlock(lastBlock *types.Header) (encodedBlock []byte) { + lastBlock.Extra = lastBlock.Extra[:len(lastBlock.Extra)-65] + + encodedBlock, err := rlp.EncodeToBytes(&lastBlock) + if err != nil { + fmt.Println("can't RLP encode requested block:", err) + return + } + + return encodedBlock - return encodedPrefixBlock[1:3] } -// EncodeExtraData calculate prefix of the extraData with the signature -func encodeExtraData(blockHeader header) (prefix []byte) { - blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130] - encExtra, err := hex.DecodeString(blockHeader.Extra[2:]) +// EncodePrefix calculate prefix of the entire signed block +func encodeSignedBlock(lastBlock *types.Header) (encodedBlock []byte) { + encodedBlock, err := rlp.EncodeToBytes(&lastBlock) if err != nil { - fmt.Printf("Error: %s", err) + fmt.Println("can't RLP encode requested block:", err) return } - encodedExtraData := encodeBlock(encExtra) - - return encodedExtraData[0:1] + return encodedBlock } // GenerateInterface Creates an interface for a block diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index da4e3c9..1fffc32 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -2,52 +2,42 @@ package cli -import ( - "encoding/hex" - "encoding/json" - "fmt" - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" -) - -func Test_EncodePrefix(t *testing.T) { - prefixString := "0214" - expectedPrefix, _ := hex.DecodeString(prefixString) - - // read a fake block - raw, err := ioutil.ReadFile("../block.json") - if err != nil { - fmt.Println("cannot find test block.json file:", err) - return - } - - // Marshall fake block into the Header - var blockHeader header - json.Unmarshal(raw, &blockHeader) - prefix := encodePrefix(blockHeader) - - assert.Equal(t, expectedPrefix, prefix) - -} - -func Test_EncodeExtraDataPrefix(t *testing.T) { - prefixString := "a0" - expectedPrefix, _ := hex.DecodeString(prefixString) - - // read a fake block - raw, err := ioutil.ReadFile("../block.json") - if err != nil { - fmt.Println("cannot find test block.json file:", err) - return - } - - // Marshall fake block into the Header - var blockHeader header - json.Unmarshal(raw, &blockHeader) - prefix := encodeExtraData(blockHeader) - - assert.Equal(t, expectedPrefix, prefix) - -} +// func Test_EncodeSignedBlock(t *testing.T) { +// TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +// EXPECTED_SIGNED_BYTES, _ := hex.DecodeString(TEST_SIGNED) + +// // read a fake block +// raw, err := ioutil.ReadFile("./block.json") +// if err != nil { +// fmt.Println("cannot find test block.json file:", err) +// return +// } + +// // Marshall fake block into the Header +// var blockHeader header +// json.Unmarshal(raw, &blockHeader) +// SIGNED_BLOCK := encodeSignedBlock(blockHeader) + +// assert.Equal(t, EXPECTED_SIGNED_BYTES, SIGNED_BLOCK) +// } + +// func Test_EncodeUnsignedBlock(t *testing.T) { +// // TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +// TEST_UNSIGNED := "f9021aa03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1da0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +// EXPECTED_UNSIGNED_BYTES, _ := hex.DecodeString(TEST_UNSIGNED) + +// // read a fake block +// raw, err := ioutil.ReadFile("./block.json") +// if err != nil { +// fmt.Println("cannot find test block.json file:", err) +// return +// } + +// // Marshall fake block into the Header +// var blockHeader header +// json.Unmarshal(raw, &blockHeader) +// UNSIGNED_BLOCK := encodeUnsignedBlock(blockHeader) + +// assert.Equal(t, EXPECTED_UNSIGNED_BYTES, UNSIGNED_BLOCK) + +// } diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 419f7c1..4538402 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -16,6 +16,8 @@ type Setup struct { AddrFrom string `json:"rpc-from"` AccountFrom string `json:"account-from"` KeystoreFrom string `json:"keystore-from"` + Validation string `json:"validation-addr"` + ChainId string `json:"validation-chainid"` Ion string `json:"ion-addr"` } diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index 4fa8c25..e9d6b4c 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -20,7 +20,7 @@ func InitClient(addr string) (clientTo *ethclient.Client) { return } -func InitValidationContract(setup Setup, client *ethclient.Client) (Ion *contract.Ion) { +func InitIon(setup Setup, client *ethclient.Client) (Ion *contract.Ion) { // Initialise the contract address := common.HexToAddress(setup.Ion) Ion, err := contract.NewIon(address, client) @@ -30,3 +30,14 @@ func InitValidationContract(setup Setup, client *ethclient.Client) (Ion *contrac return } + +func InitValidation(setup Setup, client *ethclient.Client) (Validation *contract.Validation) { + // Initialise the contract + address := common.HexToAddress(setup.Validation) + Validation, err := contract.NewValidation(address, client) + if err != nil { + log.Fatal(err) + } + + return +} diff --git a/ion-cli/main.go b/ion-cli/main.go index 2024db6..fe22a94 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -22,12 +22,13 @@ func main() { clientTo := config.InitClient(setup.AddrTo) clientFrom := config.InitClient(setup.AddrFrom) - Ion := config.InitValidationContract(setup, clientTo) + Ion := config.InitIon(setup, clientTo) + Validation := config.InitValidation(setup, clientTo) printInfo(setup) // Launch the CLI - cli.Launch(setup, clientFrom, Ion) + cli.Launch(setup, clientFrom, Validation, Ion) } else { fmt.Print("Error: empty config!\n") os.Exit(3) @@ -40,11 +41,13 @@ func printInfo(setup config.Setup) { fmt.Println("===============================================================") fmt.Println("Ion Command Line Interface\n") fmt.Println("RPC Client [to]:") - fmt.Println("Listening on: " + setup.AddrTo) - fmt.Println("user Account: " + setup.AccountTo) - fmt.Println("Ion Contract: " + setup.Ion) - fmt.Println("\nRPC Client [from]: ") - fmt.Println("Listening on: " + setup.AddrFrom) - fmt.Println("user Account: " + setup.AccountFrom) + fmt.Println("Listening on:\t\t" + setup.AddrTo) + fmt.Println("User Account:\t\t" + setup.AccountTo) + fmt.Println("Validation Contract:\t" + setup.Validation) + fmt.Println("Validation ChainId:\t" + setup.ChainId) + fmt.Println("Ion Contract:\t\t" + setup.Ion) + fmt.Println("\nRPC Client [from]:") + fmt.Println("Listening on:\t\t" + setup.AddrFrom) + fmt.Println("User Account:\t\t" + setup.AccountFrom) fmt.Println("===============================================================") } diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index b9b2c35..7602091 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -3,6 +3,8 @@ "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613", + "validation-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", + "validation-chainid":"0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075", "rpc-from":"https://rinkeby.infura.io", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "keystore-from":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 08f8736..5a4e049 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -14,7 +14,7 @@ module.exports = async (deployer) => { .then(() => deployer.deploy(PatriciaTrie)) .then(() => PatriciaTrie.deployed) .then(() => deployer.link(PatriciaTrie, Ion)) - .then(() => deployer.deploy(Ion, "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075")) + .then(() => deployer.deploy(Ion, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) .then(() => Ion.deployed) .then(() => deployer.deploy(EventVerifier)) .then(() => EventVerifier.deployed) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..955c832 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,9377 @@ +{ + "name": "ion-truffle", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "requires": { + "call-me-maybe": "1.0.1", + "glob-to-regexp": "0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", + "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "requires": { + "any-observable": "0.3.0" + } + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + }, + "abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "requires": { + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "antlr4": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.0.tgz", + "integrity": "sha1-KX+VbdwG+DOX/AmQ7PLgzyC/u+4=" + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true, + "optional": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.11.0", + "convert-source-map": "1.5.1", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.10", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.10", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "3.2.8", + "invariant": "2.2.4", + "semver": "5.4.1" + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-preset-node6": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-node6/-/babel-preset-node6-11.0.0.tgz", + "integrity": "sha1-CDWZRRckiYWinRj21GXasWu4p9g=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "requires": { + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "home-or-tmp": "2.0.0", + "lodash": "4.17.10", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "requires": { + "source-map": "0.5.7" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.10" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.10" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.10", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "bignumber.js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true, + "optional": true + }, + "binaryextensions": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", + "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "1.2.0", + "browserify-des": "1.0.2", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sha3": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", + "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", + "requires": { + "js-sha3": "0.3.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000865", + "electron-to-chromium": "1.3.52" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, + "buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "caniuse-lite": { + "version": "1.0.30000865", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", + "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "requires": { + "check-error": "1.0.2" + } + }, + "chai-bignumber": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/chai-bignumber/-/chai-bignumber-2.0.2.tgz", + "integrity": "sha512-BIdRNjRaoRj4bMsZLKbIZPMNKqmwnzNiyxqBYDSs6dFOCs9w8OHPuUE8e1bH60i1IhOzT0NjLtCD+lKEWB1KTQ==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "requires": { + "slice-ansi": "0.0.4", + "string-width": "1.0.2" + }, + "dependencies": { + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + } + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "1.0.1" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "requires": { + "color-name": "1.1.1" + } + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" + }, + "colors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", + "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.2" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.3", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" + } + }, + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + }, + "dargs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" + }, + "death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "1.0.1" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "requires": { + "abstract-leveldown": "2.6.3" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-conflict": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "2.0.1" + } + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "2.0.2" + } + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "create-hmac": "1.1.7" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" + }, + "electron-to-chromium": { + "version": "1.3.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", + "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.5", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "tapable": "1.0.0" + } + }, + "envinfo": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-5.10.0.tgz", + "integrity": "sha512-rXbzXWvnQxy+TcqZlARbWVQwgGVVouVJgFZhLVN5htjLxl1thstrP2ZGi0pXC309AbK7gVOPU+ulz/tmpCI7iw==" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "1.0.1" + } + }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "requires": { + "string-template": "0.2.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.4.1", + "concat-stream": "1.6.2", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "3.3.10", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "eth-proof": { + "version": "git+https://github.com/Shirikatsu/eth-proof.git#9b7fdea64ec5810c9c8a74c67ab96dbf0f035567", + "requires": { + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.6", + "keccak": "1.4.0", + "leveldown": "1.9.0", + "levelup": "1.3.9", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "rlp": "2.1.0", + "web3": "0.19.1" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, + "ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "requires": { + "async": "2.6.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "1.3.6", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" + } + }, + "merkle-patricia-tree": { + "version": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "integrity": "sha512-wJSFtpBHTdtRsqrVH7UoEyQOm0KNqqmTdE3vzZ/FamCe/w3cIhv7+khBiMlNlvRsrhxIhCCeVbshaG/FMz+xiQ==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.6", + "rlp": "2.1.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + } + } + }, + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + }, + "ethereumjs-block": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.0.0.tgz", + "integrity": "sha512-doi2jH6fryGmBMzjxv2XFuJjcOUx4qZCil+qBNNdruNpDtXE1BZvC8Chj+YpuabzzTUZx5op9ob/MjXz3Xk+aw==", + "requires": { + "async": "2.6.1", + "ethereumjs-common": "0.3.1", + "ethereumjs-tx": "1.3.6", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "2.3.1" + } + }, + "ethereumjs-common": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-0.3.1.tgz", + "integrity": "sha512-o7GIMruAsif5RBe5A+dB3NhHjssYitoriiTzqHweTe5Wh45zL0kbpjPGTBQXo8dUp1QbjML40Cwsu+v7lcU6lA==" + }, + "ethereumjs-testrpc-sc": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.2.tgz", + "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", + "requires": { + "source-map-support": "0.5.6", + "webpack-cli": "2.1.5" + } + }, + "ethereumjs-tx": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.6.tgz", + "integrity": "sha512-wzsEs0mCSLqdDjqSDg6AWh1hyL8H3R/pyZxehkcCXq5MJEFXWz+eJ2jSv+3yEaLy6tXrNP7dmqS3Kyb3zAONkg==", + "requires": { + "ethereum-common": "0.0.18", + "ethereumjs-util": "5.2.0" + } + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.1.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + }, + "ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "requires": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.2" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "2.2.4" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.3", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "1.4.0", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.23", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-future": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", + "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" + }, + "fast-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", + "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "requires": { + "@mrmlnc/readdir-enhanced": "2.2.1", + "@nodelib/fs.stat": "1.1.0", + "glob-parent": "3.1.0", + "is-glob": "4.0.0", + "merge2": "1.2.2", + "micromatch": "3.1.10" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.0.0", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "requires": { + "readable-stream": "2.3.6" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "flow-parser": { + "version": "0.76.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.76.0.tgz", + "integrity": "sha512-p+K8OKiMlq8AIZH8KTydHEGUUd71AqfCL+zTJNsdHtQmX3i3eaeIysF83Ad6Oo7OQcHCj3vocb/EHYiEyq+ZBg==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "1.1.4" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "ganache-cli": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.6.tgz", + "integrity": "sha512-S+mPguwQD8dt9T0O/7mH941U9IYDbmCsoenCr31Zlr9yxjSYdNbWYGj3xsNw8CViZsMRGwIYeCaHPqK4bx2YVw==", + "dev": true, + "requires": { + "source-map-support": "0.5.6" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "gh-got": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", + "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", + "requires": { + "got": "7.1.0", + "is-plain-obj": "1.1.0" + }, + "dependencies": { + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + } + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "github-username": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", + "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", + "requires": { + "gh-got": "6.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-all": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", + "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", + "requires": { + "glob": "7.1.2", + "yargs": "1.2.6" + }, + "dependencies": { + "minimist": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" + }, + "yargs": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", + "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", + "requires": { + "minimist": "0.1.0" + } + } + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "2.19.0", + "process": "0.5.2" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "requires": { + "@sindresorhus/is": "0.7.0", + "cacheable-request": "2.1.4", + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "into-stream": "3.1.0", + "is-retry-allowed": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "mimic-response": "1.0.1", + "p-cancelable": "0.4.1", + "p-timeout": "2.0.1", + "pify": "3.0.0", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "3.0.0", + "url-to-options": "1.0.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grouped-queue": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", + "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", + "requires": { + "lodash": "4.17.10" + } + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "1.4.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "1.1.5", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.5.0" + } + }, + "http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "2.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "2.3.0", + "p-is-promise": "1.1.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "1.4.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "requires": { + "symbol-observable": "1.2.0" + }, + "dependencies": { + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-scoped": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", + "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", + "requires": { + "scoped-regex": "1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.12.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.1", + "wordwrap": "1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "requires": { + "binaryextensions": "2.1.1", + "editions": "1.3.4", + "textextensions": "2.2.0" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "js-sha3": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", + "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jscodeshift": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.1.tgz", + "integrity": "sha512-sRMollbhbmSDrR79JMAnhEjyZJlQQVozeeY9A6/KNuV26DNcuB3mGSCWXp0hks9dcwRNOELbNOiwraZaXXRk5Q==", + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "7.0.0-beta.47", + "colors": "1.3.0", + "flow-parser": "0.76.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "neo-async": "2.5.1", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.15.2", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.47", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", + "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==" + } + } + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + }, + "json-bigint-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint-string/-/json-bigint-string-1.0.0.tgz", + "integrity": "sha1-M5l4TXeLt4RAvXLHCUrw4HW75oM=", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "1.3.0", + "inherits": "2.0.3", + "nan": "2.10.0", + "safe-buffer": "5.1.2" + } + }, + "keccakjs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", + "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", + "requires": { + "browserify-sha3": "0.0.1", + "sha3": "1.2.2" + } + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "optional": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + }, + "level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "requires": { + "inherits": "2.0.3", + "level-errors": "1.0.5", + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "leveldown": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-1.9.0.tgz", + "integrity": "sha512-3MwcrnCUIuFiKp/jSrG1UqDTV4k1yH8f5HH6T9dpqCKG+lRxcfo2KwAqbzTT+TTKfCbaATeHMy9mm1y6sI3ZvA==", + "requires": { + "abstract-leveldown": "2.7.2", + "bindings": "1.3.0", + "fast-future": "1.0.2", + "nan": "2.7.0", + "prebuild-install": "2.5.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "requires": { + "deferred-leveldown": "1.2.2", + "level-codec": "7.0.1", + "level-errors": "1.0.5", + "level-iterator-stream": "1.3.1", + "prr": "1.0.1", + "semver": "5.4.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "listr": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.1.tgz", + "integrity": "sha512-MSMUUVN1f8aRnPi4034RkOqdiUlpYW+FqwFE3aL0uYNPRavkt2S2SsSpDDofn8BDpqv2RNnsdOcCHWsChcq77A==", + "requires": { + "@samverschueren/stream-to-observable": "0.3.0", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "1.1.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "6.2.1", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + }, + "rxjs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.1.tgz", + "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==", + "requires": { + "tslib": "1.9.3" + } + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" + }, + "listr-update-renderer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", + "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "requires": { + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "1.0.1" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "1.2.0" + } + }, + "mem-fs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", + "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", + "requires": { + "through2": "2.0.3", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" + } + }, + "mem-fs-editor": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-4.0.3.tgz", + "integrity": "sha512-tgWmwI/+6vwu6POan82dTjxEpwAoaj0NAFnghtVo/FcLK2/7IhPUtFUUYlwou4MOY6OtjTUJtwpfH1h+eSUziw==", + "requires": { + "commondir": "1.0.1", + "deep-extend": "0.6.0", + "ejs": "2.6.1", + "glob": "7.1.2", + "globby": "7.1.1", + "isbinaryfile": "3.0.2", + "mkdirp": "0.5.1", + "multimatch": "2.1.0", + "rimraf": "2.6.2", + "through2": "2.0.3", + "vinyl": "2.2.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.10", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + } + } + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "requires": { + "abstract-leveldown": "2.7.2", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "0.1.7", + "readable-stream": "2.3.6" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge2": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", + "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==" + }, + "merkle-patricia-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", + "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.6", + "rlp": "2.1.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "0.1.1" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", + "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==" + }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" + }, + "node-abi": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", + "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "requires": { + "semver": "5.4.1" + } + }, + "node-dir": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", + "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "requires": { + "chalk": "0.4.0", + "underscore": "1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" + } + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.0.9" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.3" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "2.0.0", + "query-string": "5.1.1", + "sort-keys": "2.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "requires": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "oboe": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", + "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", + "requires": { + "http-https": "1.0.0" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "1.2.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "original-require": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", + "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "requires": { + "p-reduce": "1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-lazy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", + "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "1.3.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-headers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", + "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", + "requires": { + "for-each": "0.3.3", + "trim": "0.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.2" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "requires": { + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, + "pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + } + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "prettier": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.7.tgz", + "integrity": "sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==" + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.2" + } + }, + "randomhex": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "read-chunk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", + "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", + "requires": { + "pify": "3.0.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" + } + }, + "recast": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.2.tgz", + "integrity": "sha512-L4f/GqxjlEJ5IZ+tdll/l+6dVi2ylysWbkgFJbMuldD6Jklgfv6zJnCpuAZDfjwHhfcd/De0dDKelsTEPQ29qA==", + "requires": { + "ast-types": "0.11.5", + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "1.8.1" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==" + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "requires": { + "regenerate": "1.4.0", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "0.5.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "req-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", + "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", + "requires": { + "req-from": "1.0.1" + } + }, + "req-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", + "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", + "requires": { + "resolve-from": "2.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + } + } + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "1.0.1" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "rlp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", + "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "requires": { + "rx-lite": "4.0.8" + } + }, + "rxjs": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", + "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "scoped-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" + }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "requires": { + "nan": "2.10.0" + } + }, + "scrypt.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", + "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", + "requires": { + "scrypt": "6.0.3", + "scryptsy": "1.2.1" + } + }, + "scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "requires": { + "pbkdf2": "3.0.16" + } + }, + "secp256k1": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.0.tgz", + "integrity": "sha512-e5QIJl8W7Y4tT6LHffVcZAxJjvpgE5Owawv6/XCYPQljE9aP2NFFddQ8OYMKhdLshNu88FfL3qCN3/xYkXGRsA==", + "requires": { + "bindings": "1.3.0", + "bip66": "1.1.5", + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "drbg.js": "1.0.1", + "elliptic": "6.4.0", + "nan": "2.10.0", + "safe-buffer": "5.1.2" + } + }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.3", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.2" + } + }, + "servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "requires": { + "body-parser": "1.18.3", + "cors": "2.8.4", + "express": "4.16.3", + "request": "2.87.0", + "xhr": "2.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "optional": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "sha3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", + "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", + "requires": { + "nan": "2.10.0" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + } + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "3.2.2" + } + }, + "sol-explore": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", + "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=" + }, + "solc": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", + "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", + "requires": { + "fs-extra": "0.30.0", + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "semver": "5.4.1", + "yargs": "4.8.1" + } + }, + "solhint": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.2.1.tgz", + "integrity": "sha512-3B0ydhkOlicyyTmKnwJC6kiwdJUXvbbDYXcy8m7rznoQPgzzkmSOsJgb9BAe+KBQP5BD3PLgcoOQ84t3FSxqsQ==", + "requires": { + "antlr4": "4.7.0", + "commander": "2.11.0", + "eslint": "4.19.1", + "glob": "7.1.2", + "ignore": "3.3.10", + "lodash": "4.17.10" + } + }, + "solidity-coverage": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.5.5.tgz", + "integrity": "sha512-WexTLFZ3NBIWGYpNgWHtFLkASdoGP0i5Q/OJzwoCpHNtG1QrJO/mxUctc5BghP8srwMN8HxCtUJtu/eyGbIOJw==", + "requires": { + "death": "1.1.0", + "ethereumjs-testrpc-sc": "6.1.2", + "istanbul": "0.4.5", + "keccakjs": "0.2.1", + "req-cwd": "1.0.1", + "shelljs": "0.7.8", + "sol-explore": "1.6.2", + "solidity-parser-sc": "0.4.11", + "tree-kill": "1.2.0", + "web3": "0.18.4" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + }, + "crypto-js": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", + "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + }, + "web3": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", + "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + } + } + }, + "solidity-parser-sc": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz", + "integrity": "sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw==", + "requires": { + "mocha": "4.1.0", + "pegjs": "0.10.0", + "yargs": "4.8.1" + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", + "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "requires": { + "buffer-from": "1.1.0", + "source-map": "0.6.1" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "requires": { + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.4.1", + "lodash": "4.17.10", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.6.1" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "textextensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", + "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "truffle": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.13.tgz", + "integrity": "sha1-vydYaYi0/4RWPt+/MrR5QUCKdq0=", + "dev": true, + "requires": { + "mocha": "4.1.0", + "original-require": "1.0.1", + "solc": "0.4.24" + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "optional": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "optional": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==" + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "2.0.0" + } + }, + "url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "utf8": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", + "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "v8-compile-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", + "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" + } + }, + "web3": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", + "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", + "requires": { + "bignumber.js": "4.1.0", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + }, + "web3-core": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.34.tgz", + "integrity": "sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4=", + "requires": { + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-core-requestmanager": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", + "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-method": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz", + "integrity": "sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-promievent": "1.0.0-beta.34", + "web3-core-subscriptions": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz", + "integrity": "sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw=", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz", + "integrity": "sha1-Afj2zyrmtvC3DDi64e90G1urIVw=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-providers-http": "1.0.0-beta.34", + "web3-providers-ipc": "1.0.0-beta.34", + "web3-providers-ws": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz", + "integrity": "sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4=", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", + "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", + "dev": true, + "requires": { + "bn.js": "4.11.6", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + } + } + }, + "web3-eth-accounts": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz", + "integrity": "sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM=", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.34", + "web3-core-helpers": "1.0.0-beta.34", + "web3-core-method": "1.0.0-beta.34", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + } + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", + "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz", + "integrity": "sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno=", + "requires": { + "web3-core-helpers": "1.0.0-beta.34", + "xhr2": "0.1.4" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz", + "integrity": "sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao=", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz", + "integrity": "sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM=", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.34", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "requires": { + "debug": "2.6.9", + "nan": "2.10.0", + "typedarray-to-buffer": "3.1.5", + "yaeti": "0.0.6" + } + } + } + }, + "web3-utils": { + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + } + } + }, + "webpack-addons": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", + "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", + "requires": { + "jscodeshift": "0.4.1" + }, + "dependencies": { + "ast-types": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "jscodeshift": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", + "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", + "requires": { + "async": "1.5.2", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "6.18.0", + "colors": "1.3.0", + "flow-parser": "0.76.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.12.9", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + } + }, + "recast": { + "version": "0.12.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", + "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", + "requires": { + "ast-types": "0.10.1", + "core-js": "2.5.7", + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" + } + } + } + }, + "webpack-cli": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.1.5.tgz", + "integrity": "sha512-CiWQR+1JS77rmyiO6y1q8Kt/O+e8nUUC9YfJ25JtSmzDwbqJV7vIsh3+QKRHVTbTCa0DaVh8iY1LBiagUIDB3g==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "diff": "3.5.0", + "enhanced-resolve": "4.1.0", + "envinfo": "5.10.0", + "glob-all": "3.1.0", + "global-modules": "1.0.0", + "got": "8.3.2", + "import-local": "1.0.0", + "inquirer": "5.2.0", + "interpret": "1.1.0", + "jscodeshift": "0.5.1", + "listr": "0.14.1", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mkdirp": "0.5.1", + "p-each-series": "1.0.0", + "p-lazy": "1.0.0", + "prettier": "1.13.7", + "supports-color": "5.4.0", + "v8-compile-cache": "2.0.0", + "webpack-addons": "1.1.5", + "yargs": "11.1.0", + "yeoman-environment": "2.3.0", + "yeoman-generator": "2.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" + } + }, + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "4.3.2", + "is-function": "1.0.1", + "parse-headers": "2.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "requires": { + "buffer-to-arraybuffer": "0.0.5", + "object-assign": "4.1.1", + "query-string": "5.1.1", + "simple-get": "2.8.1", + "timed-out": "4.0.1", + "url-set-query": "1.0.0", + "xhr": "2.5.0" + } + }, + "xhr-request-promise": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", + "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", + "requires": { + "xhr-request": "1.1.0" + } + }, + "xhr2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", + "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + }, + "yeoman-environment": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.3.0.tgz", + "integrity": "sha512-PHSAkVOqYdcR+C+Uht1SGC4eVD/9OhygYFkYaI66xF8vKIeS1RNYay+umj2ZrQeJ50tF5Q/RSO6qGDz9y3Ifug==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "globby": "8.0.1", + "grouped-queue": "0.3.3", + "inquirer": "5.2.0", + "is-scoped": "1.0.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mem-fs": "1.1.3", + "strip-ansi": "4.0.0", + "text-table": "0.2.0", + "untildify": "3.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globby": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", + "glob": "7.1.2", + "ignore": "3.3.10", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "yeoman-generator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.5.tgz", + "integrity": "sha512-rV6tJ8oYzm4mmdF2T3wjY+Q42jKF2YiiD0VKfJ8/0ZYwmhCKC9Xs2346HVLPj/xE13i68psnFJv7iS6gWRkeAg==", + "requires": { + "async": "2.6.1", + "chalk": "2.4.1", + "cli-table": "0.3.1", + "cross-spawn": "6.0.5", + "dargs": "5.1.0", + "dateformat": "3.0.3", + "debug": "3.1.0", + "detect-conflict": "1.0.1", + "error": "7.0.2", + "find-up": "2.1.0", + "github-username": "4.1.0", + "istextorbinary": "2.2.1", + "lodash": "4.17.10", + "make-dir": "1.3.0", + "mem-fs-editor": "4.0.3", + "minimist": "1.2.0", + "pretty-bytes": "4.0.2", + "read-chunk": "2.1.0", + "read-pkg-up": "3.0.0", + "rimraf": "2.6.2", + "run-async": "2.3.0", + "shelljs": "0.8.2", + "text-table": "0.2.0", + "through2": "2.0.3", + "yeoman-environment": "2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "requires": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + } + } +} diff --git a/test/ion.js b/test/ion.js index 12f090d..d2405a3 100644 --- a/test/ion.js +++ b/test/ion.js @@ -105,7 +105,6 @@ const signedHeader = [ TESTBLOCK.nonce ]; - // Remove last 65 Bytes of extraData const extraBytes = utils.hexToBytes(TESTBLOCK.extraData); const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); @@ -131,10 +130,11 @@ const unsignedHeader = [ ]; const TEST_SIGNED_HEADER = '0x' + rlp.encode(signedHeader).toString('hex'); +console.log(TEST_SIGNED_HEADER) const signedHeaderHash = Web3Utils.sha3(TEST_SIGNED_HEADER); -// assert.equal(TESTBLOCK.hash, signedHeaderHash); const TEST_UNSIGNED_HEADER = '0x' + rlp.encode(unsignedHeader).toString('hex'); +console.log(TEST_UNSIGNED_HEADER) const unsignedHeaderHash = Web3Utils.sha3(TEST_UNSIGNED_HEADER); const TESTRLPENCODING = "0xf9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" From 28aaad150f2ac36a2751f84db511e64faaffb43a Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 2 Aug 2018 13:38:29 +0100 Subject: [PATCH 103/203] Ion registered thgrough validation contract --- contracts/Ion.sol | 53 ++++++---------------------------------- contracts/Validation.sol | 7 +++++- test/ion.js | 38 ++++++++++------------------ test/validation.js | 32 +++++++++++++++--------- 4 files changed, 47 insertions(+), 83 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 316b0c4..f10cfe2 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -95,57 +95,27 @@ contract Ion { */ /* - * RegisterChain + * addChain * param: chainId Unique id of another chain to interoperate with * param: validationAddr Address of the validation contract required to make modular validation * param: _validators List of validators on the block chain * param: _genesisHash Genesis blockhash of the interop block chain * * Supplied with an id of another chain, checks if this id already exists in the known set of ids - * and adds it to the list of known chains. + * and adds it to the list of known chains. Should be called by the validation contract upon + * registration. */ - function RegisterChain(bytes32 _id, address validationAddr) public { + function addChain(bytes32 _id) public returns (bool) { require( _id != chainId, "Cannot add this chain id to chain register" ); require(!chains[_id], "Chain already exists" ); chains[_id] = true; registeredChains.push(_id); // Create mapping of registered _id to the validation address - m_validation[_id] = validationAddr; - } - - /* - * SubmitBlock - * param: _id (bytes32) Unique id of chain submitting block from - * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain without the signature in extraData - * param: _rlpSignedBlockHeader (bytes) RLP-encoded byte array of the block header from other chain with the signature in extraData - * - * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered - * and if valid the block is persisted as BlockHeader structs defined above. - */ - // function SubmitBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) public onlyRegisteredChains(_id) { - // RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); - // RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); - - // // Instantiate validation - // address validationAddr = validation_addr[_id]; - // Validation validation = Validation(validationAddr); - // validation.ValidateBlock(_id, _rlpBlockHeader, _rlpSignedBlockHeader); - - // // Append the new block to the struct - // bytes32 _parentBlockHash = SolUtils.BytesToBytes32(header[0].toBytes(), 1); - // bytes32 _blockHash = keccak256(_rlpSignedBlockHeader); - // uint256 blockHeight = m_blockheaders[_id][_parentBlockHash].blockHeight + 1; + m_validation[_id] = msg.sender; - // // Add the updates to the m_blockheaders - // m_blockheaders[_id][_blockHash].blockHeight = blockHeight; - // m_blockheaders[_id][_blockHash].prevBlockHash = _parentBlockHash; - // m_blockheaders[_id][_blockHash].txRootHash = SolUtils.BytesToBytes32(header[4].toBytes(), 1); - // m_blockheaders[_id][_blockHash].receiptRootHash = SolUtils.BytesToBytes32(header[5].toBytes(), 1); - - // addBlockHashToChain(_id, _blockHash); - - // } + return true; + } /* * CheckTxProof @@ -261,15 +231,6 @@ contract Ion { return true; } - /* - * @description when a block is submitted the root hash must be added to a mapping of chains to hashes - * @param _chainId unique identifier of the chain from which the block hails - * @param _hash root hash of the block being added - */ - function addBlockHashToChain(bytes32 _chainId, bytes32 _hash) internal { - m_blockhashes[_chainId][_hash] = true; - } - /* ======================================================================================================================== diff --git a/contracts/Validation.sol b/contracts/Validation.sol index c4402ac..30ea89b 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -5,6 +5,7 @@ pragma solidity ^0.4.23; import "./libraries/ECVerify.sol"; import "./libraries/RLP.sol"; import "./libraries/SolidityUtils.sol"; +import "./Ion.sol"; contract Validation { using RLP for RLP.RLPItem; @@ -47,7 +48,7 @@ contract Validation { * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. */ - function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { + function RegisterChain(bytes32 _id, address _ion, address[] _validators, bytes32 _genesisHash) public { require( _id != chainId, "Cannot add this chain id to chain register" ); require(!chains[_id], "Chain already exists" ); chains[_id] = true; @@ -57,8 +58,12 @@ contract Validation { m_validators[_id][_validators[i]] = true; } + Ion ion = Ion(_ion); + require(ion.addChain(_id), "Chain not added to Ion successfully!"); + m_blockheaders[_id][_genesisHash].blockHeight = 0; m_blockhashes[_id][_genesisHash] = true; + } /* diff --git a/test/ion.js b/test/ion.js index d2405a3..0c4765d 100644 --- a/test/ion.js +++ b/test/ion.js @@ -85,7 +85,7 @@ const TESTBLOCK = { uncles: [] } -const TEST_VALIDATORS = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"] +const VALIDATORS = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"] const signedHeader = [ TESTBLOCK.parentHash, @@ -130,11 +130,9 @@ const unsignedHeader = [ ]; const TEST_SIGNED_HEADER = '0x' + rlp.encode(signedHeader).toString('hex'); -console.log(TEST_SIGNED_HEADER) const signedHeaderHash = Web3Utils.sha3(TEST_SIGNED_HEADER); const TEST_UNSIGNED_HEADER = '0x' + rlp.encode(unsignedHeader).toString('hex'); -console.log(TEST_UNSIGNED_HEADER) const unsignedHeaderHash = Web3Utils.sha3(TEST_UNSIGNED_HEADER); const TESTRLPENCODING = "0xf9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" @@ -151,9 +149,7 @@ const TRIG_FIRED_RINKEBY_TXHASH = "0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fc const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 const TRIG_CALLED_BY = "0x279884e133f9346f2fad9cc158222068221b613e"; -const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; const GENESIS_HASH = TESTBLOCK.parentHash; -// const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; contract('Ion.js', (accounts) => { @@ -169,26 +165,25 @@ contract('Ion.js', (accounts) => { const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await ion.RegisterChain(TESTCHAINID, validation.address); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); let chain = await ion.chains(TESTCHAINID); assert.equal(chain, true); // Fail adding id of this chain - await ion.RegisterChain(DEPLOYEDCHAINID, validation.address).should.be.rejected; + await validation.RegisterChain(DEPLOYEDCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already registered - await ion.RegisterChain(TESTCHAINID, validation.address).should.be.rejected; + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; }) it('Check Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + const val = await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); @@ -199,8 +194,7 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -218,8 +212,7 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -233,8 +226,7 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -252,8 +244,7 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -267,8 +258,7 @@ contract('Ion.js', (accounts) => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -302,8 +292,7 @@ contract('Ion.js', (accounts) => { const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -325,8 +314,7 @@ contract('Ion.js', (accounts) => { const functionContract = await Function.new(ion.address, verifier.address); // Register chain and submit block to Ion - await ion.RegisterChain(TESTCHAINID, validation.address); - await validation.RegisterChain(TESTCHAINID, TEST_VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); diff --git a/test/validation.js b/test/validation.js index fb97300..0ce9861 100644 --- a/test/validation.js +++ b/test/validation.js @@ -10,6 +10,7 @@ const Web3Accounts = require('web3-eth-accounts'); const rlp = require('rlp'); const Validation = artifacts.require("Validation"); +const Ion = artifacts.require("Ion"); const Recover = artifacts.require("Recover"); const web3 = new Web3(); @@ -61,26 +62,28 @@ contract('Validation.js', (accounts) => { }) it('Test: Register Chain', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); let chain = await validation.chains(TESTCHAINID); assert.equal(chain, true); // Fail adding id of this chain - await validation.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(DEPLOYEDCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already initialised - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; }) it('Test: Register Chain - Check Validators', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); let validators = await validation.m_validators.call(TESTCHAINID, VALIDATORS[0]); assert.equal(validators, true); @@ -88,10 +91,11 @@ contract('Validation.js', (accounts) => { it('Test: Register Chain - Check Genesis Hash', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); let header = await validation.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); let blockHeight = header[0]; @@ -101,9 +105,10 @@ contract('Validation.js', (accounts) => { }) it('Test: Authentic Submission Happy Path - SubmitBlock()', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -176,9 +181,10 @@ contract('Validation.js', (accounts) => { // Here the block header is signed off chain but by a whitelisted validator it('Test: Authentic Submission Off-Chain Signature - SubmitBlock()', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -286,9 +292,10 @@ contract('Validation.js', (accounts) => { // Here the block header is signed off chain but by a whitelisted validator who alters the block it('Test: Inauthentic Block Submission - SubmitBlock()', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -407,9 +414,10 @@ contract('Validation.js', (accounts) => { // Here the block header is signed off chain but by a a non-whitelisted validator it('Test: Fail Submit Block unkown validator - SubmitBlock()', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -503,9 +511,10 @@ contract('Validation.js', (accounts) => { }) it('Test: Fail Submit Block from unknown chain - SubmitBlock()', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -565,9 +574,10 @@ contract('Validation.js', (accounts) => { }) it('Test: Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); From ab3059dfeb05fb59c518938b773d1ddc6078822d Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Thu, 2 Aug 2018 21:13:01 +0100 Subject: [PATCH 104/203] WIP: CheckRootsProof not working properly :( dont know why --- ion-cli/flow_test/client.go | 86 +++++++++++++ ion-cli/flow_test/client_test.go | 68 ++++++++++ ion-cli/flow_test/trie.go | 111 +++++++++++++++++ ion-cli/flow_test/utils.go | 12 ++ ion-cli/flow_test/utils_test.go | 208 ++++++++++++++++++++++++++++++- 5 files changed, 481 insertions(+), 4 deletions(-) create mode 100644 ion-cli/flow_test/client.go create mode 100644 ion-cli/flow_test/client_test.go create mode 100644 ion-cli/flow_test/trie.go diff --git a/ion-cli/flow_test/client.go b/ion-cli/flow_test/client.go new file mode 100644 index 0000000..b841f07 --- /dev/null +++ b/ion-cli/flow_test/client.go @@ -0,0 +1,86 @@ +package ionflow + +import ( + "context" + "encoding/json" + "fmt" + "log" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" +) + +// Client gets client or fails if no connection +func Client(url string) *ethclient.Client { + client, err := ethclient.Dial(url) + if err != nil { + log.Fatal("Client failed to connect: ", err) + } else { + fmt.Println("Connected to: ", url) + } + return client +} + +// GetBlockTxReceipts get the receipts for all the transactions in a block +func GetBlockTxReceipts(ec *ethclient.Client, block *types.Block) []*types.Receipt { + var receiptsArr []*types.Receipt + for _, tx := range block.Transactions() { + receipt, err := ec.TransactionReceipt(context.Background(), tx.Hash()) + if err != nil { + log.Fatal("TransactionReceipt ERROR:", err) + } + receiptsArr = append(receiptsArr, receipt) + } + return receiptsArr +} + +// ------- +// Since you can't get a block by giving it the transaction hash in go-ethereum +// the only solution was to replicate their code and add that feature to it +// really annoying!!! +// ------- + +// ClientRPC RPC Client gets an RPC client (useful to get the block number out of a transaction) +func ClientRPC(url string) *rpc.Client { + c, err := rpc.DialContext(context.Background(), url) + if err != nil { + log.Fatal("RPC Client failed to connect: ", err) + } + return c +} + +type rpcTransaction struct { + tx *types.Transaction + txExtraInfo +} + +type txExtraInfo struct { + BlockNumber *string `json:"blockNumber,omitempty"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + From *common.Address `json:"from,omitempty"` +} + +func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error { + if err := json.Unmarshal(msg, &tx.tx); err != nil { + return err + } + return json.Unmarshal(msg, &tx.txExtraInfo) +} + +// BlockNumberByTransactionHash gets a block number by a transaction hash in that block +func BlockNumberByTransactionHash(ctx context.Context, c *rpc.Client, txHash common.Hash) (*string, *types.Transaction, error) { + var json *rpcTransaction + var err error + err = c.CallContext(ctx, &json, "eth_getTransactionByHash", txHash) + if err != nil { + return nil, nil, err + } else if json == nil { + return nil, nil, ethereum.NotFound + } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { + return nil, nil, fmt.Errorf("server returned transaction without signature") + } + return json.BlockNumber, json.tx, nil +} diff --git a/ion-cli/flow_test/client_test.go b/ion-cli/flow_test/client_test.go new file mode 100644 index 0000000..5edcc1b --- /dev/null +++ b/ion-cli/flow_test/client_test.go @@ -0,0 +1,68 @@ +package ionflow + +import ( + "context" + "math/big" + "testing" +) + +const URL = "https://mainnet.infura.io" + +// NOTE: This tests depend on an external network (not really good) + +func TestClient(t *testing.T) { + client := Client(URL) + client.Close() +} + +func TestGetReceipts(t *testing.T) { + expectedTotalReceipts := 92 + + client := Client(URL) + defer client.Close() + + blockNumber := big.NewInt(6021002) + block, err := client.BlockByNumber(context.Background(), blockNumber) + if err != nil { + t.Error(err) + } + + receiptArr := GetBlockTxReceipts(client, block) + + if len(receiptArr) != expectedTotalReceipts { + t.Errorf("Got %d receipts and expected %d receipts!\n", len(receiptArr), expectedTotalReceipts) + } +} + +func TestBlockNumberByTransactionHash(t *testing.T) { + client := Client(URL) + defer client.Close() + + blockNumber := big.NewInt(6021002) + block, err := client.BlockByNumber(context.Background(), blockNumber) + if err != nil { + t.Fatal(err) + } + txArr := block.Transactions() + tx := txArr[0] + txHash := tx.Hash() + + // needs to use the ClientRPC because we make the request directly to the RPC in order to get the blocknumber + clientRPC := ClientRPC(URL) + defer clientRPC.Close() + + bNumber, _, err := BlockNumberByTransactionHash(context.Background(), clientRPC, txHash) + if err != nil { + t.Fatal(err) + } + + var bNumberInt big.Int + t.Log(bNumber) + t.Log((*bNumber)[2:]) + bNumberInt.SetString((*bNumber)[2:], 16) + t.Log(bNumberInt) + + if blockNumber.Cmp(&bNumberInt) != 0 { + t.Errorf("Blocknumber retrieved by transaction hash is not right. It expected %s but got %s\n", blockNumber.String(), bNumberInt.String()) + } +} diff --git a/ion-cli/flow_test/trie.go b/ion-cli/flow_test/trie.go new file mode 100644 index 0000000..bb72cd3 --- /dev/null +++ b/ion-cli/flow_test/trie.go @@ -0,0 +1,111 @@ +package ionflow + +import ( + "log" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +// ReceiptTrie generate trie for receipts +// TODO: the argument should be of type interface so that this is a generic function +func ReceiptTrie(receipts []*types.Receipt) *trie.Trie { + var receiptRLPidxArr, receiptRLPArr [][]byte + for idx, receipt := range receipts { + idxRLP, err := rlp.EncodeToBytes(uint(idx)) + if err != nil { + log.Fatalf("ReceiptTrie RLP error: %v", err) + } + txRLP, err := rlp.EncodeToBytes(receipt) + if err != nil { + log.Fatalf("ReceiptTrie RLP error: %v", err) + } + + receiptRLPidxArr = append(receiptRLPidxArr, idxRLP) + receiptRLPArr = append(receiptRLPArr, txRLP) + } + + trieObj := generateTrie(receiptRLPidxArr, receiptRLPArr) + + return trieObj +} + +// TxTrie generated Trie out of transaction array +// TODO: the argument should be of type interface so that this is a generic function +func TxTrie(transactions []*types.Transaction) *trie.Trie { + var txRLPIdxArr, txRLPArr [][]byte + for idx, tx := range transactions { + idxRLP, err := rlp.EncodeToBytes(uint(idx)) + if err != nil { + log.Fatalf("TxTrie RLP error: %v", err) + } + txRLP, err := rlp.EncodeToBytes(tx) + if err != nil { + log.Fatalf("TxTrie RLP error: %v", err) + } + + txRLPIdxArr = append(txRLPIdxArr, idxRLP) + txRLPArr = append(txRLPArr, txRLP) + } + + trieObj := generateTrie(txRLPIdxArr, txRLPArr) + + return trieObj +} + +func generateTrie(paths [][]byte, values [][]byte) *trie.Trie { + if len(paths) != len(values) { + log.Fatal("Paths array and Values array have different lengths when generating Trie") + } + + trieDB := trie.NewDatabase(ethdb.NewMemDatabase()) + trieObj, _ := trie.New(common.Hash{}, trieDB) // empty trie + + for idx := range paths { + p := paths[idx] + v := values[idx] + + trieObj.Update(p, v) // update trie with the rlp encode index and the rlp encoded transaction + } + + _, err := trieObj.Commit(nil) // commit to database (which in this case is stored in memory) + if err != nil { + log.Fatalf("commit error: %v", err) + } + + return trieObj +} + +// Proof creates an array of the proof pathj ordered +func Proof(trie *trie.Trie, path []byte) []byte { + proof := generateProof(trie, path) + proofRLP, err := rlp.EncodeToBytes(proof) + if err != nil { + log.Fatal("ERROR encoding proof: ", err) + } + return proofRLP +} + +func generateProof(trie *trie.Trie, path []byte) []interface{} { + proof := ethdb.NewMemDatabase() + err := trie.Prove(path, 0, proof) + if err != nil { + log.Fatal("ERROR failed to create proof") + } + + var proofArr []interface{} + for nodeIt := trie.NodeIterator(nil); nodeIt.Next(true); { + if val, err := proof.Get(nodeIt.Hash().Bytes()); val != nil && err == nil { + var decodedVal interface{} + err = rlp.DecodeBytes(val, &decodedVal) + if err != nil { + log.Fatalf("ERROR(%s) failed decoding RLP: 0x%0x\n", err, val) + } + proofArr = append(proofArr, decodedVal) + } + } + return proofArr +} diff --git a/ion-cli/flow_test/utils.go b/ion-cli/flow_test/utils.go index f3f2c84..0756e22 100644 --- a/ion-cli/flow_test/utils.go +++ b/ion-cli/flow_test/utils.go @@ -25,6 +25,12 @@ type ContractInstance struct { Address common.Address } +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- +// GENERIC UTIL FUNCTIONS +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + func getContractBytecodeAndABI(c *compiler.Contract) (string, string) { cABIBytes, err := json.Marshal(c.Info.AbiDefinition) if err != nil { @@ -184,6 +190,12 @@ func TransactionContract( return signedTx } +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- +// ION SPECIFIC FUNCTIONS +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + // CompileAndDeployIon specific compile and deploy ion contract func CompileAndDeployIon( ctx context.Context, diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index c48c5ad..b417eec 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -3,14 +3,18 @@ package ionflow import ( "bytes" "context" + "encoding/json" "log" "math/big" "testing" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rlp" ) func TestCompileAndDeployIon(t *testing.T) { @@ -106,7 +110,7 @@ func TestRegisterChain(t *testing.T) { } methodName := "chains" - out := new(bool) + var isChainRegistered bool CallContract( ctx, blockchain, @@ -114,11 +118,207 @@ func TestRegisterChain(t *testing.T) { userAAddr, ionContractInstance.Address, methodName, - out, + &isChainRegistered, chainIDA, ) - if !*out { - t.Log("ERROR expecting value of chains(validation.address) to be true, but it was ", *out) + if !isChainRegistered { + t.Log("ERROR expecting value of chains(validation.address) to be true, but it was ", isChainRegistered) } } + +func TestVerifyTx(t *testing.T) { + ctx := context.Background() + + testValidators := [7]common.Hash{ + common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), + common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), + common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), + common.HexToHash("0xb279182d99e65703f0076e4812653aab85fca0f0"), + common.HexToHash("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), + common.HexToHash("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), + common.HexToHash("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), + } + + deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") + testChainID := common.HexToHash("0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254") + + urlEventChain := "https://rinkeby.infura.io" + txHashWithEvent := common.HexToHash("0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") + + userKey, _ := crypto.GenerateKey() + userAddr := crypto.PubkeyToAddress(userKey.PublicKey) + userIntialBalance := big.NewInt(1000000000) + + // --------------------------------------------- + // GET BLOCK WITH EVENT FROM RINKEBY CHAIN + // --------------------------------------------- + + clientRPC := ClientRPC(urlEventChain) + defer clientRPC.Close() + + blockNumberStr, _, err := BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) + if err != nil { + t.Fatal("ERROR couldn't find block by tx hash: ", err) + } + + var blockNumber big.Int + blockNumber.SetString((*blockNumberStr)[2:], 16) + + client := ethclient.NewClient(clientRPC) + eventTxBlockNumber := blockNumber + block, err := client.BlockByNumber(ctx, &eventTxBlockNumber) + if err != nil { + t.Fatal("ERROR retriving block: ", err) + } + + // --------------------------------------------- + // START BLOCKCHAIN SIMULATOR + // --------------------------------------------- + alloc := make(core.GenesisAlloc) + alloc[userAddr] = core.GenesisAccount{Balance: userIntialBalance} + blockchain := backends.NewSimulatedBackend(alloc) + + // --------------------------------------------- + // COMPILE AND DEPLOY ION + // --------------------------------------------- + contractChan := CompileAndDeployIon(ctx, blockchain, userKey, deployedChainID) + blockchain.Commit() + <-contractChan // PatriciaTrie libraryContractInstance + blockchain.Commit() + ionContractInstance := <-contractChan + + // --------------------------------------------- + // COMPILE AND DEPLOY VALIDATION + // --------------------------------------------- + contractChan = CompileAndDeployValidation(ctx, blockchain, userKey, deployedChainID) + blockchain.Commit() + validationContractInstance := <-contractChan + + // --------------------------------------------- + // REGISTER CHAIN ON ION + // --------------------------------------------- + var validationContractAddr [32]byte + copy(validationContractAddr[:], validationContractInstance.Address.Bytes()) + txRegisterChainIon := TransactionContract( + ctx, + blockchain, + userKey, + ionContractInstance.Contract, + ionContractInstance.Address, + nil, + uint64(3000000), + "RegisterChain", + testChainID, + validationContractAddr, + ) + blockchain.Commit() + registerChainIonReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainIon) + if err != nil || registerChainIonReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // REGISTER CHAIN ON VALIDATION + // --------------------------------------------- + var genesisHash [32]byte + copy(genesisHash[:], block.ParentHash().Bytes()) + txRegisterChainValidation := TransactionContract( + ctx, + blockchain, + userKey, + validationContractInstance.Contract, + validationContractInstance.Address, + nil, + uint64(3000000), + "RegisterChain", + testChainID, + testValidators, + genesisHash, + ) + blockchain.Commit() + registerChainValidationReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainValidation) + if err != nil || registerChainValidationReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // SUBMIT BLOCK ON VALIDATION + // --------------------------------------------- + blockHeader := block.Header() + extraData := blockHeader.Extra + unsignedExtraData := extraData[:len(extraData)-(64+1)] // 64 bytes + 1 vanity byte + signedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) + blockHeader.Extra = unsignedExtraData + unsignedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) + txSubmitBlockValidation := TransactionContract( + ctx, + blockchain, + userKey, + validationContractInstance.Contract, + validationContractInstance.Address, + nil, + uint64(3000000), + "SubmitBlock", + testChainID, + unsignedBlockHeaderRLP, + signedBlockHeaderRLP, + ) + + blockchain.Commit() + submitBlockValidationReceipt, err := bind.WaitMined(ctx, blockchain, txSubmitBlockValidation) + if err != nil || submitBlockValidationReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // FIXME + // CHECK ROOTS PROOF ON ION + // let tx = await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); + // --------------------------------------------- + blockHash := block.Hash() + txTrie := TxTrie(block.Transactions()) + blockReceipts := GetBlockTxReceipts(client, block) + receiptTrie := ReceiptTrie(blockReceipts) + + txKey := []byte{0x01} + txProofArr := Proof(txTrie, txKey) + receiptKey := []byte{0x01} + receiptProofArr := Proof(receiptTrie, receiptKey) + + checkRootsProofIon := TransactionContract( + ctx, + blockchain, + userKey, + ionContractInstance.Contract, + ionContractInstance.Address, + nil, + uint64(3000000), + "CheckRootsProof", + testChainID, + blockHash, + txProofArr, + receiptProofArr, + ) + + blockchain.Commit() + chackRootsProofIonReceipt, err := bind.WaitMined(ctx, blockchain, checkRootsProofIon) + + t.Logf("Block Hash: % 0x\n", blockHash) + t.Logf("Block Transactions RLP: %0x\n", txProofArr) + t.Logf("Block Receipts RLP: %0x\n", receiptProofArr) + reJSON, _ := json.Marshal(chackRootsProofIonReceipt) + t.Logf("%#v\n", chackRootsProofIonReceipt) + t.Logf("Receipt JSON: %s\n", reJSON) + t.Logf("Gas Used: %d\n", chackRootsProofIonReceipt.GasUsed) + + if err != nil || chackRootsProofIonReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment", err) + } + + // ==================================================================================================== + // TODO + // let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); + // let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, "0x"+nodes.toString('hex'), TEST_PATH); + // let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); +} From c4122853d5d51c4f7b1256e6812b971a7e5dd521 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Fri, 3 Aug 2018 14:03:56 +0100 Subject: [PATCH 105/203] fixed copying wrong address size bug --- ion-cli/flow_test/utils_test.go | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index b417eec..ca6cd0a 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -3,7 +3,6 @@ package ionflow import ( "bytes" "context" - "encoding/json" "log" "math/big" "testing" @@ -198,7 +197,7 @@ func TestVerifyTx(t *testing.T) { // --------------------------------------------- // REGISTER CHAIN ON ION // --------------------------------------------- - var validationContractAddr [32]byte + var validationContractAddr [20]byte copy(validationContractAddr[:], validationContractInstance.Address.Bytes()) txRegisterChainIon := TransactionContract( ctx, @@ -272,9 +271,7 @@ func TestVerifyTx(t *testing.T) { } // --------------------------------------------- - // FIXME // CHECK ROOTS PROOF ON ION - // let tx = await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); // --------------------------------------------- blockHash := block.Hash() txTrie := TxTrie(block.Transactions()) @@ -303,15 +300,6 @@ func TestVerifyTx(t *testing.T) { blockchain.Commit() chackRootsProofIonReceipt, err := bind.WaitMined(ctx, blockchain, checkRootsProofIon) - - t.Logf("Block Hash: % 0x\n", blockHash) - t.Logf("Block Transactions RLP: %0x\n", txProofArr) - t.Logf("Block Receipts RLP: %0x\n", receiptProofArr) - reJSON, _ := json.Marshal(chackRootsProofIonReceipt) - t.Logf("%#v\n", chackRootsProofIonReceipt) - t.Logf("Receipt JSON: %s\n", reJSON) - t.Logf("Gas Used: %d\n", chackRootsProofIonReceipt.GasUsed) - if err != nil || chackRootsProofIonReceipt.Status == 0 { t.Fatal("ERROR while waiting for contract deployment", err) } From c533c061bd7a0539feb93884e0a28105dc006b90 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 3 Aug 2018 14:27:49 +0100 Subject: [PATCH 106/203] Improved the CLI framework --- .travis.yml | 1 + IonCliScript.txt | 6 +- abi/Function.bin | 2 +- abi/Ion.abi | 2 +- abi/Ion.bin | 2 +- abi/IonCompatible.bin | 2 +- abi/Validation.abi | 2 +- abi/Validation.bin | 2 +- contracts/Ion.sol | 21 +--- contracts/Validation.sol | 36 +++++-- ion-cli/Makefile | 4 + ion-cli/cli/cli.go | 222 +++++++++++++++++++-------------------- ion-cli/cli/rpc.go | 12 ++- ion-cli/cli/rpc_test.go | 89 +++++++++------- ion-cli/config/config.go | 3 +- ion-cli/config/init.go | 11 ++ ion-cli/main.go | 4 +- ion-cli/rinkeby.json | 1 + package.json | 2 +- test/ion.js | 33 ------ 20 files changed, 233 insertions(+), 224 deletions(-) diff --git a/.travis.yml b/.travis.yml index a868acc..f37fda1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ matrix: - npm run test - cd ./ion-cli - go get -t ./... + - make build - make test - make integration-test diff --git a/IonCliScript.txt b/IonCliScript.txt index 28dcbe5..b0f2ca7 100644 --- a/IonCliScript.txt +++ b/IonCliScript.txt @@ -1,4 +1,6 @@ registerValidationChain: chainId - 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 - validators - "["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"]" - genesis - 0x3471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35 + validators - "["0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"]" + genesis - 0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177 + +0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91 \ No newline at end of file diff --git a/abi/Function.bin b/abi/Function.bin index daafd9a..7148282 100644 --- a/abi/Function.bin +++ b/abi/Function.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051604080610b28833981018060405281019080805190602001909291908051906020019092919050505081806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610a57806100d16000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d0fdb2b314610046575b600080fd5b34801561005257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff1916906020019092919050505061022d565b604051808215151515815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f484c1f78b8b88876040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180856000191660001916815260200184600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156102fb5780820151818401526020810190506102e0565b50505050905090810190601f1680156103285780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156103b157600080fd5b505af11580156103c5573d6000803e3d6000fd5b505050506040513d60208110156103db57600080fd5b810190808051906020019092919050505015156103f457fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663affd8be98b8b89898c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156104c55780820151818401526020810190506104aa565b50505050905090810190601f1680156104f25780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561052b578082015181840152602081019050610510565b50505050905090810190601f1680156105585780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015610591578082015181840152602081019050610576565b50505050905090810190601f1680156105be5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1580156105e357600080fd5b505af11580156105f7573d6000803e3d6000fd5b505050506040513d602081101561060d57600080fd5b8101908080519060200190929190505050151561062657fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bec205b98b8b87878c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106f75780820151818401526020810190506106dc565b50505050905090810190601f1680156107245780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561075d578082015181840152602081019050610742565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b838110156107c35780820151818401526020810190506107a8565b50505050905090810190601f1680156107f05780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b15801561081557600080fd5b505af1158015610829573d6000803e3d6000fd5b505050506040513d602081101561083f57600080fd5b8101908080519060200190929190505050151561085857fe5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357064c3d8986856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200180602001836bffffffffffffffffffffffff19166bffffffffffffffffffffffff19168152602001828103825284818151815260200191508051906020019080838360005b8381101561094c578082015181840152602081019050610931565b50505050905090810190601f1680156109795780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d60208110156109c457600080fd5b8101908080519060200190929190505050156109eb576109e26109fd565b600190506109f0565b600090505b9998505050505050505050565b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e60405160405180910390a15600a165627a7a723058209ee022fb1f514b1f2780626ece41ad8a233f24fa4fe14d217ede8653e42ad6dc0029 \ No newline at end of file +608060405234801561001057600080fd5b50604051604080610b28833981018060405281019080805190602001909291908051906020019092919050505081806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610a57806100d16000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d0fdb2b314610046575b600080fd5b34801561005257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919080356bffffffffffffffffffffffff19169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356bffffffffffffffffffffffff1916906020019092919050505061022d565b604051808215151515815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f484c1f78b8b88876040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180856000191660001916815260200184600019166000191681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156102fb5780820151818401526020810190506102e0565b50505050905090810190601f1680156103285780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156103b157600080fd5b505af11580156103c5573d6000803e3d6000fd5b505050506040513d60208110156103db57600080fd5b810190808051906020019092919050505015156103f457fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663affd8be98b8b89898c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156104c55780820151818401526020810190506104aa565b50505050905090810190601f1680156104f25780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561052b578082015181840152602081019050610510565b50505050905090810190601f1680156105585780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015610591578082015181840152602081019050610576565b50505050905090810190601f1680156105be5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1580156105e357600080fd5b505af11580156105f7573d6000803e3d6000fd5b505050506040513d602081101561060d57600080fd5b8101908080519060200190929190505050151561062657fe5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bec205b98b8b87878c6040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086600019166000191681526020018560001916600019168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b838110156106f75780820151818401526020810190506106dc565b50505050905090810190601f1680156107245780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b8381101561075d578082015181840152602081019050610742565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b838110156107c35780820151818401526020810190506107a8565b50505050905090810190601f1680156107f05780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b15801561081557600080fd5b505af1158015610829573d6000803e3d6000fd5b505050506040513d602081101561083f57600080fd5b8101908080519060200190929190505050151561085857fe5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357064c3d8986856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200180602001836bffffffffffffffffffffffff19166bffffffffffffffffffffffff19168152602001828103825284818151815260200191508051906020019080838360005b8381101561094c578082015181840152602081019050610931565b50505050905090810190601f1680156109795780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d60208110156109c457600080fd5b8101908080519060200190929190505050156109eb576109e26109fd565b600190506109f0565b600090505b9998505050505050505050565b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e60405160405180910390a15600a165627a7a7230582066acb6d2022bd3fc24245324749ec602be3ee529c14763c73ce2aec4c2444c790029 \ No newline at end of file diff --git a/abi/Ion.abi b/abi/Ion.abi index 221cda6..eb13ccc 100644 --- a/abi/Ion.abi +++ b/abi/Ion.abi @@ -1 +1 @@ -[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"registeredChains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"validationAddr","type":"address"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_validation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckReceiptProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_txNodes","type":"bytes"},{"name":"_receiptNodes","type":"bytes"}],"name":"CheckRootsProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"},{"indexed":false,"name":"proofType","type":"uint256"}],"name":"VerifiedProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"registeredChains","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckTxProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_validation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_value","type":"bytes"},{"name":"_parentNodes","type":"bytes"},{"name":"_path","type":"bytes"}],"name":"CheckReceiptProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"addChain","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"blockHeight","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_blockHash","type":"bytes32"},{"name":"_txNodes","type":"bytes"},{"name":"_receiptNodes","type":"bytes"}],"name":"CheckRootsProof","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"chainId","type":"bytes32"},{"indexed":false,"name":"blockHash","type":"bytes32"},{"indexed":false,"name":"proofType","type":"uint256"}],"name":"VerifiedProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Ion.bin b/abi/Ion.bin index 9ae5130..db3a1c2 100644 --- a/abi/Ion.bin +++ b/abi/Ion.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50604051602080611fde83398101806040528101908080519060200190929190505050806001816000191690555050611f908061004e6000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d3146100ca5780634b3550301461011357806353fe62e61461016a57806395b0ea00146101d35780639a8a059214610224578063affd8be914610257578063b64b633614610380578063bec205b9146103f1578063c18de0ef1461051a578063e79b136c14610563578063f22a195e146105e3578063f44ff71214610616578063f484c1f714610641575b600080fd5b3480156100d657600080fd5b506100f560048036038101908080359060200190929190505050610724565b60405180826000191660001916815260200191505060405180910390f35b34801561011f57600080fd5b5061015060048036038101908080356000191690602001909291908035600019169060200190929190505050610747565b604051808215151515815260200191505060405180910390f35b34801561017657600080fd5b506101b96004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610776565b604051808215151515815260200191505060405180910390f35b3480156101df57600080fd5b506102226004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107a5565b005b34801561023057600080fd5b506102396109af565b60405180826000191660001916815260200191505060405180910390f35b34801561026357600080fd5b5061036660048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506109b5565b604051808215151515815260200191505060405180910390f35b34801561038c57600080fd5b506103af6004803603810190808035600019169060200190929190505050610f45565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103fd57600080fd5b5061050060048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610f78565b604051808215151515815260200191505060405180910390f35b34801561052657600080fd5b506105496004803603810190808035600019169060200190929190505050611508565b604051808215151515815260200191505060405180910390f35b34801561056f57600080fd5b506105a060048036038101908080356000191690602001909291908035600019169060200190929190505050611528565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b3480156105ef57600080fd5b506105f8611565565b60405180826000191660001916815260200191505060405180910390f35b34801561062257600080fd5b5061062b61156b565b6040518082815260200191505060405180910390f35b34801561064d57600080fd5b5061070a60048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050611571565b604051808215151515815260200191505060405180910390f35b60028181548110151561073357fe5b906000526020600020016000915090505481565b60066020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6001546000191682600019161415151561084d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60046000836000191660001916815260200190815260200160002060009054906101000a900460ff161515156108eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160046000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555060028290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055508060056000846000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60015481565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610a58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610b2157600080fd5b505af1158015610b35573d6000803e3d6000fd5b505050506040513d6020811015610b4b57600080fd5b81019080805190602001909291905050501515610bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610c9557600080fd5b505af1158015610ca9573d6000803e3d6000fd5b505050506040513d6020811015610cbf57600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610d71578082015181840152602081019050610d56565b50505050905090810190601f168015610d9e5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610dd7578082015181840152602081019050610dbc565b50505050905090810190601f168015610e045780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610e3d578082015181840152602081019050610e22565b50505050905090810190601f168015610e6a5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610e8c57600080fd5b505af4158015610ea0573d6000803e3d6000fd5b505050506040513d6020811015610eb657600080fd5b81019080805190602001909291905050501515610ecf57fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c60006002811115610eff57fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060008760046000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561101b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156110e457600080fd5b505af11580156110f8573d6000803e3d6000fd5b505050506040513d602081101561110e57600080fd5b81019080805190602001909291905050501515611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561125857600080fd5b505af115801561126c573d6000803e3d6000fd5b505050506040513d602081101561128257600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015611334578082015181840152602081019050611319565b50505050905090810190601f1680156113615780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b8381101561139a57808201518184015260208101905061137f565b50505050905090810190601f1680156113c75780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b838110156114005780820151818401526020810190506113e5565b50505050905090810190601f16801561142d5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561144f57600080fd5b505af4158015611463573d6000803e3d6000fd5b505050506040513d602081101561147957600080fd5b8101908080519060200190929190505050151561149257fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c600160028111156114c257fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60046020528060005260406000206000915054906101000a900460ff1681565b6007602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154905084565b60005481565b60035481565b6000806000808760046000826000191660001916815260200190815260200160002060009054906101000a900460ff161515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060056000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156116de57600080fd5b505af11580156116f2573d6000803e3d6000fd5b505050506040513d602081101561170857600080fd5b8101908080519060200190929190505050151561178d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600560008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1696508673ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561185257600080fd5b505af1158015611866573d6000803e3d6000fd5b505050506040513d602081101561187c57600080fd5b810190808051906020019092919050505095508673ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561191657600080fd5b505af115801561192a573d6000803e3d6000fd5b505050506040513d602081101561194057600080fd5b8101908080519060200190929190505050945061195c8a6119fe565b60001916866000191614151561196e57fe5b611977896119fe565b60001916856000191614151561198957fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c6002808111156119b857fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001975050505050505050949350505050565b6000611a08611f0f565b606080611a1485611ab1565b9250611a1f83611b0c565b9150611a42826000815181101515611a3357fe5b90602001906020020151611bc9565b9050806040518082805190602001908083835b602083101515611a7a5780518252602082019150602081019050602083039250611a55565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b611ab9611f0f565b600080835191506000821415611ae75760408051908101604052806000815260200160008152509250611b05565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000611b18611f29565b6000611b2385611c2e565b1515611b2e57600080fd5b611b3785611c60565b925082604051908082528060200260200182016040528015611b7357816020015b611b60611f4a565b815260200190600190039081611b585790505b509350611b7f85611cda565b91505b611b8b82611d22565b15611bc157611b9982611d4c565b8482815181101515611ba757fe5b906020019060200201819052508080600101915050611b82565b505050919050565b60606000826020015190506000811415611be257611c28565b806040519080825280601f01601f191660200182016040528015611c155781602001602082028038833980820191505090505b509150611c2783600001518383611da8565b5b50919050565b600080600083602001511415611c475760009150611c5a565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611c7287611c2e565b1515611c815760009550611cd0565b86600001519350835160001a9450611c9887611de9565b840192506001876020015185010391505b8183111515611ccc57611cbb83611e75565b830192508080600101915050611ca9565b8095505b5050505050919050565b611ce2611f29565b6000611ced83611c2e565b1515611cf857600080fd5b611d0183611de9565b83600001510190508282600001819052508082602001818152505050919050565b6000611d2c611f0f565b826000015190508060200151816000015101836020015110915050919050565b611d54611f0f565b600080611d6084611d22565b15611d9c5783602001519150611d7582611e75565b90508183600001818152505080836020018181525050808201846020018181525050611da1565b600080fd5b5050919050565b60006020601f83010484602085015b828414611dd65760208402808301518183015260018501945050611db7565b6000865160200187015250505050505050565b60008060008084602001511415611e035760009250611e6e565b83600001519050805160001a91506080821015611e235760009250611e6e565b60b8821080611e3f575060c08210158015611e3e575060f882105b5b15611e4d5760019250611e6e565b60c0821015611e6457600160b78303019250611e6e565b600160f783030192505b5050919050565b600080825160001a90506080811015611e915760019150611f09565b60b8811015611ea857600160808203019150611f08565b60c0811015611ed25760b78103806020036101000a60018501510480820160010193505050611f07565b60f8811015611ee957600160c08203019150611f06565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611f3d611f4a565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820c9e393c8db8d60d821761db3344bc3e16cce6df66586591bd3d2a43eaa4b2ee60029 \ No newline at end of file +608060405234801561001057600080fd5b50604051602080611d9c83398101806040528101908080519060200190929190505050806000816000191690555050611d4e8061004e6000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063200ab0d31461009e5780639a8a0592146100e7578063affd8be91461011a578063b64b633614610243578063bec205b9146102b4578063c18de0ef146103dd578063e7a27c4214610426578063f44ff7121461046f578063f484c1f71461049a575b600080fd5b3480156100aa57600080fd5b506100c96004803603810190808035906020019092919050505061057d565b60405180826000191660001916815260200191505060405180910390f35b3480156100f357600080fd5b506100fc6105a0565b60405180826000191660001916815260200191505060405180910390f35b34801561012657600080fd5b5061022960048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506105a6565b604051808215151515815260200191505060405180910390f35b34801561024f57600080fd5b506102726004803603810190808035600019169060200190929190505050610b36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102c057600080fd5b506103c360048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610b69565b604051808215151515815260200191505060405180910390f35b3480156103e957600080fd5b5061040c60048036038101908080356000191690602001909291905050506110f9565b604051808215151515815260200191505060405180910390f35b34801561043257600080fd5b506104556004803603810190808035600019169060200190929190505050611119565b604051808215151515815260200191505060405180910390f35b34801561047b57600080fd5b50610484611329565b6040518082815260200191505060405180910390f35b3480156104a657600080fd5b5061056360048036038101908080356000191690602001909291908035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061132f565b604051808215151515815260200191505060405180910390f35b60018181548110151561058c57fe5b906000526020600020016000915090505481565b60005481565b60008060008760036000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610649576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060046000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561071257600080fd5b505af1158015610726573d6000803e3d6000fd5b505050506040513d602081101561073c57600080fd5b810190808051906020019092919050505015156107c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600460008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561088657600080fd5b505af115801561089a573d6000803e3d6000fd5b505050506040513d60208110156108b057600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610962578082015181840152602081019050610947565b50505050905090810190601f16801561098f5780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b838110156109c85780820151818401526020810190506109ad565b50505050905090810190601f1680156109f55780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610a2e578082015181840152602081019050610a13565b50505050905090810190601f168015610a5b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b158015610a7d57600080fd5b505af4158015610a91573d6000803e3d6000fd5b505050506040513d6020811015610aa757600080fd5b81019080805190602001909291905050501515610ac057fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c60006002811115610af057fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060008760036000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610c0c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060046000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610cd557600080fd5b505af1158015610ce9573d6000803e3d6000fd5b505050506040513d6020811015610cff57600080fd5b81019080805190602001909291905050501515610d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600460008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508573ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b158015610e4957600080fd5b505af1158015610e5d573d6000803e3d6000fd5b505050506040513d6020811015610e7357600080fd5b8101908080519060200190929190505050945073__./contracts/libraries/PatriciaTrie.s__634f7142ad8b8b8b896040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015610f25578082015181840152602081019050610f0a565b50505050905090810190601f168015610f525780820380516001836020036101000a031916815260200191505b50848103835287818151815260200191508051906020019080838360005b83811015610f8b578082015181840152602081019050610f70565b50505050905090810190601f168015610fb85780820380516001836020036101000a031916815260200191505b50848103825286818151815260200191508051906020019080838360005b83811015610ff1578082015181840152602081019050610fd6565b50505050905090810190601f16801561101e5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b15801561104057600080fd5b505af4158015611054573d6000803e3d6000fd5b505050506040513d602081101561106a57600080fd5b8101908080519060200190929190505050151561108357fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c600160028111156110b357fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001965050505050505095945050505050565b60036020528060005260406000206000915054906101000a900460ff1681565b60008054600019168260001916141515156111c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60036000836000191660001916815260200190815260200160002060009054906101000a900460ff16151515611260576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b600160036000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555060018290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055503360046000846000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060019050919050565b60025481565b6000806000808760036000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156113d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b8888600060046000846000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16634b35503084846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561149c57600080fd5b505af11580156114b0573d6000803e3d6000fd5b505050506040513d60208110156114c657600080fd5b8101908080519060200190929190505050151561154b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f426c6f636b20646f6573206e6f7420657869737420666f7220636861696e000081525060200191505060405180910390fd5b600460008d6000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1696508673ffffffffffffffffffffffffffffffffffffffff166313d3babb8d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b15801561161057600080fd5b505af1158015611624573d6000803e3d6000fd5b505050506040513d602081101561163a57600080fd5b810190808051906020019092919050505095508673ffffffffffffffffffffffffffffffffffffffff166307bff1b18d8d6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001826000191660001916815260200192505050602060405180830381600087803b1580156116d457600080fd5b505af11580156116e8573d6000803e3d6000fd5b505050506040513d60208110156116fe57600080fd5b8101908080519060200190929190505050945061171a8a6117bc565b60001916866000191614151561172c57fe5b611735896117bc565b60001916856000191614151561174757fe5b7ff0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f2870468c8c60028081111561177657fe5b6040518084600019166000191681526020018360001916600019168152602001828152602001935050505060405180910390a16001975050505050505050949350505050565b60006117c6611ccd565b6060806117d28561186f565b92506117dd836118ca565b91506118008260008151811015156117f157fe5b90602001906020020151611987565b9050806040518082805190602001908083835b6020831015156118385780518252602082019150602081019050602083039250611813565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209350505050919050565b611877611ccd565b6000808351915060008214156118a557604080519081016040528060008152602001600081525092506118c3565b60208401905060408051908101604052808281526020018381525092505b5050919050565b606060006118d6611ce7565b60006118e1856119ec565b15156118ec57600080fd5b6118f585611a1e565b92508260405190808252806020026020018201604052801561193157816020015b61191e611d08565b8152602001906001900390816119165790505b50935061193d85611a98565b91505b61194982611ae0565b1561197f5761195782611b0a565b848281518110151561196557fe5b906020019060200201819052508080600101915050611940565b505050919050565b606060008260200151905060008114156119a0576119e6565b806040519080825280601f01601f1916602001820160405280156119d35781602001602082028038833980820191505090505b5091506119e583600001518383611b66565b5b50919050565b600080600083602001511415611a055760009150611a18565b8260000151905060c0815160001a101591505b50919050565b600080600080600080611a30876119ec565b1515611a3f5760009550611a8e565b86600001519350835160001a9450611a5687611ba7565b840192506001876020015185010391505b8183111515611a8a57611a7983611c33565b830192508080600101915050611a67565b8095505b5050505050919050565b611aa0611ce7565b6000611aab836119ec565b1515611ab657600080fd5b611abf83611ba7565b83600001510190508282600001819052508082602001818152505050919050565b6000611aea611ccd565b826000015190508060200151816000015101836020015110915050919050565b611b12611ccd565b600080611b1e84611ae0565b15611b5a5783602001519150611b3382611c33565b90508183600001818152505080836020018181525050808201846020018181525050611b5f565b600080fd5b5050919050565b60006020601f83010484602085015b828414611b945760208402808301518183015260018501945050611b75565b6000865160200187015250505050505050565b60008060008084602001511415611bc15760009250611c2c565b83600001519050805160001a91506080821015611be15760009250611c2c565b60b8821080611bfd575060c08210158015611bfc575060f882105b5b15611c0b5760019250611c2c565b60c0821015611c2257600160b78303019250611c2c565b600160f783030192505b5050919050565b600080825160001a90506080811015611c4f5760019150611cc7565b60b8811015611c6657600160808203019150611cc6565b60c0811015611c905760b78103806020036101000a60018501510480820160010193505050611cc5565b60f8811015611ca757600160c08203019150611cc4565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611cfb611d08565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820fc39ca6beb50451959f4ca41c774ebc668d746257556592fe219d6cd5f2199540029 \ No newline at end of file diff --git a/abi/IonCompatible.bin b/abi/IonCompatible.bin index 48b938a..73942e3 100644 --- a/abi/IonCompatible.bin +++ b/abi/IonCompatible.bin @@ -1 +1 @@ -6080604052348015600f57600080fd5b5060405160208060b483398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050603580607f6000396000f3006080604052600080fd00a165627a7a72305820265633b22444b9ca92bffc39cb488c8966ba05a699ce6a56592fdd1d2c589d9e0029 \ No newline at end of file +6080604052348015600f57600080fd5b5060405160208060b483398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050603580607f6000396000f3006080604052600080fd00a165627a7a7230582050604061d1c8d427a651689154fc650f3cd41da698fc95ed8a7f5dd58a2392610029 \ No newline at end of file diff --git a/abi/Validation.abi b/abi/Validation.abi index fb12ac6..77318bb 100644 --- a/abi/Validation.abi +++ b/abi/Validation.abi @@ -1 +1 @@ -[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getReceiptRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getTxRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getReceiptRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_hash","type":"bytes32"}],"name":"getTxRootHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"m_latestblock","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockhashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_rlpBlockHeader","type":"bytes"},{"name":"_rlpSignedBlockHeader","type":"bytes"}],"name":"SubmitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"}],"name":"m_validators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_ion","type":"address"},{"name":"_validators","type":"address[]"},{"name":"_genesisHash","type":"bytes32"}],"name":"RegisterChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chainId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"chains","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"m_blockheaders","outputs":[{"name":"blockHeight","type":"uint256"},{"name":"latestHash","type":"bytes32"},{"name":"prevBlockHash","type":"bytes32"},{"name":"txRootHash","type":"bytes32"},{"name":"receiptRootHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_id","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"signer","type":"address"}],"name":"broadcastSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"blockHash","type":"bytes32"}],"name":"broadcastHash","type":"event"}] \ No newline at end of file diff --git a/abi/Validation.bin b/abi/Validation.bin index 19b95a7..a6b2723 100644 --- a/abi/Validation.bin +++ b/abi/Validation.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b506040516020806117ca8339810180604052810190808051906020019092919050505080600081600019169055505061177c8061004e6000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806307bff1b11461009e57806313d3babb146100f957806347bfc0a8146101545780634b355030146101d6578063528243741461022d57806353fe62e6146102ea5780639a8a059214610353578063c18de0ef14610386578063e79b136c146103cf575b600080fd5b3480156100aa57600080fd5b506100db6004803603810190808035600019169060200190929190803560001916906020019092919050505061045e565b60405180826000191660001916815260200191505060405180910390f35b34801561010557600080fd5b50610136600480360381019080803560001916906020019092919080356000191690602001909291905050506104a0565b60405180826000191660001916815260200191505060405180910390f35b34801561016057600080fd5b506101d460048036038101908080356000191690602001909291908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080356000191690602001909291905050506104e2565b005b3480156101e257600080fd5b506102136004803603810190808035600019169060200190929190803560001916906020019092919050505061078f565b604051808215151515815260200191505060405180910390f35b34801561023957600080fd5b506102e86004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506107be565b005b3480156102f657600080fd5b506103396004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610dac565b604051808215151515815260200191505060405180910390f35b34801561035f57600080fd5b50610368610ddb565b60405180826000191660001916815260200191505060405180910390f35b34801561039257600080fd5b506103b56004803603810190808035600019169060200190929190505050610de1565b604051808215151515815260200191505060405180910390f35b3480156103db57600080fd5b5061040c60048036038101908080356000191690602001909291908035600019169060200190929190505050610e01565b6040518086815260200185600019166000191681526020018460001916600019168152602001836000191660001916815260200182600019166000191681526020019550505050505060405180910390f35b60006003600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060040154905092915050565b60006003600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060030154905092915050565b600080546000191684600019161415151561058b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60016000856000191660001916815260200190815260200160002060009054906101000a900460ff16151515610629576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b6001806000866000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600090505b82518110156106ff5760016004600086600019166000191681526020019081526020016000206000858481518110151561069757fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080600101915050610661565b6000600360008660001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555060016002600086600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555050505050565b60026020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008760016000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610864576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61087561087089610e44565b610e9f565b955061088861088388610e44565b610e9f565b9450600093505b8451841015610a3557600c8414156108a657610a28565b6108c685858151811015156108b757fe5b90602001906020020151610f5c565b6040518082805190602001908083835b6020831015156108fb57805182526020820191506020810190506020830392506108d6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661094c878681518110151561093d57fe5b90602001906020020151610f5c565b6040518082805190602001908083835b602083101515610981578051825260208201915060208101905060208303925061095c565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916141515610a27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486561646572206461746120646f65736e2774206d617463682100000000000081525060200191505060405180910390fd5b5b838060010194505061088f565b610a60610a59876000815181101515610a4a57fe5b90602001906020020151610f5c565b6001610fc1565b9250600260008a600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060009054906101000a900460ff161515610b18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b866040518082805190602001908083835b602083101515610b4e5780518252602082019150602081019050602083039250610b29565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018260405180826000191660001916815260200191505060405180910390a1610be789610be187600c815181101515610bd257fe5b90602001906020020151610f5c565b8a610fd5565b610c08866008815181101515610bf957fe5b906020019060200201516111d6565b600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206000018190555081600360008b6000191660001916815260200190815260200160002060008460001916600019168152602001908152602001600020600101816000191690555082600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206002018160001916905550610cee610ce7876004815181101515610cd857fe5b90602001906020020151610f5c565b6001610fc1565b600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206003018160001916905550610d58610d51876005815181101515610d4257fe5b90602001906020020151610f5c565b6001610fc1565b600360008b60001916600019168152602001908152602001600020600084600019166000191681526020019081526020016000206004018160001916905550610da1898361122d565b505050505050505050565b60046020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60005481565b60016020528060005260406000206000915054906101000a900460ff1681565b6003602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154908060040154905085565b610e4c6116fb565b600080835191506000821415610e7a5760408051908101604052806000815260200160008152509250610e98565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610eab611715565b6000610eb68561127e565b1515610ec157600080fd5b610eca856112b0565b925082604051908082528060200260200182016040528015610f0657816020015b610ef3611736565b815260200190600190039081610eeb5790505b509350610f128561132a565b91505b610f1e82611372565b15610f5457610f2c8261139c565b8482815181101515610f3a57fe5b906020019060200201819052508080600101915050610f15565b505050919050565b60606000826020015190506000811415610f7557610fbb565b806040519080825280601f01601f191660200182016040528015610fa85781602001602082028038833980820191505090505b509150610fba836000015183836113f8565b5b50919050565b600060208201915081830151905092915050565b606060008060416040519080825280601f01601f19166020018201604052801561100e5781602001602082028038833980820191505090505b50925084519150611023838660418503611439565b61108f846040518082805190602001908083835b60208310151561105c5780518252602082019150602081019050602083039250611037565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390208461145b565b905060046000876000191660001916815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561116b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef4381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b60008060006111e4846114d3565b15156111ef57600080fd5b6111f884611504565b8092508193505050602081118061120f5750600081145b1561121957600080fd5b806020036101000a82510492505050919050565b60016002600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008060008360200151141561129757600091506112aa565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806112c28761127e565b15156112d15760009550611320565b86600001519350835160001a94506112e887611585565b840192506001876020015185010391505b818311151561131c5761130b83611611565b8301925080806001019150506112f9565b8095505b5050505050919050565b611332611715565b600061133d8361127e565b151561134857600080fd5b61135183611585565b83600001510190508282600001819052508082602001818152505050919050565b600061137c6116fb565b826000015190508060200151816000015101836020015110915050919050565b6113a46116fb565b6000806113b084611372565b156113ec57836020015191506113c582611611565b905081836000018181525050808360200181815250508082018460200181815250506113f1565b600080fd5b5050919050565b60006020601f83010484602085015b8284146114265760208402808301518183015260018501945050611407565b6000865160200187015250505050505050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b6000806000806041855114151561147157600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561149c57601b810190505b601b8160ff1614806114b15750601c8160ff16145b15156114bc57600080fd5b6114c8868285856116ab565b935050505092915050565b6000806000836020015114156114ec57600091506114fe565b8260000151905060c0815160001a1091505b50919050565b6000806000806000611515866114d3565b151561152057600080fd5b85600001519150815160001a92506080831015611543578194506001935061157d565b60b8831015611561576001866020015103935060018201945061157c565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b6000806000808460200151141561159f576000925061160a565b83600001519050805160001a915060808210156115bf576000925061160a565b60b88210806115db575060c082101580156115da575060f882105b5b156115e9576001925061160a565b60c082101561160057600160b7830301925061160a565b600160f783030192505b5050919050565b600080825160001a9050608081101561162d57600191506116a5565b60b8811015611644576001608082030191506116a4565b60c081101561166e5760b78103806020036101000a600185015104808201600101935050506116a3565b60f881101561168557600160c082030191506116a2565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa92508051915050600115158215151415156116ee57600080fd5b8092505050949350505050565b604080519081016040528060008152602001600081525090565b606060405190810160405280611729611736565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820c3755aed4d27c4e81346282c5970f9b444d3102512fa0460f13223a8fff7c83a0029 \ No newline at end of file +608060405234801561001057600080fd5b50604051602080611a5983398101806040528101908080519060200190929190505050806000816000191690555050611a0b8061004e6000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806307bff1b1146100a957806313d3babb146101045780632e47ee8a1461015f5780634b355030146101ac578063528243741461020357806353fe62e6146102c05780637558a01a146103295780639a8a0592146103cb578063c18de0ef146103fe578063e79b136c14610447575b600080fd5b3480156100b557600080fd5b506100e6600480360381019080803560001916906020019092919080356000191690602001909291905050506104d6565b60405180826000191660001916815260200191505060405180910390f35b34801561011057600080fd5b5061014160048036038101908080356000191690602001909291908035600019169060200190929190505050610518565b60405180826000191660001916815260200191505060405180910390f35b34801561016b57600080fd5b5061018e600480360381019080803560001916906020019092919050505061055a565b60405180826000191660001916815260200191505060405180910390f35b3480156101b857600080fd5b506101e960048036038101908080356000191690602001909291908035600019169060200190929190505050610572565b604051808215151515815260200191505060405180910390f35b34801561020f57600080fd5b506102be6004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506105a1565b005b3480156102cc57600080fd5b5061030f6004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a6b565b604051808215151515815260200191505060405180910390f35b34801561033557600080fd5b506103c96004803603810190808035600019169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035600019169060200190929190505050610a9a565b005b3480156103d757600080fd5b506103e0610efe565b60405180826000191660001916815260200191505060405180910390f35b34801561040a57600080fd5b5061042d6004803603810190808035600019169060200190929190505050610f04565b604051808215151515815260200191505060405180910390f35b34801561045357600080fd5b5061048460048036038101908080356000191690602001909291908035600019169060200190929190505050610f24565b6040518086815260200185600019166000191681526020018460001916600019168152602001836000191660001916815260200182600019166000191681526020019550505050505060405180910390f35b60006004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060040154905092915050565b60006004600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060030154905092915050565b60026020528060005260406000206000915090505481565b60036020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60608060008060008760016000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610647576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436861696e206973206e6f74207265676973746572656400000000000000000081525060200191505060405180910390fd5b61065861065389610f67565b610fc2565b955061066b61066688610f67565b610fc2565b9450600093505b845184101561081857600c8414156106895761080b565b6106a9858581518110151561069a57fe5b9060200190602002015161107f565b6040518082805190602001908083835b6020831015156106de57805182526020820191506020810190506020830392506106b9565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191661072f878681518110151561072057fe5b9060200190602002015161107f565b6040518082805190602001908083835b602083101515610764578051825260208201915060208101905060208303925061073f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191614151561080a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486561646572206461746120646f65736e2774206d617463682100000000000081525060200191505060405180910390fd5b5b8380600101945050610672565b61084361083c87600081518110151561082d57fe5b9060200190602002015161107f565b60016110e4565b9250600360008a600019166000191681526020019081526020016000206000846000191660001916815260200190815260200160002060009054906101000a900460ff1615156108fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f74206368696c64206f662070726576696f757320626c6f636b210000000081525060200191505060405180910390fd5b866040518082805190602001908083835b602083101515610931578051825260208201915060208101905060208303925061090c565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091507fcd7ee33e1a630d6301d87631aab1d4ddce7e1942593cd2689aa989f76d67cf018260405180826000191660001916815260200191505060405180910390a16109ca896109c487600c8151811015156109b557fe5b9060200190602002015161107f565b8a6110f8565b610a4c8983856109fb6109f48b60048151811015156109e557fe5b9060200190602002015161107f565b60016110e4565b610a26610a1f8c6005815181101515610a1057fe5b9060200190602002015161107f565b60016110e4565b610a478c6008815181101515610a3857fe5b906020019060200201516112f9565b611350565b610a568983611494565b610a6089836114e5565b505050505050505050565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008060005460001916866000191614151515610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f43616e6e6f7420616464207468697320636861696e20696420746f206368616981526020017f6e2072656769737465720000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60016000876000191660001916815260200190815260200160002060009054906101000a900460ff16151515610be3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f436861696e20616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b6001806000886000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b8351821015610cb957600160056000886000191660001916815260200190815260200160002060008685815181101515610c5157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508180600101925050610c1b565b8490508073ffffffffffffffffffffffffffffffffffffffff1663e7a27c42876040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b158015610d3357600080fd5b505af1158015610d47573d6000803e3d6000fd5b505050506040513d6020811015610d5d57600080fd5b81019080805190602001909291905050501515610e08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f436861696e206e6f7420616464656420746f20496f6e2073756363657373667581526020017f6c6c79210000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600060046000886000191660001916815260200190815260200160002060008560001916600019168152602001908152602001600020600001819055508260046000886000191660001916815260200190815260200160002060008560001916600019168152602001908152602001600020600101816000191690555060016003600088600019166000191681526020019081526020016000206000856000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550826002600088600019166000191681526020019081526020016000208160001916905550505050505050565b60005481565b60016020528060005260406000206000915054906101000a900460ff1681565b6004602052816000526040600020602052806000526040600020600091509150508060000154908060010154908060020154908060030154908060040154905085565b610f6f61198a565b600080835191506000821415610f9d5760408051908101604052806000815260200160008152509250610fbb565b60208401905060408051908101604052808281526020018381525092505b5050919050565b60606000610fce6119a4565b6000610fd98561150d565b1515610fe457600080fd5b610fed8561153f565b92508260405190808252806020026020018201604052801561102957816020015b6110166119c5565b81526020019060019003908161100e5790505b509350611035856115b9565b91505b61104182611601565b156110775761104f8261162b565b848281518110151561105d57fe5b906020019060200201819052508080600101915050611038565b505050919050565b60606000826020015190506000811415611098576110de565b806040519080825280601f01601f1916602001820160405280156110cb5781602001602082028038833980820191505090505b5091506110dd83600001518383611687565b5b50919050565b600060208201915081830151905092915050565b606060008060416040519080825280601f01601f1916602001820160405280156111315781602001602082028038833980820191505090505b509250845191506111468386604185036116c8565b6111b2846040518082805190602001908083835b60208310151561117f578051825260208201915060208101905060208303925061115a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020846116ea565b905060056000876000191660001916815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561128e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f5369676e6572206e6f7420612076616c696461746f722100000000000000000081525060200191505060405180910390fd5b7f3fc7485a49f5212e355cd85d3fa5518c2b1e29bcc613ab74cc722a2c5b1eef4381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050505050565b600080600061130784611762565b151561131257600080fd5b61131b84611793565b809250819350505060208111806113325750600081145b1561133c57600080fd5b806020036101000a82510492505050919050565b80600460008860001916600019168152602001908152602001600020600087600019166000191681526020019081526020016000206000018190555084600460008860001916600019168152602001908152602001600020600087600019166000191681526020019081526020016000206001018160001916905550836004600088600019166000191681526020019081526020016000206000876000191660001916815260200190815260200160002060020181600019169055508260046000886000191660001916815260200190815260200160002060008760001916600019168152602001908152602001600020600301816000191690555081600460008860001916600019168152602001908152602001600020600087600019166000191681526020019081526020016000206004018160001916905550505050505050565b60016003600084600019166000191681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b8060026000846000191660001916815260200190815260200160002081600019169055505050565b6000806000836020015114156115265760009150611539565b8260000151905060c0815160001a101591505b50919050565b6000806000806000806115518761150d565b151561156057600095506115af565b86600001519350835160001a945061157787611814565b840192506001876020015185010391505b81831115156115ab5761159a836118a0565b830192508080600101915050611588565b8095505b5050505050919050565b6115c16119a4565b60006115cc8361150d565b15156115d757600080fd5b6115e083611814565b83600001510190508282600001819052508082602001818152505050919050565b600061160b61198a565b826000015190508060200151816000015101836020015110915050919050565b61163361198a565b60008061163f84611601565b1561167b5783602001519150611654826118a0565b90508183600001818152505080836020018181525050808201846020018181525050611680565b600080fd5b5050919050565b60006020601f83010484602085015b8284146116b55760208402808301518183015260018501945050611696565b6000865160200187015250505050505050565b6000835190506020820191508060208501828486016004610bb8fa5050505050565b6000806000806041855114151561170057600080fd5b6020850151925060408501519150606085015160001a9050601b8160ff16101561172b57601b810190505b601b8160ff1614806117405750601c8160ff16145b151561174b57600080fd5b6117578682858561193a565b935050505092915050565b60008060008360200151141561177b576000915061178d565b8260000151905060c0815160001a1091505b50919050565b60008060008060006117a486611762565b15156117af57600080fd5b85600001519150815160001a925060808310156117d2578194506001935061180c565b60b88310156117f0576001866020015103935060018201945061180b565b60b78303905080600187602001510303935060018183010194505b5b505050915091565b6000806000808460200151141561182e5760009250611899565b83600001519050805160001a9150608082101561184e5760009250611899565b60b882108061186a575060c08210158015611869575060f882105b5b156118785760019250611899565b60c082101561188f57600160b78303019250611899565b600160f783030192505b5050919050565b600080825160001a905060808110156118bc5760019150611934565b60b88110156118d357600160808203019150611933565b60c08110156118fd5760b78103806020036101000a60018501510480820160010193505050611932565b60f881101561191457600160c08203019150611931565b60f78103806020036101000a600185015104808201600101935050505b5b5b5b50919050565b60008060006040518781528660208201528560408201528460608201526020816080836001610bb8fa925080519150506001151582151514151561197d57600080fd5b8092505050949350505050565b604080519081016040528060008152602001600081525090565b6060604051908101604052806119b86119c5565b8152602001600081525090565b6040805190810160405280600081526020016000815250905600a165627a7a72305820a837d768c41148e3cf2e607a27809b08f41ec76da534697302e1e8f2f798f59b0029 \ No newline at end of file diff --git a/contracts/Ion.sol b/contracts/Ion.sol index f10cfe2..6e1388a 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -13,27 +13,14 @@ contract Ion { using RLP for RLP.Iterator; using RLP for bytes; - struct BlockHeader { - uint256 blockHeight; - bytes32 prevBlockHash; - bytes32 txRootHash; - bytes32 receiptRootHash; - } - - - // address[] public validators; - bytes32 public blockHash; + // bytes32 public blockHash; bytes32 public chainId; bytes32[] public registeredChains; uint256 public blockHeight; mapping (bytes32 => bool) public chains; mapping (bytes32 => address) public m_validation; - mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; - mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; - // input chainId to validators address returning bool - mapping (bytes32 => mapping (address => bool)) public m_validators; /* @@ -102,8 +89,9 @@ contract Ion { * param: _genesisHash Genesis blockhash of the interop block chain * * Supplied with an id of another chain, checks if this id already exists in the known set of ids - * and adds it to the list of known chains. Should be called by the validation contract upon - * registration. + * and adds it to the list of known chains. + * + *Should be called by the validation registerChain() function */ function addChain(bytes32 _id) public returns (bool) { require( _id != chainId, "Cannot add this chain id to chain register" ); @@ -219,7 +207,6 @@ contract Ion { public returns (bool) { - // BlockHeader storage blockHeader = m_blockheaders[_id][_blockHash]; Validation validation = Validation(m_validation[_id]); bytes32 txRootHash = validation.getTxRootHash(_id, _blockHash); bytes32 receiptRootHash = validation.getReceiptRootHash(_id, _blockHash); diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 30ea89b..fc330f1 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -26,6 +26,7 @@ contract Validation { } mapping (bytes32 => bool) public chains; + mapping (bytes32 => bytes32) public m_latestblock; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; mapping (bytes32 => mapping (address => bool)) public m_validators; @@ -62,7 +63,9 @@ contract Validation { require(ion.addChain(_id), "Chain not added to Ion successfully!"); m_blockheaders[_id][_genesisHash].blockHeight = 0; + m_blockheaders[_id][_genesisHash].latestHash = _genesisHash; m_blockhashes[_id][_genesisHash] = true; + m_latestblock[_id] = _genesisHash; } @@ -99,14 +102,10 @@ contract Validation { recoverSignature(_id, signedHeader[12].toBytes(), _rlpBlockHeader); - // Append the new block to the struct - m_blockheaders[_id][_blockHash].blockHeight = header[8].toUint(); - m_blockheaders[_id][_blockHash].latestHash = _blockHash; - m_blockheaders[_id][_blockHash].prevBlockHash = _parentBlockHash; - m_blockheaders[_id][_blockHash].txRootHash = SolUtils.BytesToBytes32(header[4].toBytes(), 1); - m_blockheaders[_id][_blockHash].receiptRootHash = SolUtils.BytesToBytes32(header[5].toBytes(), 1); - + // Append the new block to the struct + addBlockHeaderToChain(_id, _blockHash, _parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint()); addBlockHashToChain(_id, _blockHash); + updateBlockHash(_id, _blockHash); } @@ -122,6 +121,20 @@ contract Validation { emit broadcastSignature(sigAddr); } + /* + * @description when a block is submitted the root hash must be added to a mapping of chains to hashes + * @param _id unique identifier of the chain from which the block hails + * @param _hash root hash of the block being added + */ + function addBlockHeaderToChain(bytes32 _id, bytes32 _hash, bytes32 _parentHash, bytes32 _txRootHash, bytes32 _receiptRootHash, uint256 _height) internal { + // Append the new block to the struct + m_blockheaders[_id][_hash].blockHeight = _height; + m_blockheaders[_id][_hash].latestHash = _hash; + m_blockheaders[_id][_hash].prevBlockHash = _parentHash; + m_blockheaders[_id][_hash].txRootHash = _txRootHash; + m_blockheaders[_id][_hash].receiptRootHash = _receiptRootHash; + } + /* * @description when a block is submitted the root hash must be added to a mapping of chains to hashes * @param _id unique identifier of the chain from which the block hails @@ -131,6 +144,15 @@ contract Validation { m_blockhashes[_id][_hash] = true; } + /* + * @description when a block is submitted the latest block is updated here + * @param _id unique identifier of the chain from which the block hails + * @param _hash root hash of the block being added + */ + function updateBlockHash(bytes32 _id, bytes32 _hash) internal { + m_latestblock[_id] = _hash; + } + /* * @description returns the transaction root hash of a specific block * @param _id unique identifier of the chain from which the block hails diff --git a/ion-cli/Makefile b/ion-cli/Makefile index 4a7fa08..b5f3a7b 100644 --- a/ion-cli/Makefile +++ b/ion-cli/Makefile @@ -8,6 +8,8 @@ clean: @rm contracts/validation.go @rm contracts/ion.go @rm contracts/patricia.go + @rm contracts/trigger.go + @rm contracts/function.go test: @go test ./... -v -short @@ -30,6 +32,8 @@ build: @abigen --bin=../abi/Validation.bin --abi=../abi/Validation.abi --pkg=contract --type=validation --out=contracts/validation.go @abigen --bin=../abi/Ion.bin --abi=../abi/Ion.abi --pkg=contract --type=ion --out=contracts/ion.go @abigen --bin=../abi/PatriciaTrie.bin --abi=../abi/PatriciaTrie.abi --pkg=contract --type=patricia --out=contracts/patricia.go + @abigen --bin=../abi/Function.bin --abi=../abi/Function.abi --pkg=contract --type=function --out=contracts/function.go + @abigen --bin=../abi/Trigger.bin --abi=../abi/Trigger.abi --pkg=contract --type=trigger --out=contracts/trigger.go # Now build project @go get -t -v ./... diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 76ca8a9..3a686d2 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -22,7 +22,7 @@ import ( ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contract.Validation, Ion *contract.Ion) { +func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contract.Validation, Ion *contract.Ion, Trigger *contract.Trigger) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -34,13 +34,29 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra // Create an authorized transactor and spend 1 unicorn keyTo := config.ReadString(setup.KeystoreTo) - auth, err := bind.NewTransactor(strings.NewReader(keyTo), "password1") + authTo, err := bind.NewTransactor(strings.NewReader(keyTo), "password1") if err != nil { log.Fatalf("Failed to create authorized transactor: %v", err) } - auth.Value = big.NewInt(0) // in wei - auth.GasLimit = uint64(300000) // in units - auth.GasPrice = gasPrice + authTo.Value = big.NewInt(0) // in wei + authTo.From = common.HexToAddress(setup.AccountTo) + authTo.GasLimit = uint64(100000) // in units + authTo.GasPrice = gasPrice + + // Create an authorized transactor and spend 1 unicorn + keyFrom := config.ReadString(setup.KeystoreFrom) + authFrom, err := bind.NewTransactor(strings.NewReader(keyFrom), "password1") + if err != nil { + log.Fatalf("Failed to create authorized transactor: %v", err) + } + authFrom.Value = big.NewInt(0) // in wei + authFrom.From = common.HexToAddress(setup.AccountFrom) // in wei + authFrom.GasLimit = uint64(100000) // in units + authFrom.GasPrice = gasPrice + + //--------------------------------------------------------------------------------------------- + // RPC Client Specific Commands + //--------------------------------------------------------------------------------------------- shell.AddCmd(&ishell.Cmd{ Name: "latestBlock", @@ -49,7 +65,9 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrFrom) c.Println("Get latest block number:") - latestBlock(clientFrom) + lastBlock := latestBlock(clientFrom) + c.Printf("latest block: %v\n", lastBlock.Number) + c.Println("===============================================================") }, }) @@ -71,6 +89,10 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra }, }) + //--------------------------------------------------------------------------------------------- + // Validation Specific Commands + //--------------------------------------------------------------------------------------------- + shell.AddCmd(&ishell.Cmd{ Name: "registerChainValidation", Help: "use: registerChainValidation \n\t\t\t\tdescription: Register new chain with validation contract", @@ -105,20 +127,20 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra return } - c.Printf("Running Command:\t%x\t%x\t%x\n", bytesChainId, validators, bytesGenesis) - tx, err := Validation.RegisterChain(auth, bytesChainId, validators, bytesGenesis) + ionAddress := common.HexToAddress(setup.Ion) + tx, err := Validation.RegisterChain(authTo, bytesChainId, ionAddress, validators, bytesGenesis) if err != nil { c.Printf("Error: %s", err) return } - c.Println(tx) + c.Printf("\nTransaction Result:\n%x\n", tx) c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ Name: "checkBlockValidation", - Help: "use: checkBlockValidation [chainId] [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", + Help: "use: checkBlockValidation [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", Func: func(c *ishell.Context) { c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) @@ -155,7 +177,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra shell.AddCmd(&ishell.Cmd{ Name: "submitBlockValidation", - Help: "use: submitBlockValidation [chainId] [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", + Help: "use: submitBlockValidation [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { c.Println("===============================================================") c.ShowPrompt(false) @@ -174,7 +196,7 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) signedBlock, unsignedBlock := calculateRlpEncoding(clientFrom, blockNum) - res, err := Validation.SubmitBlock(auth, bytesChainId, unsignedBlock, signedBlock) + res, err := Validation.SubmitBlock(authTo, bytesChainId, unsignedBlock, signedBlock) if err != nil { c.Printf("Error: %s", err) return @@ -184,111 +206,85 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra }, }) - // shell.AddCmd(&ishell.Cmd{ - // Name: "latestValidationBlock", - // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrTo) - // result, err := Validation.LatestBlock(&bind.CallOpts{}) - // if err != nil { - // fmt.Printf("Error: %s", err) - // return - // } - // c.Println("Last Block Submitted:") - // c.Printf("0x%x\n", result) - - // c.Println("===============================================================") - // }, - // }) - - // shell.AddCmd(&ishell.Cmd{ - // Name: "getValidationBlock", - // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrFrom) - // blockNum := new(big.Int) - // blockNum.SetString(c.Args[0], 10) - // result, err := Validation.GetBlock(&bind.CallOpts{}, blockNum) - // if err != nil { - // fmt.Printf("Error: %s", err) - // return - // } - // c.Println("Last Block Submitted:") - // c.Printf("Block:\n\t%x\n", result.BlockHeight) - // c.Printf("Hash:\n\t0x%x\n", result.BlockHash) - // c.Printf("Parent Hash:\n\t0x%x\n", result.PrevBlockHash) - - // c.Println("===============================================================") - // }, - // }) - - // shell.AddCmd(&ishell.Cmd{ - // Name: "submitValidationBlock", - // Help: "use: submitValidationBlock [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrTo) - // if len(c.Args) == 0 { - // c.Println("Select a block") - // } else if len(c.Args) > 1 { - // c.Println("Too many arguments entered.") - // } else { - // c.Println("RLP encode block: " + c.Args[0]) - // encodedBlock, prefixBlock, prefixExtra := calculateRlpEncoding(clientFrom, c.Args[0]) - // res, err := Validation.ValidateBlock(auth, encodedBlock, prefixBlock, prefixExtra) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - // c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) - // } - // c.Println("===============================================================") - // }, - // }) - - // shell.AddCmd(&ishell.Cmd{ - // Name: "generateTxProof", - // Help: "use: generateTxProof [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrTo) - // if len(c.Args) == 0 { - // c.Println("Select a block") - // } else if len(c.Args) > 2 { - // c.Println("Too many arguments entered.") - // } else { - // c.Println("RLP encode block: " + c.Args[0]) - // rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) - // c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) - // } - // c.Println("===============================================================") - // }, - // }) + shell.AddCmd(&ishell.Cmd{ + Name: "latestValidationBlock", + Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo) + // Get the chainId + bytesChainId, err := utils.StringToBytes32(setup.ChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } + + result, err := Validation.MLatestblock(&bind.CallOpts{}, bytesChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("Latest Block Submitted:\nBlockHash:\t0x%x\nChainId:\t%s\n", result, setup.ChainId) + c.Println("===============================================================") + }, + }) + + //--------------------------------------------------------------------------------------------- + // Trigger Specific Commands + //--------------------------------------------------------------------------------------------- + shell.AddCmd(&ishell.Cmd{ + Name: "triggerEvent", + Help: "use: triggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrFrom) + lastBlock := latestBlock(clientFrom) + + result, err := Trigger.Fire(authFrom) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("Triggered Event:\nResult:\t%+v\n", result.Hash) + block := lastBlock.Number + blockNumber, _ := strconv.ParseUint(block.String(), 0, 64) + // s := []uint32{} + ch := make(chan *contract.TriggerTriggered) + opts := &bind.WatchOpts{} + opts.Start = &blockNumber + _, err = Trigger.WatchTriggered(opts, ch) + if err != nil { + log.Fatalf("Failed WatchTriggered: %v", err) + } + var newEvent *contract.TriggerTriggered = <-ch + fmt.Println(newEvent.Caller) + + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "verifyAndExecute", + Help: "use: verifyAndExecute [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo) + if len(c.Args) == 0 { + c.Println("Select a block") + } else if len(c.Args) > 2 { + c.Println("Too many arguments entered.") + } else { + c.Println("RLP encode block: " + c.Args[0]) + rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) + c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) + } + c.Println("===============================================================") + }, + }) //--------------------------------------------------------------------------------------------- // Ion Specific Commands - // //--------------------------------------------------------------------------------------------- - // shell.AddCmd(&ishell.Cmd{ - // Name: "ionRegisterChain", - // Help: "use: ionRegisterChain [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrTo) - // if len(c.Args) == 0 { - // c.Println("Select a block") - // } else if len(c.Args) > 2 { - // c.Println("Too many arguments entered.") - // } else { - // c.Println("RLP encode block: " + c.Args[0]) - // rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) - // c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) - // } - // c.Println("===============================================================") - // }, - // }) // run shell shell.Run() diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 89acf01..ef45363 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -34,15 +34,15 @@ type header struct { Nonce string `json:"nonce"` } -func latestBlock(client *ethclient.Client) { +func latestBlock(client *ethclient.Client) (lastBlock *types.Header) { // var lastBlock Block lastBlock, err := client.HeaderByNumber(context.Background(), nil) if err != nil { fmt.Println("can't get latest block:", err) - return + return nil } - // Print events from the subscription as they arrive. - fmt.Printf("latest block: %v\n", lastBlock.Number) + + return } func getBlock(client *ethclient.Client, block string) { @@ -65,6 +65,10 @@ func getBlock(client *ethclient.Client, block string) { fmt.Println(string(b)) } +func generateProof() { + +} + // func calculateRlpEncoding(client *ethclient.Client, block string) { func calculateRlpEncoding(client *ethclient.Client, block string) (rlpSignedBlock []byte, rlpUnsignedBlock []byte) { // var blockHeader header diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index 1fffc32..05ae19b 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -2,42 +2,53 @@ package cli -// func Test_EncodeSignedBlock(t *testing.T) { -// TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" -// EXPECTED_SIGNED_BYTES, _ := hex.DecodeString(TEST_SIGNED) - -// // read a fake block -// raw, err := ioutil.ReadFile("./block.json") -// if err != nil { -// fmt.Println("cannot find test block.json file:", err) -// return -// } - -// // Marshall fake block into the Header -// var blockHeader header -// json.Unmarshal(raw, &blockHeader) -// SIGNED_BLOCK := encodeSignedBlock(blockHeader) - -// assert.Equal(t, EXPECTED_SIGNED_BYTES, SIGNED_BLOCK) -// } - -// func Test_EncodeUnsignedBlock(t *testing.T) { -// // TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" -// TEST_UNSIGNED := "f9021aa03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1da0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" -// EXPECTED_UNSIGNED_BYTES, _ := hex.DecodeString(TEST_UNSIGNED) - -// // read a fake block -// raw, err := ioutil.ReadFile("./block.json") -// if err != nil { -// fmt.Println("cannot find test block.json file:", err) -// return -// } - -// // Marshall fake block into the Header -// var blockHeader header -// json.Unmarshal(raw, &blockHeader) -// UNSIGNED_BLOCK := encodeUnsignedBlock(blockHeader) - -// assert.Equal(t, EXPECTED_UNSIGNED_BYTES, UNSIGNED_BLOCK) - -// } +import ( + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" +) + +func Test_EncodeSignedBlock(t *testing.T) { + TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + EXPECTED_SIGNED_BYTES, _ := hex.DecodeString(TEST_SIGNED) + + // read a fake block + raw, err := ioutil.ReadFile("./block.json") + if err != nil { + fmt.Println("cannot find test block.json file:", err) + return + } + + // Marshall fake block into the Header + var blockHeader *types.Header + json.Unmarshal(raw, &blockHeader) + SIGNED_BLOCK := encodeSignedBlock(blockHeader) + + assert.Equal(t, EXPECTED_SIGNED_BYTES, SIGNED_BLOCK) +} + +func Test_EncodeUnsignedBlock(t *testing.T) { + // TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + TEST_UNSIGNED := "f9021aa03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1da0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + EXPECTED_UNSIGNED_BYTES, _ := hex.DecodeString(TEST_UNSIGNED) + + // read a fake block + raw, err := ioutil.ReadFile("./block.json") + if err != nil { + fmt.Println("cannot find test block.json file:", err) + return + } + + // Marshall fake block into the Header + var blockHeader *types.Header + json.Unmarshal(raw, &blockHeader) + UNSIGNED_BLOCK := encodeUnsignedBlock(blockHeader) + + assert.Equal(t, EXPECTED_UNSIGNED_BYTES, UNSIGNED_BLOCK) + +} diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 4538402..ebcc42c 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -16,9 +16,10 @@ type Setup struct { AddrFrom string `json:"rpc-from"` AccountFrom string `json:"account-from"` KeystoreFrom string `json:"keystore-from"` - Validation string `json:"validation-addr"` ChainId string `json:"validation-chainid"` + Validation string `json:"validation-addr"` Ion string `json:"ion-addr"` + Trigger string `json:"trigger-addr"` } // Takes path to a JSON and returns a struct of the contents diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index e9d6b4c..5d0cce4 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -41,3 +41,14 @@ func InitValidation(setup Setup, client *ethclient.Client) (Validation *contract return } + +func InitTrigger(setup Setup, client *ethclient.Client) (Trigger *contract.Trigger) { + // Initialise the contract + address := common.HexToAddress(setup.Trigger) + Trigger, err := contract.NewTrigger(address, client) + if err != nil { + log.Fatal(err) + } + + return +} diff --git a/ion-cli/main.go b/ion-cli/main.go index fe22a94..fd4f94e 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -24,11 +24,12 @@ func main() { Ion := config.InitIon(setup, clientTo) Validation := config.InitValidation(setup, clientTo) + Trigger := config.InitTrigger(setup, clientFrom) printInfo(setup) // Launch the CLI - cli.Launch(setup, clientFrom, Validation, Ion) + cli.Launch(setup, clientFrom, Validation, Ion, Trigger) } else { fmt.Print("Error: empty config!\n") os.Exit(3) @@ -49,5 +50,6 @@ func printInfo(setup config.Setup) { fmt.Println("\nRPC Client [from]:") fmt.Println("Listening on:\t\t" + setup.AddrFrom) fmt.Println("User Account:\t\t" + setup.AccountFrom) + fmt.Println("Trigger Contract:\t" + setup.Trigger) fmt.Println("===============================================================") } diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index 7602091..9101a9c 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -7,5 +7,6 @@ "validation-chainid":"0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075", "rpc-from":"https://rinkeby.infura.io", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "trigger-addr":"0x61621bcf02914668f8404c1f860e92fc1893f74c", "keystore-from":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/package.json b/package.json index e9829db..1f95c3d 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "web3-utils": "^1.0.0-beta.33" }, "scripts": { - "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", "deploy": "truffle deploy --network development", "depclique": "truffle deploy --network clique", diff --git a/test/ion.js b/test/ion.js index 0c4765d..2235923 100644 --- a/test/ion.js +++ b/test/ion.js @@ -340,39 +340,6 @@ contract('Ion.js', (accounts) => { await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_DEPLOYED_RINKEBY_ADDR).should.be.rejected; }) -// it('Verify Nested Nodes Verification', async () => { -// const patricia = await PatriciaTrieTest.new(); -// -// path = "0x8461626364"; -// value = "0x857465737434"; -// nodes = "0xf8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808080" -// rootHash = "0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c"; -// -// verified = await patricia.verifyProof.call(value, nodes, path, rootHash); -// assert.ok(verified, "Patricia proof failed."); -// }) -// -// it('Fail Nested Nodes Verification', async () => { -// const patricia = await PatriciaTrieTest.new(); -// -// path = "0x8461626364"; -// value = "0x857465737434"; -// nodes = "0xf8cbf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080f8428080c58320616274cc842061626386857465737433a05d495bd9e35ab0dab60dec18b21acc860829508e7df1064fce1f0b8fa4c0e8b2808080808080808080808080e583161626a06b1a1127b4c489762c8259381ff9ecf51b7ef0c2879b89e72c993edc944f1ccce5808080ca8220648685746573743480ca822064868574657374358080808080808080808080" -// rootHash = "0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c"; -// -// // Fail with incorrect node value -// await patricia.verifyProof.call(value.slice(0,-2) + "f", nodes, path, rootHash).should.be.rejected; -// -// // Fail with incorrect RLP-encoded nodes -// await patricia.verifyProof.call(value, nodes.slice(0, -2) + "f", path, rootHash).should.be.rejected; -// -// // Fail with incorrect path -// await patricia.verifyProof.call(value, nodes, path.slice(0, -2) + "f", rootHash).should.be.rejected; -// -// // Fail with incorrect root node hash -// await patricia.verifyProof.call(value, nodes, path, rootHash.slice(0, -2) + "f").should.be.rejected; -// }) - }) async function verifyReceipts(eP, txHash) { From 365ce6329dde4386506ccd94059bec625d79663b Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Fri, 3 Aug 2018 16:01:16 +0100 Subject: [PATCH 107/203] WIP need to get transaction signature to verify executiongit status! --- ion-cli/flow_test/utils.go | 80 +++++++++++++++++++++++++++++++++ ion-cli/flow_test/utils_test.go | 70 +++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/ion-cli/flow_test/utils.go b/ion-cli/flow_test/utils.go index 0756e22..ef6c615 100644 --- a/ion-cli/flow_test/utils.go +++ b/ion-cli/flow_test/utils.go @@ -333,3 +333,83 @@ func CompileAndDeployValidation( return resChan } + +// CompileAndDeployTriggerVerifierAndConsumerFunction method +func CompileAndDeployTriggerVerifierAndConsumerFunction( + ctx context.Context, + client bind.ContractTransactor, + userKey *ecdsa.PrivateKey, + ionContractAddress common.Address, +) <-chan ContractInstance { + // --------------------------------------------- + // COMPILE VALIDATION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + triggerEventVerifierContractPath := basePath + "TriggerEventVerifier.sol" + consumerFunctionContractPath := basePath + "Function.sol" + + contracts, err := compiler.CompileSolidity("", consumerFunctionContractPath, triggerEventVerifierContractPath) + if err != nil { + log.Fatal("ERROR failed to compile Ion.sol:", err) + } + + triggerEventVerifierContract := contracts[triggerEventVerifierContractPath+":TriggerEventVerifier"] + triggerEventVerifierBinStr, triggerEventVerifierABIStr := getContractBytecodeAndABI(triggerEventVerifierContract) + consumerFunctionContract := contracts[consumerFunctionContractPath+":Function"] + consumerFunctionBinStr, consumerFunctionABIStr := getContractBytecodeAndABI(consumerFunctionContract) + + // --------------------------------------------- + // DEPLOY TRIGGER EVENT CONTRACT + // --------------------------------------------- + triggerEventSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + triggerEventVerifierBinStr, + triggerEventVerifierABIStr, + nil, + uint64(3000000), + ) + + resChan := make(chan ContractInstance) + + // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed + // Ion depends on PatriciaTrie library + go func() { + defer close(resChan) + deployBackend := client.(bind.DeployBackend) + + // wait for trigger event contract to be deployed + triggerEventAddr, err := bind.WaitDeployed(ctx, deployBackend, triggerEventSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // DEPLOY CONSUMER FUNCTION CONTRACT + // --------------------------------------------- + consumerFunctionSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + consumerFunctionBinStr, + consumerFunctionABIStr, + nil, + uint64(3000000), + ionContractAddress, + triggerEventAddr, + ) + + resChan <- ContractInstance{triggerEventVerifierContract, triggerEventAddr} + + // wait for consumer function contract to be deployed + consumerFunctionAddr, err := bind.WaitDeployed(ctx, deployBackend, consumerFunctionSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + resChan <- ContractInstance{consumerFunctionContract, consumerFunctionAddr} + }() + + return resChan +} diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index ca6cd0a..5d21dac 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -156,7 +156,7 @@ func TestVerifyTx(t *testing.T) { clientRPC := ClientRPC(urlEventChain) defer clientRPC.Close() - blockNumberStr, _, err := BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) + blockNumberStr, txTrigger, err := BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) if err != nil { t.Fatal("ERROR couldn't find block by tx hash: ", err) } @@ -304,9 +304,73 @@ func TestVerifyTx(t *testing.T) { t.Fatal("ERROR while waiting for contract deployment", err) } + // --------------------------------------------- + // COMPILE AND DEPLOY TRIGGER VERIFIER AND CONSUMER FUNCTION + // --------------------------------------------- + contractChan = CompileAndDeployTriggerVerifierAndConsumerFunction( + ctx, + blockchain, + userKey, + ionContractInstance.Address, + ) + blockchain.Commit() + <-contractChan // triggerEventVerifierContractInstance := <-contractChan + blockchain.Commit() + consumerFunctionContractInstance := <-contractChan + + // --------------------------------------------- + // FIXME + // VERIFY FUNCTION EXECUITION + // let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); + // --------------------------------------------- + txTriggerPath := []byte{0x13} // SHOULD SOMEHOW BE DYNAMIC! + txTriggerRLP, _ := rlp.EncodeToBytes(txTrigger) + txTriggerProofArr := Proof(txTrie, txTriggerPath[:]) + receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[0x13]) + receiptTriggerProofArr := Proof(receiptTrie, txTriggerPath[:]) + + // get tx sender TODO!!! + + triggerCalledBy := userAddr + + txVerifyAndExecuteFunction := TransactionContract( + ctx, + blockchain, + userKey, + consumerFunctionContractInstance.Contract, + consumerFunctionContractInstance.Address, + nil, + uint64(3000000), + "verifyAndExecute", + testChainID, + blockHash, + txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, + txTriggerPath, // TEST_PATH, + txTriggerRLP, // TEST_TX_VALUE, + txTriggerProofArr, // TEST_TX_NODES, + receiptTrigger, // TEST_RECEIPT_VALUE, + receiptTriggerProofArr, // TEST_RECEIPT_NODES, + triggerCalledBy, // TRIG_CALLED_BY, + ) + + t.Logf("%0x\n", txTriggerPath) + t.Logf("%0x\n", txTriggerRLP) + t.Logf("%0x\n", txTriggerProofArr) + t.Logf("%0x\n", receiptTrigger) + t.Logf("%0x\n", receiptTriggerProofArr) + t.Logf("%0x\n", triggerCalledBy) + + blockchain.Commit() + verifyAndExecuteFunctionReceipt, err := bind.WaitMined(ctx, blockchain, txVerifyAndExecuteFunction) + if err != nil || verifyAndExecuteFunctionReceipt.Status == 0 { + t.Logf("\n\n%#v\n\n%#v\n", txTrigger, verifyAndExecuteFunctionReceipt) + t.Fatal("ERROR while waiting for contract deployment", err) + } + + //blockchain.Commit() + //<-contractChan // PatriciaTrie libraryContractInstance + // ==================================================================================================== // TODO - // let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); - // let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, "0x"+nodes.toString('hex'), TEST_PATH); // let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); } From 656ca8e441c2c3d9f36808d7cc05ffdaf92607b2 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Fri, 3 Aug 2018 22:19:26 +0100 Subject: [PATCH 108/203] verifying function --- ion-cli/flow_test/utils_test.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index 5d21dac..77677a6 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rlp" @@ -330,8 +331,8 @@ func TestVerifyTx(t *testing.T) { receiptTriggerProofArr := Proof(receiptTrie, txTriggerPath[:]) // get tx sender TODO!!! - - triggerCalledBy := userAddr + signer := types.HomesteadSigner{} // blockchain simulater signer is this one + triggerCalledBy, _ := types.Sender(signer, txTrigger) txVerifyAndExecuteFunction := TransactionContract( ctx, @@ -353,13 +354,6 @@ func TestVerifyTx(t *testing.T) { triggerCalledBy, // TRIG_CALLED_BY, ) - t.Logf("%0x\n", txTriggerPath) - t.Logf("%0x\n", txTriggerRLP) - t.Logf("%0x\n", txTriggerProofArr) - t.Logf("%0x\n", receiptTrigger) - t.Logf("%0x\n", receiptTriggerProofArr) - t.Logf("%0x\n", triggerCalledBy) - blockchain.Commit() verifyAndExecuteFunctionReceipt, err := bind.WaitMined(ctx, blockchain, txVerifyAndExecuteFunction) if err != nil || verifyAndExecuteFunctionReceipt.Status == 0 { @@ -367,6 +361,9 @@ func TestVerifyTx(t *testing.T) { t.Fatal("ERROR while waiting for contract deployment", err) } + // TODO check logs to confirm executed + //t.Logf("verifyAndExecuteFunctionReceipt: %#v\n", verifyAndExecuteFunctionReceipt.Logs) + //blockchain.Commit() //<-contractChan // PatriciaTrie libraryContractInstance From e2352a86e22c7a64bffabdbd481c4542d6fad649 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Fri, 3 Aug 2018 23:55:30 +0100 Subject: [PATCH 109/203] flow test verifies that consumer function was launched --- ion-cli/flow_test/flow_test.go | 273 ++++++++++++++++++++++++++++++++ ion-cli/flow_test/utils_test.go | 249 ----------------------------- 2 files changed, 273 insertions(+), 249 deletions(-) create mode 100644 ion-cli/flow_test/flow_test.go diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/flow_test.go new file mode 100644 index 0000000..caa398f --- /dev/null +++ b/ion-cli/flow_test/flow_test.go @@ -0,0 +1,273 @@ +package ionflow + +import ( + "bytes" + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rlp" +) + +// TODO +// avoid having to get data from RInkeby, make it deploy a triger function into a PoA chain + +// TestVerifyTx test for the full flow of Ion +func TestVerifyTx(t *testing.T) { + ctx := context.Background() + + // --------------------------------------------- + // HARD CODED DATA + // --------------------------------------------- + testValidators := [7]common.Hash{ + common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), + common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), + common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), + common.HexToHash("0xb279182d99e65703f0076e4812653aab85fca0f0"), + common.HexToHash("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), + common.HexToHash("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), + common.HexToHash("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), + } + + deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") + testChainID := common.HexToHash("0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254") + + urlEventChain := "https://rinkeby.infura.io" + txHashWithEvent := common.HexToHash("0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") + + signer := types.HomesteadSigner{} // blockchain simulater signer is this one + userKey, _ := crypto.GenerateKey() + userAddr := crypto.PubkeyToAddress(userKey.PublicKey) + userIntialBalance := big.NewInt(1000000000) + + // --------------------------------------------- + // GET BLOCK WITH EVENT FROM RINKEBY CHAIN + // --------------------------------------------- + + clientRPC := ClientRPC(urlEventChain) + defer clientRPC.Close() + + blockNumberStr, txTrigger, err := BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) + if err != nil { + t.Fatal("ERROR couldn't find block by tx hash: ", err) + } + + var blockNumber big.Int + blockNumber.SetString((*blockNumberStr)[2:], 16) + + client := ethclient.NewClient(clientRPC) + eventTxBlockNumber := blockNumber + block, err := client.BlockByNumber(ctx, &eventTxBlockNumber) + if err != nil { + t.Fatal("ERROR retriving block: ", err) + } + + // --------------------------------------------- + // START BLOCKCHAIN SIMULATOR + // --------------------------------------------- + alloc := make(core.GenesisAlloc) + alloc[userAddr] = core.GenesisAccount{Balance: userIntialBalance} + blockchain := backends.NewSimulatedBackend(alloc) + + // --------------------------------------------- + // COMPILE AND DEPLOY ION + // --------------------------------------------- + contractChan := CompileAndDeployIon(ctx, blockchain, userKey, deployedChainID) + blockchain.Commit() + <-contractChan // PatriciaTrie libraryContractInstance + blockchain.Commit() + ionContractInstance := <-contractChan + + // --------------------------------------------- + // COMPILE AND DEPLOY VALIDATION + // --------------------------------------------- + contractChan = CompileAndDeployValidation(ctx, blockchain, userKey, deployedChainID) + blockchain.Commit() + validationContractInstance := <-contractChan + + // --------------------------------------------- + // REGISTER CHAIN ON ION + // --------------------------------------------- + var validationContractAddr [20]byte + copy(validationContractAddr[:], validationContractInstance.Address.Bytes()) + txRegisterChainIon := TransactionContract( + ctx, + blockchain, + userKey, + ionContractInstance.Contract, + ionContractInstance.Address, + nil, + uint64(3000000), + "RegisterChain", + testChainID, + validationContractAddr, + ) + blockchain.Commit() + registerChainIonReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainIon) + if err != nil || registerChainIonReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // REGISTER CHAIN ON VALIDATION + // --------------------------------------------- + var genesisHash [32]byte + copy(genesisHash[:], block.ParentHash().Bytes()) + txRegisterChainValidation := TransactionContract( + ctx, + blockchain, + userKey, + validationContractInstance.Contract, + validationContractInstance.Address, + nil, + uint64(3000000), + "RegisterChain", + testChainID, + testValidators, + genesisHash, + ) + blockchain.Commit() + registerChainValidationReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainValidation) + if err != nil || registerChainValidationReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // SUBMIT BLOCK ON VALIDATION + // --------------------------------------------- + blockHeader := block.Header() + extraData := blockHeader.Extra + unsignedExtraData := extraData[:len(extraData)-(64+1)] // 64 bytes + 1 vanity byte + signedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) + blockHeader.Extra = unsignedExtraData + unsignedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) + txSubmitBlockValidation := TransactionContract( + ctx, + blockchain, + userKey, + validationContractInstance.Contract, + validationContractInstance.Address, + nil, + uint64(3000000), + "SubmitBlock", + testChainID, + unsignedBlockHeaderRLP, + signedBlockHeaderRLP, + ) + + blockchain.Commit() + submitBlockValidationReceipt, err := bind.WaitMined(ctx, blockchain, txSubmitBlockValidation) + if err != nil || submitBlockValidationReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // CHECK ROOTS PROOF ON ION + // --------------------------------------------- + blockHash := block.Hash() + txTrie := TxTrie(block.Transactions()) + blockReceipts := GetBlockTxReceipts(client, block) + receiptTrie := ReceiptTrie(blockReceipts) + + txKey := []byte{0x01} + txProofArr := Proof(txTrie, txKey) + receiptKey := []byte{0x01} + receiptProofArr := Proof(receiptTrie, receiptKey) + + checkRootsProofIon := TransactionContract( + ctx, + blockchain, + userKey, + ionContractInstance.Contract, + ionContractInstance.Address, + nil, + uint64(3000000), + "CheckRootsProof", + testChainID, + blockHash, + txProofArr, + receiptProofArr, + ) + + blockchain.Commit() + chackRootsProofIonReceipt, err := bind.WaitMined(ctx, blockchain, checkRootsProofIon) + if err != nil || chackRootsProofIonReceipt.Status == 0 { + t.Fatal("ERROR while waiting for contract deployment", err) + } + + // --------------------------------------------- + // COMPILE AND DEPLOY TRIGGER VERIFIER AND CONSUMER FUNCTION + // --------------------------------------------- + contractChan = CompileAndDeployTriggerVerifierAndConsumerFunction( + ctx, + blockchain, + userKey, + ionContractInstance.Address, + ) + blockchain.Commit() + <-contractChan // triggerEventVerifierContractInstance := <-contractChan + blockchain.Commit() + consumerFunctionContractInstance := <-contractChan + + // --------------------------------------------- + // VERIFY FUNCTION EXECUITION + // --------------------------------------------- + txTriggerPath := []byte{0x13} // SHOULD SOMEHOW BE DYNAMIC! + txTriggerRLP, _ := rlp.EncodeToBytes(txTrigger) + txTriggerProofArr := Proof(txTrie, txTriggerPath[:]) + receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[0x13]) + receiptTriggerProofArr := Proof(receiptTrie, txTriggerPath[:]) + triggerCalledBy, _ := types.Sender(signer, txTrigger) + + txVerifyAndExecuteFunction := TransactionContract( + ctx, + blockchain, + userKey, + consumerFunctionContractInstance.Contract, + consumerFunctionContractInstance.Address, + nil, + uint64(3000000), + "verifyAndExecute", + testChainID, + blockHash, + txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, + txTriggerPath, // TEST_PATH, + txTriggerRLP, // TEST_TX_VALUE, + txTriggerProofArr, // TEST_TX_NODES, + receiptTrigger, // TEST_RECEIPT_VALUE, + receiptTriggerProofArr, // TEST_RECEIPT_NODES, + triggerCalledBy, // TRIG_CALLED_BY, + ) + + blockchain.Commit() + verifyAndExecuteFunctionReceipt, err := bind.WaitMined(ctx, blockchain, txVerifyAndExecuteFunction) + if err != nil || verifyAndExecuteFunctionReceipt.Status == 0 { + t.Logf("\n\n%#v\n\n%#v\n", txTrigger, verifyAndExecuteFunctionReceipt) + t.Fatal("ERROR while waiting for contract deployment", err) + } + + // confirm the Executed event was emited by Consumer Function + eventSignatureHash := crypto.Keccak256Hash([]byte("Executed()")) // Ion argument + t.Logf("Event Signature Hash: %v\n", eventSignatureHash) + + foundExecuted := false + for _, vlog := range verifyAndExecuteFunctionReceipt.Logs { + if len(vlog.Topics) < 1 { + continue + } + foundExecuted = bytes.Equal(vlog.Topics[0].Bytes(), eventSignatureHash.Bytes()) + if foundExecuted { + break + } + } + if !foundExecuted { + t.Fatal("ERROR did not find Executed() event") + } +} diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/flow_test/utils_test.go index 77677a6..4863205 100644 --- a/ion-cli/flow_test/utils_test.go +++ b/ion-cli/flow_test/utils_test.go @@ -9,12 +9,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rlp" ) func TestCompileAndDeployIon(t *testing.T) { @@ -126,248 +122,3 @@ func TestRegisterChain(t *testing.T) { t.Log("ERROR expecting value of chains(validation.address) to be true, but it was ", isChainRegistered) } } - -func TestVerifyTx(t *testing.T) { - ctx := context.Background() - - testValidators := [7]common.Hash{ - common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), - common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), - common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), - common.HexToHash("0xb279182d99e65703f0076e4812653aab85fca0f0"), - common.HexToHash("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), - common.HexToHash("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), - common.HexToHash("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), - } - - deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") - testChainID := common.HexToHash("0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254") - - urlEventChain := "https://rinkeby.infura.io" - txHashWithEvent := common.HexToHash("0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") - - userKey, _ := crypto.GenerateKey() - userAddr := crypto.PubkeyToAddress(userKey.PublicKey) - userIntialBalance := big.NewInt(1000000000) - - // --------------------------------------------- - // GET BLOCK WITH EVENT FROM RINKEBY CHAIN - // --------------------------------------------- - - clientRPC := ClientRPC(urlEventChain) - defer clientRPC.Close() - - blockNumberStr, txTrigger, err := BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) - if err != nil { - t.Fatal("ERROR couldn't find block by tx hash: ", err) - } - - var blockNumber big.Int - blockNumber.SetString((*blockNumberStr)[2:], 16) - - client := ethclient.NewClient(clientRPC) - eventTxBlockNumber := blockNumber - block, err := client.BlockByNumber(ctx, &eventTxBlockNumber) - if err != nil { - t.Fatal("ERROR retriving block: ", err) - } - - // --------------------------------------------- - // START BLOCKCHAIN SIMULATOR - // --------------------------------------------- - alloc := make(core.GenesisAlloc) - alloc[userAddr] = core.GenesisAccount{Balance: userIntialBalance} - blockchain := backends.NewSimulatedBackend(alloc) - - // --------------------------------------------- - // COMPILE AND DEPLOY ION - // --------------------------------------------- - contractChan := CompileAndDeployIon(ctx, blockchain, userKey, deployedChainID) - blockchain.Commit() - <-contractChan // PatriciaTrie libraryContractInstance - blockchain.Commit() - ionContractInstance := <-contractChan - - // --------------------------------------------- - // COMPILE AND DEPLOY VALIDATION - // --------------------------------------------- - contractChan = CompileAndDeployValidation(ctx, blockchain, userKey, deployedChainID) - blockchain.Commit() - validationContractInstance := <-contractChan - - // --------------------------------------------- - // REGISTER CHAIN ON ION - // --------------------------------------------- - var validationContractAddr [20]byte - copy(validationContractAddr[:], validationContractInstance.Address.Bytes()) - txRegisterChainIon := TransactionContract( - ctx, - blockchain, - userKey, - ionContractInstance.Contract, - ionContractInstance.Address, - nil, - uint64(3000000), - "RegisterChain", - testChainID, - validationContractAddr, - ) - blockchain.Commit() - registerChainIonReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainIon) - if err != nil || registerChainIonReceipt.Status == 0 { - t.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // REGISTER CHAIN ON VALIDATION - // --------------------------------------------- - var genesisHash [32]byte - copy(genesisHash[:], block.ParentHash().Bytes()) - txRegisterChainValidation := TransactionContract( - ctx, - blockchain, - userKey, - validationContractInstance.Contract, - validationContractInstance.Address, - nil, - uint64(3000000), - "RegisterChain", - testChainID, - testValidators, - genesisHash, - ) - blockchain.Commit() - registerChainValidationReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainValidation) - if err != nil || registerChainValidationReceipt.Status == 0 { - t.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // SUBMIT BLOCK ON VALIDATION - // --------------------------------------------- - blockHeader := block.Header() - extraData := blockHeader.Extra - unsignedExtraData := extraData[:len(extraData)-(64+1)] // 64 bytes + 1 vanity byte - signedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) - blockHeader.Extra = unsignedExtraData - unsignedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) - txSubmitBlockValidation := TransactionContract( - ctx, - blockchain, - userKey, - validationContractInstance.Contract, - validationContractInstance.Address, - nil, - uint64(3000000), - "SubmitBlock", - testChainID, - unsignedBlockHeaderRLP, - signedBlockHeaderRLP, - ) - - blockchain.Commit() - submitBlockValidationReceipt, err := bind.WaitMined(ctx, blockchain, txSubmitBlockValidation) - if err != nil || submitBlockValidationReceipt.Status == 0 { - t.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // CHECK ROOTS PROOF ON ION - // --------------------------------------------- - blockHash := block.Hash() - txTrie := TxTrie(block.Transactions()) - blockReceipts := GetBlockTxReceipts(client, block) - receiptTrie := ReceiptTrie(blockReceipts) - - txKey := []byte{0x01} - txProofArr := Proof(txTrie, txKey) - receiptKey := []byte{0x01} - receiptProofArr := Proof(receiptTrie, receiptKey) - - checkRootsProofIon := TransactionContract( - ctx, - blockchain, - userKey, - ionContractInstance.Contract, - ionContractInstance.Address, - nil, - uint64(3000000), - "CheckRootsProof", - testChainID, - blockHash, - txProofArr, - receiptProofArr, - ) - - blockchain.Commit() - chackRootsProofIonReceipt, err := bind.WaitMined(ctx, blockchain, checkRootsProofIon) - if err != nil || chackRootsProofIonReceipt.Status == 0 { - t.Fatal("ERROR while waiting for contract deployment", err) - } - - // --------------------------------------------- - // COMPILE AND DEPLOY TRIGGER VERIFIER AND CONSUMER FUNCTION - // --------------------------------------------- - contractChan = CompileAndDeployTriggerVerifierAndConsumerFunction( - ctx, - blockchain, - userKey, - ionContractInstance.Address, - ) - blockchain.Commit() - <-contractChan // triggerEventVerifierContractInstance := <-contractChan - blockchain.Commit() - consumerFunctionContractInstance := <-contractChan - - // --------------------------------------------- - // FIXME - // VERIFY FUNCTION EXECUITION - // let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); - // --------------------------------------------- - txTriggerPath := []byte{0x13} // SHOULD SOMEHOW BE DYNAMIC! - txTriggerRLP, _ := rlp.EncodeToBytes(txTrigger) - txTriggerProofArr := Proof(txTrie, txTriggerPath[:]) - receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[0x13]) - receiptTriggerProofArr := Proof(receiptTrie, txTriggerPath[:]) - - // get tx sender TODO!!! - signer := types.HomesteadSigner{} // blockchain simulater signer is this one - triggerCalledBy, _ := types.Sender(signer, txTrigger) - - txVerifyAndExecuteFunction := TransactionContract( - ctx, - blockchain, - userKey, - consumerFunctionContractInstance.Contract, - consumerFunctionContractInstance.Address, - nil, - uint64(3000000), - "verifyAndExecute", - testChainID, - blockHash, - txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, - txTriggerPath, // TEST_PATH, - txTriggerRLP, // TEST_TX_VALUE, - txTriggerProofArr, // TEST_TX_NODES, - receiptTrigger, // TEST_RECEIPT_VALUE, - receiptTriggerProofArr, // TEST_RECEIPT_NODES, - triggerCalledBy, // TRIG_CALLED_BY, - ) - - blockchain.Commit() - verifyAndExecuteFunctionReceipt, err := bind.WaitMined(ctx, blockchain, txVerifyAndExecuteFunction) - if err != nil || verifyAndExecuteFunctionReceipt.Status == 0 { - t.Logf("\n\n%#v\n\n%#v\n", txTrigger, verifyAndExecuteFunctionReceipt) - t.Fatal("ERROR while waiting for contract deployment", err) - } - - // TODO check logs to confirm executed - //t.Logf("verifyAndExecuteFunctionReceipt: %#v\n", verifyAndExecuteFunctionReceipt.Logs) - - //blockchain.Commit() - //<-contractChan // PatriciaTrie libraryContractInstance - - // ==================================================================================================== - // TODO - // let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); -} From 06f4f7ec8e0fe3301910a1633144c17856bea3a7 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Sat, 4 Aug 2018 00:03:41 +0100 Subject: [PATCH 110/203] flow test verifies that consumer function was launched --- ion-cli/flow_test/flow_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/flow_test.go index caa398f..c573333 100644 --- a/ion-cli/flow_test/flow_test.go +++ b/ion-cli/flow_test/flow_test.go @@ -255,7 +255,6 @@ func TestVerifyTx(t *testing.T) { // confirm the Executed event was emited by Consumer Function eventSignatureHash := crypto.Keccak256Hash([]byte("Executed()")) // Ion argument - t.Logf("Event Signature Hash: %v\n", eventSignatureHash) foundExecuted := false for _, vlog := range verifyAndExecuteFunctionReceipt.Logs { From dede262637a36fda4bfd65fa0372b46edb75f4f1 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 6 Aug 2018 08:55:54 +0100 Subject: [PATCH 111/203] restructured the ion-cli directories --- ion-cli/cli/cli.go | 36 +++++++------- ion-cli/cli/proof_test.go | 38 -------------- ion-cli/cli/rpc.go | 4 -- ion-cli/{flow_test => ionflow}/client.go | 0 ion-cli/{flow_test => ionflow}/client_test.go | 0 .../raw_example_test.go | 0 ion-cli/{flow_test => ionflow}/trie.go | 0 ion-cli/{flow_test => ionflow}/utils.go | 0 ion-cli/{flow_test => ionflow}/utils_test.go | 0 ion-cli/{cli => utils}/proof.go | 21 +++++++- ion-cli/utils/proof_test.go | 49 +++++++++++++++++++ 11 files changed, 87 insertions(+), 61 deletions(-) delete mode 100644 ion-cli/cli/proof_test.go rename ion-cli/{flow_test => ionflow}/client.go (100%) rename ion-cli/{flow_test => ionflow}/client_test.go (100%) rename ion-cli/{flow_test => ionflow}/raw_example_test.go (100%) rename ion-cli/{flow_test => ionflow}/trie.go (100%) rename ion-cli/{flow_test => ionflow}/utils.go (100%) rename ion-cli/{flow_test => ionflow}/utils_test.go (100%) rename ion-cli/{cli => utils}/proof.go (86%) create mode 100644 ion-cli/utils/proof_test.go diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 3a686d2..4c0cf89 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -263,24 +263,24 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra }, }) - shell.AddCmd(&ishell.Cmd{ - Name: "verifyAndExecute", - Help: "use: verifyAndExecute [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrTo) - if len(c.Args) == 0 { - c.Println("Select a block") - } else if len(c.Args) > 2 { - c.Println("Too many arguments entered.") - } else { - c.Println("RLP encode block: " + c.Args[0]) - rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) - c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) - } - c.Println("===============================================================") - }, - }) + // shell.AddCmd(&ishell.Cmd{ + // Name: "verifyAndExecute", + // Help: "use: verifyAndExecute [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrTo) + // if len(c.Args) == 0 { + // c.Println("Select a block") + // } else if len(c.Args) > 2 { + // c.Println("Too many arguments entered.") + // } else { + // c.Println("RLP encode block: " + c.Args[0]) + // rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) + // c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) + // } + // c.Println("===============================================================") + // }, + // }) //--------------------------------------------------------------------------------------------- // Ion Specific Commands diff --git a/ion-cli/cli/proof_test.go b/ion-cli/cli/proof_test.go deleted file mode 100644 index 905b1f1..0000000 --- a/ion-cli/cli/proof_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd - -package cli_test - -import ( - "encoding/hex" - "log" - "testing" - - "github.com/clearmatics/ion/ion-cli/cli" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/stretchr/testify/assert" -) - -func initTestClient() (client *ethclient.Client) { - client, err := ethclient.Dial("https://mainnet.infura.io") - if err != nil { - log.Fatal(err) - } - return client -} - -func Test_GenerateTxProof(t *testing.T) { - client := initTestClient() - - var transaction = "0xd828cadfcc7694d314058404506fc10a4dadac72aba68c286b34137da4156630" - - var expectedRootHash = common.HexToHash("0x363d32a031aea0b43d92989f96fa0d19c75f18d93fe86f1e11be79202a614bd0") - expectedLeaf, _ := hex.DecodeString("f8cb8201e1850d09dc3000827c9f9466323324b77d72c65ea76caa918464836498ebd680b864b31d61b000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000561dedea8f2554241222e2f2eb221e625c7fb7b526a03b8772e36e5f5a4ffc4c1e6ef884c72208e6086b5d637591fe2dc7b8559aec9ba02c1da7488bdf45f01f511358b7b79e330b5e9e28bb3a10e6006e112148460801") - expectedIdx, _ := hex.DecodeString("31") // 49 is 31 in hex bytes - var blockNumber = "5904064" - - rootHash, idx, leaf, _ := cli.GenerateTxProof(client, transaction, blockNumber) - assert.Equal(t, expectedRootHash, rootHash) - assert.Equal(t, expectedIdx, idx) - assert.Equal(t, expectedLeaf, leaf) -} diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index ef45363..e59a408 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -65,10 +65,6 @@ func getBlock(client *ethclient.Client, block string) { fmt.Println(string(b)) } -func generateProof() { - -} - // func calculateRlpEncoding(client *ethclient.Client, block string) { func calculateRlpEncoding(client *ethclient.Client, block string) (rlpSignedBlock []byte, rlpUnsignedBlock []byte) { // var blockHeader header diff --git a/ion-cli/flow_test/client.go b/ion-cli/ionflow/client.go similarity index 100% rename from ion-cli/flow_test/client.go rename to ion-cli/ionflow/client.go diff --git a/ion-cli/flow_test/client_test.go b/ion-cli/ionflow/client_test.go similarity index 100% rename from ion-cli/flow_test/client_test.go rename to ion-cli/ionflow/client_test.go diff --git a/ion-cli/flow_test/raw_example_test.go b/ion-cli/ionflow/raw_example_test.go similarity index 100% rename from ion-cli/flow_test/raw_example_test.go rename to ion-cli/ionflow/raw_example_test.go diff --git a/ion-cli/flow_test/trie.go b/ion-cli/ionflow/trie.go similarity index 100% rename from ion-cli/flow_test/trie.go rename to ion-cli/ionflow/trie.go diff --git a/ion-cli/flow_test/utils.go b/ion-cli/ionflow/utils.go similarity index 100% rename from ion-cli/flow_test/utils.go rename to ion-cli/ionflow/utils.go diff --git a/ion-cli/flow_test/utils_test.go b/ion-cli/ionflow/utils_test.go similarity index 100% rename from ion-cli/flow_test/utils_test.go rename to ion-cli/ionflow/utils_test.go diff --git a/ion-cli/cli/proof.go b/ion-cli/utils/proof.go similarity index 86% rename from ion-cli/cli/proof.go rename to ion-cli/utils/proof.go index 934e379..23042a9 100644 --- a/ion-cli/cli/proof.go +++ b/ion-cli/utils/proof.go @@ -1,4 +1,4 @@ -package cli +package utils import ( "bytes" @@ -8,6 +8,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" @@ -15,6 +16,24 @@ import ( "github.com/maxrobot/go-ethereum/crypto" ) +type rpcTransaction struct { + tx *types.Transaction + txExtraInfo +} + +type txExtraInfo struct { + BlockNumber *string `json:"blockNumber,omitempty"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + From *common.Address `json:"from,omitempty"` +} + +func GenerateProof(client *ethclient.Client, txHash common.Hash) { + // blockNumberStr, _, err := BlockNumberByTransactionHash(context.Background(), client, txHash) + tx, block, _ := client.TransactionByHash(context.Background(), txHash) + fmt.Printf("%x\t%x\n", tx, block) + +} + // GenerateTxProof takes a transaction and block, returns the trie root, tx index and proof path func GenerateTxProof(client *ethclient.Client, transaction string, blockNum string) (root common.Hash, txIdx []byte, leaf []byte, proof *ethdb.MemDatabase) { // Select a specific block diff --git a/ion-cli/utils/proof_test.go b/ion-cli/utils/proof_test.go new file mode 100644 index 0000000..f6e59af --- /dev/null +++ b/ion-cli/utils/proof_test.go @@ -0,0 +1,49 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package utils_test + +import ( + "log" + "testing" + + "github.com/clearmatics/ion/ion-cli/utils" + + "github.com/ethereum/go-ethereum/ethclient" +) + +// func initTestClient() (client *ethclient.Client) { +// client, err := ethclient.Dial("https://mainnet.infura.io") +// if err != nil { +// log.Fatal(err) +// } +// return client +// } + +// func Test_GenerateTxProof(t *testing.T) { +// client := initTestClient() + +// var transaction = "0xd828cadfcc7694d314058404506fc10a4dadac72aba68c286b34137da4156630" + +// var expectedRootHash = common.HexToHash("0x363d32a031aea0b43d92989f96fa0d19c75f18d93fe86f1e11be79202a614bd0") +// expectedLeaf, _ := hex.DecodeString("f8cb8201e1850d09dc3000827c9f9466323324b77d72c65ea76caa918464836498ebd680b864b31d61b000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000561dedea8f2554241222e2f2eb221e625c7fb7b526a03b8772e36e5f5a4ffc4c1e6ef884c72208e6086b5d637591fe2dc7b8559aec9ba02c1da7488bdf45f01f511358b7b79e330b5e9e28bb3a10e6006e112148460801") +// expectedIdx, _ := hex.DecodeString("31") // 49 is 31 in hex bytes +// var blockNumber = "5904064" + +// rootHash, idx, leaf, _ := cli.GenerateTxProof(client, transaction, blockNumber) +// assert.Equal(t, expectedRootHash, rootHash) +// assert.Equal(t, expectedIdx, idx) +// assert.Equal(t, expectedLeaf, leaf) +// } + +func Test_GenerateProof(t *testing.T) { + CONTRACT_ADDR, _ := utils.StringToBytes32("61621bcf02914668f8404c1f860e92fc1893f74c") + TXHASH, _ := utils.StringToBytes32("afc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") + + // Connect to the RPC Client + client, err := ethclient.Dial("https://rinkeby.infura.io") + if err != nil { + log.Fatalf("could not create RPC client: %v", err) + } + + utils.GenerateProof(client, TXHASH) +} From a0b7da9c57275aff24b470e09dfe2383ec5979e9 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Mon, 6 Aug 2018 12:26:28 +0100 Subject: [PATCH 112/203] made tx index for verifier dynamic --- ion-cli/flow_test/flow_test.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ion-cli/flow_test/flow_test.go b/ion-cli/flow_test/flow_test.go index c573333..b3e11be 100644 --- a/ion-cli/flow_test/flow_test.go +++ b/ion-cli/flow_test/flow_test.go @@ -172,7 +172,8 @@ func TestVerifyTx(t *testing.T) { // CHECK ROOTS PROOF ON ION // --------------------------------------------- blockHash := block.Hash() - txTrie := TxTrie(block.Transactions()) + blockTransactions := block.Transactions() + txTrie := TxTrie(blockTransactions) blockReceipts := GetBlockTxReceipts(client, block) receiptTrie := ReceiptTrie(blockReceipts) @@ -219,10 +220,17 @@ func TestVerifyTx(t *testing.T) { // --------------------------------------------- // VERIFY FUNCTION EXECUITION // --------------------------------------------- - txTriggerPath := []byte{0x13} // SHOULD SOMEHOW BE DYNAMIC! + var txTriggerIdx uint8 + for idx, tx := range blockTransactions { + if txHashWithEvent == tx.Hash() { + txTriggerIdx = uint8(idx) + break + } + } + txTriggerPath := []byte{txTriggerIdx} txTriggerRLP, _ := rlp.EncodeToBytes(txTrigger) txTriggerProofArr := Proof(txTrie, txTriggerPath[:]) - receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[0x13]) + receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[txTriggerIdx]) receiptTriggerProofArr := Proof(receiptTrie, txTriggerPath[:]) triggerCalledBy, _ := types.Sender(signer, txTrigger) From 9f37c2eee17ae35400e06ce149bf1f2c6395e2fa Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 6 Aug 2018 14:39:04 +0100 Subject: [PATCH 113/203] Added generate proof --- ion-cli/ionflow/flow_test.go | 6 +- ion-cli/utils/proof.go | 143 +++++++---------------------------- ion-cli/utils/proof_test.go | 54 +++++-------- 3 files changed, 51 insertions(+), 152 deletions(-) diff --git a/ion-cli/ionflow/flow_test.go b/ion-cli/ionflow/flow_test.go index 6fcf93c..136770f 100644 --- a/ion-cli/ionflow/flow_test.go +++ b/ion-cli/ionflow/flow_test.go @@ -17,7 +17,7 @@ import ( ) // TODO -// avoid having to get data from RInkeby, make it deploy a triger function into a PoA chain +// avoid having to get data from Rinkeby, make it deploy a trigger function into a PoA chain // TestVerifyTx test for the full flow of Ion func TestVerifyTx(t *testing.T) { @@ -66,7 +66,7 @@ func TestVerifyTx(t *testing.T) { eventTxBlockNumber := blockNumber block, err := client.BlockByNumber(ctx, &eventTxBlockNumber) if err != nil { - t.Fatal("ERROR retriving block: ", err) + t.Fatal("ERROR retrieving block: ", err) } // --------------------------------------------- @@ -76,7 +76,7 @@ func TestVerifyTx(t *testing.T) { alloc[userAddr] = core.GenesisAccount{Balance: userIntialBalance} blockchain := backends.NewSimulatedBackend(alloc) - // --------------------------------------------- + // ----txTrigger----------------------------------------- // COMPILE AND DEPLOY ION // --------------------------------------------- contractChan := CompileAndDeployIon(ctx, blockchain, userKey, deployedChainID) diff --git a/ion-cli/utils/proof.go b/ion-cli/utils/proof.go index 23042a9..664aef4 100644 --- a/ion-cli/utils/proof.go +++ b/ion-cli/utils/proof.go @@ -1,19 +1,16 @@ package utils import ( - "bytes" "context" "fmt" - "log" "math/big" + "github.com/clearmatics/ion/ion-cli/ionflow" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/maxrobot/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rpc" ) type rpcTransaction struct { @@ -27,127 +24,41 @@ type txExtraInfo struct { From *common.Address `json:"from,omitempty"` } -func GenerateProof(client *ethclient.Client, txHash common.Hash) { - // blockNumberStr, _, err := BlockNumberByTransactionHash(context.Background(), client, txHash) - tx, block, _ := client.TransactionByHash(context.Background(), txHash) - fmt.Printf("%x\t%x\n", tx, block) - -} - -// GenerateTxProof takes a transaction and block, returns the trie root, tx index and proof path -func GenerateTxProof(client *ethclient.Client, transaction string, blockNum string) (root common.Hash, txIdx []byte, leaf []byte, proof *ethdb.MemDatabase) { - // Select a specific block - blockNumber := new(big.Int) - blockNumber.SetString(blockNum, 10) - - // Fetch header of block num - header, err := client.HeaderByNumber(context.Background(), blockNumber) +func GenerateProof(ctx context.Context, client *rpc.Client, txHash common.Hash) (txTriggerPath []byte, txTriggerRLP []byte, txTriggerProofArr []byte, receiptTrigger []byte, receiptTriggerProofArr []byte) { + blockNumberStr, txTrigger, err := ionflow.BlockNumberByTransactionHash(ctx, client, txHash) if err != nil { - log.Fatal(err) - } - - // Fetch block of block num - block, err := client.BlockByNumber(context.Background(), header.Number) - if err != nil { - log.Fatal(err) - } - - // Select a transaction, index should be 49 - transx := block.Transaction(common.HexToHash(transaction)) - - // Generate the trie - trieObj := new(trie.Trie) - for idx, tx := range block.Transactions() { - rlpIdx, _ := rlp.EncodeToBytes(uint(idx)) // rlp encode index of transaction - rlpTransaction, _ := rlp.EncodeToBytes(tx) // rlp encode transaction - - trieObj.Update(rlpIdx, rlpTransaction) - - // Get the information about the transaction I care about... - if transx == tx { - txIdx = rlpIdx - leaf = rlpTransaction - } - - } - - root = trieObj.Hash() - - // Generate a merkle proof for a key - proof = ethdb.NewMemDatabase() - trieObj.Prove(txIdx, 0, proof) - if proof == nil { - fmt.Printf("prover: nil proof") + fmt.Printf("Error: couldn't find block by tx hash: %s\n", err) } - return -} - -// VerifyTxProof takes a transaction and block, returns the trie root, tx index and proof path -func VerifyTxProof(client *ethclient.Client, transaction string, blockNum string) { - // Select a specific block - blockNumber := new(big.Int) - blockNumber.SetString(blockNum, 10) + // Convert returned blocknumber + var blockNumber big.Int + blockNumber.SetString((*blockNumberStr)[2:], 16) - // Fetch header of block num - header, err := client.HeaderByNumber(context.Background(), blockNumber) + clientETH := ethclient.NewClient(client) + eventTxBlockNumber := blockNumber + block, err := clientETH.BlockByNumber(ctx, &eventTxBlockNumber) if err != nil { - log.Fatal(err) + fmt.Printf("Error: retrieving block: %s\n", err) } - // assert.Equal(t, expectedBlockHash, header.Hash()) - - // Fetch block of block num - block, err := client.BlockByNumber(context.Background(), header.Number) - if err != nil { - log.Fatal(err) - } - // assert.Equal(t, expectedBlockHash, block.Hash()) - - // Select a transaction, index should be 49 - transx := block.Transaction(common.HexToHash(transaction)) - var txIdx []byte - var leaf []byte - // fmt.Printf("\nTransaction:\n% 0x", transx.Hash().Bytes()) - - // Generate the trie - trieObj := new(trie.Trie) - for idx, tx := range block.Transactions() { - rlpIdx, _ := rlp.EncodeToBytes(uint(idx)) // rlp encode index of transaction - rlpTransaction, _ := rlp.EncodeToBytes(tx) // rlp encode transaction - - trieObj.Update(rlpIdx, rlpTransaction) - txRlpHash := crypto.Keccak256Hash(rlpTransaction) + var idx byte + tx := block.Transactions() + txTrie := ionflow.TxTrie(tx) + blockReceipts := ionflow.GetBlockTxReceipts(clientETH, block) + receiptTrie := ionflow.ReceiptTrie(blockReceipts) - fmt.Printf("TxHash[%d]: \t% 0x\n\tHash(RLP(Tx)): \t% 0x\n", - idx, tx.Hash().Bytes(), txRlpHash.Bytes()) - - // Get the information about the transaction I care about... - if transx == tx { - txIdx = rlpIdx - leaf = rlpTransaction + // Calculate transaction index) + for i := 0; i < len(tx); i++ { + if txHash == tx[i].Hash() { + idx = byte(i) } - } - root := trieObj.Hash() - expectedRoot := block.TxHash() - fmt.Printf("\nExpected Root:\t%x\nRecovered Root:\t%x\n", expectedRoot, root) - - // Generate a merkle proof for a key - proof := ethdb.NewMemDatabase() - trieObj.Prove(txIdx, 0, proof) - if proof == nil { - fmt.Printf("prover: nil proof") - } + txTriggerPath = append(txTriggerPath, idx) + txTriggerRLP, _ = rlp.EncodeToBytes(txTrigger) + txTriggerProofArr = ionflow.Proof(txTrie, txTriggerPath[:]) + receiptTrigger, _ = rlp.EncodeToBytes(blockReceipts[txTriggerPath[0]]) + receiptTriggerProofArr = ionflow.Proof(receiptTrie, txTriggerPath[:]) - // Verify the proof - val, _, err := trie.VerifyProof(root, txIdx, proof) - if err != nil { - fmt.Printf("prover: failed to verify proof: %v\nraw proof: %x", err, proof) - } - if !bytes.Equal(val, leaf) { - fmt.Printf("prover: verified value mismatch: have %x, want 'k'", val) - } - fmt.Printf("\nVerified Value:\t%x\nExpected Leaf:\t%x\n", val, leaf) + return } diff --git a/ion-cli/utils/proof_test.go b/ion-cli/utils/proof_test.go index f6e59af..9b95ab0 100644 --- a/ion-cli/utils/proof_test.go +++ b/ion-cli/utils/proof_test.go @@ -3,47 +3,35 @@ package utils_test import ( - "log" + "context" + "encoding/hex" "testing" + "github.com/clearmatics/ion/ion-cli/ionflow" "github.com/clearmatics/ion/ion-cli/utils" - - "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/assert" ) -// func initTestClient() (client *ethclient.Client) { -// client, err := ethclient.Dial("https://mainnet.infura.io") -// if err != nil { -// log.Fatal(err) -// } -// return client -// } - -// func Test_GenerateTxProof(t *testing.T) { -// client := initTestClient() - -// var transaction = "0xd828cadfcc7694d314058404506fc10a4dadac72aba68c286b34137da4156630" - -// var expectedRootHash = common.HexToHash("0x363d32a031aea0b43d92989f96fa0d19c75f18d93fe86f1e11be79202a614bd0") -// expectedLeaf, _ := hex.DecodeString("f8cb8201e1850d09dc3000827c9f9466323324b77d72c65ea76caa918464836498ebd680b864b31d61b000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000561dedea8f2554241222e2f2eb221e625c7fb7b526a03b8772e36e5f5a4ffc4c1e6ef884c72208e6086b5d637591fe2dc7b8559aec9ba02c1da7488bdf45f01f511358b7b79e330b5e9e28bb3a10e6006e112148460801") -// expectedIdx, _ := hex.DecodeString("31") // 49 is 31 in hex bytes -// var blockNumber = "5904064" - -// rootHash, idx, leaf, _ := cli.GenerateTxProof(client, transaction, blockNumber) -// assert.Equal(t, expectedRootHash, rootHash) -// assert.Equal(t, expectedIdx, idx) -// assert.Equal(t, expectedLeaf, leaf) -// } +var TEST_PATH = "13" +var TEST_TX_VALUE = "f86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" +var TEST_TX_NODES = "f90235f871a0804f9c841a6a1d3361d79980581c84e5b4d3e4c9bf33951346775542d0ee0728a0edadb5e660118ea4323654191131b62c81fc00203a15a21c925f9f50d0e4b3e4808080808080a03eda2d64b94c5ed45026a29c75c99677d44c561ea5efea30c1db6299871d5c2e8080808080808080f90151a0bc285699e68d2fe18e7af2cdf7e7e6456e91a3fd31e3c9935bc5bef92e94bf4ba06eb963b2c3a3b6c07a7221aa6f6f86f7cb8ddb45ab1ff1a9dc781f34da1f081fa0deea5b5566e7a5634d91c5fb56e25f4370e3531e2fd71ee17ed6c4ad0be2ced3a0b4e9d14555f162e811cfbcbff9b98a271a197b75271565f693912c2ff75e2131a03b0bc2d764fbefd76848ee2da7b211eb230ede08d8c54e6a868be9f5e42122c1a0b6dd488ad4fb82b0a98dff81ac6766d1dec26b29dc06174de1d315b0ab0bdf0ca066c20ff06dc33777f53eec32b0b9a8d99872bec24bb3998bb520ae6897c21d7ea02db2a399f611ba7993efb4768938a6f61b4add8959ce4c89f201f41e882ff375a02e31051a9f938b9b342b8070db3dd829f62da8d0c83a6dff91a4e3b4cb2adb9ea090e75708e7dbf856b75ed126a960085419fcde0e6a0129a92dffc0cb83ac089680808080808080f86c20b869f86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" +var TEST_RECEIPT_VALUE = "f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" +var TEST_RECEIPT_NODES = "f90335f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" func Test_GenerateProof(t *testing.T) { - CONTRACT_ADDR, _ := utils.StringToBytes32("61621bcf02914668f8404c1f860e92fc1893f74c") + ctx := context.Background() + + // CONTRACT_ADDR, _ := utils.StringToBytes32("61621bcf02914668f8404c1f860e92fc1893f74c") TXHASH, _ := utils.StringToBytes32("afc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") // Connect to the RPC Client - client, err := ethclient.Dial("https://rinkeby.infura.io") - if err != nil { - log.Fatalf("could not create RPC client: %v", err) - } - - utils.GenerateProof(client, TXHASH) + client := ionflow.ClientRPC("https://rinkeby.infura.io") + defer client.Close() + + PATH, TX_VALUE, TX_NODES, RECEIPT_VALUE, RECEIPT_NODES := utils.GenerateProof(ctx, client, TXHASH) + assert.Equal(t, TEST_PATH, hex.EncodeToString(PATH)) + assert.Equal(t, TEST_TX_VALUE, hex.EncodeToString(TX_VALUE)) + assert.Equal(t, TEST_TX_NODES, hex.EncodeToString(TX_NODES)) + assert.Equal(t, TEST_RECEIPT_VALUE, hex.EncodeToString(RECEIPT_VALUE)) + assert.Equal(t, TEST_RECEIPT_NODES, hex.EncodeToString(RECEIPT_NODES)) } From 2fc8c8e1cf85a0293aee0bd921a66504c500df86 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 6 Aug 2018 14:42:04 +0100 Subject: [PATCH 114/203] Resolved apparent conflicts in package-lock.json --- package-lock.json | 413 ---------------------------------------------- 1 file changed, 413 deletions(-) diff --git a/package-lock.json b/package-lock.json index 337c49e..cbb3bd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,11 +56,7 @@ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "requires": { -<<<<<<< HEAD - "mime-types": "2.1.18", -======= "mime-types": "2.1.19", ->>>>>>> flow_test "negotiator": "0.6.1" } }, @@ -1776,15 +1772,9 @@ "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" }, "colors": { -<<<<<<< HEAD - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", - "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==" -======= "version": "1.3.1", "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.1.tgz", "integrity": "sha512-jg/vxRmv430jixZrC+La5kMbUWqIg32/JsYNZb94+JEmzceYbWKTsv1OuTp+7EaqiaWRR2tPcykibwCRgclIsw==" ->>>>>>> flow_test }, "combined-stream": { "version": "1.0.6", @@ -1855,14 +1845,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, -<<<<<<< HEAD -======= "cookiejar": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" }, ->>>>>>> flow_test "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -2211,14 +2198,6 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, "ecc-jsbn": { -<<<<<<< HEAD - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "0.1.1" -======= "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", @@ -2226,7 +2205,6 @@ "requires": { "jsbn": "0.1.1", "safer-buffer": "2.1.2" ->>>>>>> flow_test } }, "editions": { @@ -2389,11 +2367,7 @@ "cross-spawn": "5.1.0", "debug": "3.1.0", "doctrine": "2.1.0", -<<<<<<< HEAD - "eslint-scope": "3.7.1", -======= "eslint-scope": "3.7.3", ->>>>>>> flow_test "eslint-visitor-keys": "1.0.0", "espree": "3.5.4", "esquery": "1.0.1", @@ -2481,15 +2455,9 @@ } }, "eslint-scope": { -<<<<<<< HEAD - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", -======= "version": "3.7.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", ->>>>>>> flow_test "requires": { "esrecurse": "4.2.1", "estraverse": "4.2.0" @@ -2510,15 +2478,9 @@ } }, "esprima": { -<<<<<<< HEAD - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" -======= "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" ->>>>>>> flow_test }, "esquery": { "version": "1.0.1", @@ -2552,25 +2514,12 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "eth-lib": { -<<<<<<< HEAD - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", - "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", - "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0", - "keccakjs": "0.2.1", - "nano-json-stream-parser": "0.1.2", - "servify": "0.1.12", - "ws": "3.3.3", -======= "version": "0.2.7", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", "requires": { "bn.js": "4.11.8", "elliptic": "6.4.0", ->>>>>>> flow_test "xhr-request-promise": "0.1.2" } }, @@ -2578,11 +2527,7 @@ "version": "git+https://github.com/Shirikatsu/eth-proof.git#9b7fdea64ec5810c9c8a74c67ab96dbf0f035567", "requires": { "ethereumjs-block": "1.7.1", -<<<<<<< HEAD - "ethereumjs-tx": "1.3.6", -======= "ethereumjs-tx": "1.3.7", ->>>>>>> flow_test "keccak": "1.4.0", "leveldown": "1.9.0", "levelup": "1.3.9", @@ -2591,14 +2536,6 @@ "web3": "0.19.1" }, "dependencies": { -<<<<<<< HEAD - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" - }, -======= ->>>>>>> flow_test "ethereumjs-block": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", @@ -2606,11 +2543,7 @@ "requires": { "async": "2.6.1", "ethereum-common": "0.2.0", -<<<<<<< HEAD - "ethereumjs-tx": "1.3.6", -======= "ethereumjs-tx": "1.3.7", ->>>>>>> flow_test "ethereumjs-util": "5.2.0", "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" } @@ -2639,15 +2572,9 @@ } }, "ethereum-common": { -<<<<<<< HEAD - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" -======= "version": "0.2.0", "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" ->>>>>>> flow_test }, "ethereumjs-block": { "version": "2.0.0", @@ -2656,11 +2583,7 @@ "requires": { "async": "2.6.1", "ethereumjs-common": "0.3.1", -<<<<<<< HEAD - "ethereumjs-tx": "1.3.6", -======= "ethereumjs-tx": "1.3.7", ->>>>>>> flow_test "ethereumjs-util": "5.2.0", "merkle-patricia-tree": "2.3.1" } @@ -2680,14 +2603,6 @@ } }, "ethereumjs-tx": { -<<<<<<< HEAD - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.6.tgz", - "integrity": "sha512-wzsEs0mCSLqdDjqSDg6AWh1hyL8H3R/pyZxehkcCXq5MJEFXWz+eJ2jSv+3yEaLy6tXrNP7dmqS3Kyb3zAONkg==", - "requires": { - "ethereum-common": "0.0.18", - "ethereumjs-util": "5.2.0" -======= "version": "1.3.7", "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", @@ -2701,7 +2616,6 @@ "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" } ->>>>>>> flow_test } }, "ethereumjs-util": { @@ -2829,11 +2743,7 @@ "on-finished": "2.3.0", "parseurl": "1.3.2", "path-to-regexp": "0.1.7", -<<<<<<< HEAD - "proxy-addr": "2.0.3", -======= "proxy-addr": "2.0.4", ->>>>>>> flow_test "qs": "6.5.1", "range-parser": "1.2.0", "safe-buffer": "5.1.1", @@ -2920,15 +2830,9 @@ } }, "extend": { -<<<<<<< HEAD - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" -======= "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" ->>>>>>> flow_test }, "extend-shallow": { "version": "3.0.2", @@ -3408,11 +3312,7 @@ "requires": { "asynckit": "0.4.0", "combined-stream": "1.0.6", -<<<<<<< HEAD - "mime-types": "2.1.18" -======= "mime-types": "2.1.19" ->>>>>>> flow_test } }, "forwarded": { @@ -4664,15 +4564,9 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { -<<<<<<< HEAD - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" -======= "version": "1.8.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" ->>>>>>> flow_test }, "is-accessor-descriptor": { "version": "0.1.6", @@ -5052,11 +4946,7 @@ "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "requires": { "argparse": "1.0.10", -<<<<<<< HEAD - "esprima": "4.0.0" -======= "esprima": "4.0.1" ->>>>>>> flow_test } }, "jsbn": { @@ -5075,22 +4965,14 @@ "babel-preset-stage-1": "6.24.1", "babel-register": "6.26.0", "babylon": "7.0.0-beta.47", -<<<<<<< HEAD - "colors": "1.3.0", -======= "colors": "1.3.1", ->>>>>>> flow_test "flow-parser": "0.76.0", "lodash": "4.17.10", "micromatch": "2.3.11", "neo-async": "2.5.1", "node-dir": "0.1.8", "nomnom": "1.8.1", -<<<<<<< HEAD - "recast": "0.15.2", -======= "recast": "0.15.3", ->>>>>>> flow_test "temp": "0.8.3", "write-file-atomic": "1.3.4" }, @@ -5370,11 +5252,7 @@ "log-update": "1.0.2", "ora": "0.2.3", "p-map": "1.2.0", -<<<<<<< HEAD - "rxjs": "6.2.1", -======= "rxjs": "6.2.2", ->>>>>>> flow_test "strip-ansi": "3.0.1" }, "dependencies": { @@ -5396,15 +5274,9 @@ } }, "rxjs": { -<<<<<<< HEAD - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.1.tgz", - "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==", -======= "version": "6.2.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", ->>>>>>> flow_test "requires": { "tslib": "1.9.3" } @@ -5898,18 +5770,6 @@ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { -<<<<<<< HEAD - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "requires": { - "mime-db": "1.33.0" -======= "version": "1.35.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" @@ -5920,7 +5780,6 @@ "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", "requires": { "mime-db": "1.35.0" ->>>>>>> flow_test } }, "mimic-fn": { @@ -6747,15 +6606,9 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "prettier": { -<<<<<<< HEAD - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.7.tgz", - "integrity": "sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==" -======= "version": "1.14.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.0.tgz", "integrity": "sha512-KtQ2EGaUwf2EyDfp1fxyEb0PqGKakVm0WyXwDt6u+cAoxbO2Z2CwKvOe3+b4+F2IlO9lYHi1kqFuRM70ddBnow==" ->>>>>>> flow_test }, "pretty-bytes": { "version": "4.0.2", @@ -6783,21 +6636,12 @@ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" }, "proxy-addr": { -<<<<<<< HEAD - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", - "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", - "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.6.0" -======= "version": "2.0.4", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", "requires": { "forwarded": "0.1.2", "ipaddr.js": "1.8.0" ->>>>>>> flow_test } }, "prr": { @@ -7000,21 +6844,12 @@ } }, "recast": { -<<<<<<< HEAD - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.2.tgz", - "integrity": "sha512-L4f/GqxjlEJ5IZ+tdll/l+6dVi2ylysWbkgFJbMuldD6Jklgfv6zJnCpuAZDfjwHhfcd/De0dDKelsTEPQ29qA==", - "requires": { - "ast-types": "0.11.5", - "esprima": "4.0.0", -======= "version": "0.15.3", "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.3.tgz", "integrity": "sha512-xqnagxQH7mL4+UpcCVMObPPdjCEE2dmfGcTwcdpyNgZOd9W0rfdLRF3+smoA+AQqMw6xK6G4021dAQK8XfPYIQ==", "requires": { "ast-types": "0.11.5", "esprima": "4.0.1", ->>>>>>> flow_test "private": "0.1.8", "source-map": "0.6.1" } @@ -7152,11 +6987,7 @@ "aws4": "1.7.0", "caseless": "0.12.0", "combined-stream": "1.0.6", -<<<<<<< HEAD - "extend": "3.0.1", -======= "extend": "3.0.2", ->>>>>>> flow_test "forever-agent": "0.6.1", "form-data": "2.3.2", "har-validator": "5.0.3", @@ -7164,11 +6995,7 @@ "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", -<<<<<<< HEAD - "mime-types": "2.1.18", -======= "mime-types": "2.1.19", ->>>>>>> flow_test "oauth-sign": "0.8.2", "performance-now": "2.1.0", "qs": "6.5.2", @@ -7176,8 +7003,6 @@ "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", "uuid": "3.3.2" -<<<<<<< HEAD -======= }, "dependencies": { "uuid": { @@ -7185,7 +7010,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" } ->>>>>>> flow_test } }, "require-directory": { @@ -7597,11 +7421,7 @@ "map-cache": "0.2.2", "source-map": "0.5.7", "source-map-resolve": "0.5.2", -<<<<<<< HEAD - "use": "3.1.0" -======= "use": "3.1.1" ->>>>>>> flow_test }, "dependencies": { "define-property": { @@ -7741,14 +7561,6 @@ "bignumber.js": { "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" }, -<<<<<<< HEAD - "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" - }, -======= ->>>>>>> flow_test "web3": { "version": "0.18.4", "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", @@ -7862,11 +7674,7 @@ "assert-plus": "1.0.0", "bcrypt-pbkdf": "1.0.2", "dashdash": "1.14.1", -<<<<<<< HEAD - "ecc-jsbn": "0.1.1", -======= "ecc-jsbn": "0.1.2", ->>>>>>> flow_test "getpass": "0.1.7", "jsbn": "0.1.1", "safer-buffer": "2.1.2", @@ -8272,11 +8080,7 @@ "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "requires": { "media-typer": "0.3.0", -<<<<<<< HEAD - "mime-types": "2.1.18" -======= "mime-types": "2.1.19" ->>>>>>> flow_test } }, "typedarray": { @@ -8480,25 +8284,9 @@ "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, "use": { -<<<<<<< HEAD - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "requires": { - "kind-of": "6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } - } -======= "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" ->>>>>>> flow_test }, "user-home": { "version": "1.1.1", @@ -8522,15 +8310,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { -<<<<<<< HEAD - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" -======= "version": "2.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" ->>>>>>> flow_test }, "v8-compile-cache": { "version": "2.0.0", @@ -8606,26 +8388,6 @@ } }, "web3-core": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.34.tgz", - "integrity": "sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4=", - "requires": { - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-core-requestmanager": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - } - }, - "web3-core-helpers": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz", - "integrity": "sha1-sWjaANPhnhVrwVriAyA91N/uLQM=", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.35.tgz", "integrity": "sha512-ayGavbgVk4KL9Y88Uv411fBJ0SVgVfKhKEBweKYzmP0zOqneMzWt6YsyD1n6kRvjAbqA0AfUPEOKyMNjcx2tjw==", @@ -8644,7 +8406,6 @@ "underscore": "1.8.3", "web3-eth-iban": "1.0.0-beta.35", "web3-utils": "1.0.0-beta.35" ->>>>>>> flow_test }, "dependencies": { "underscore": { @@ -8655,17 +8416,6 @@ } }, "web3-core-method": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz", - "integrity": "sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0=", - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-promievent": "1.0.0-beta.34", - "web3-core-subscriptions": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz", "integrity": "sha512-jidImCide8q0GpfsO4L73qoHrbkeWgwU3uOH5DKtJtv0ccmG086knNMRgryb/o9ZgetDWLmDEsJnHjBSoIwcbA==", @@ -8675,7 +8425,6 @@ "web3-core-promievent": "1.0.0-beta.35", "web3-core-subscriptions": "1.0.0-beta.35", "web3-utils": "1.0.0-beta.35" ->>>>>>> flow_test }, "dependencies": { "underscore": { @@ -8686,32 +8435,15 @@ } }, "web3-core-promievent": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz", - "integrity": "sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw=", -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz", "integrity": "sha512-GvqXqKq07OmHuVi5uNRg6k79a1/CI0ViCC+EtNv4CORHtDRmYEt5Bvdv6z6FJEiaaQkD0lKbFwNhLxutx7HItw==", ->>>>>>> flow_test "requires": { "any-promise": "1.3.0", "eventemitter3": "1.1.1" } }, "web3-core-requestmanager": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz", - "integrity": "sha1-Afj2zyrmtvC3DDi64e90G1urIVw=", - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", - "web3-providers-http": "1.0.0-beta.34", - "web3-providers-ipc": "1.0.0-beta.34", - "web3-providers-ws": "1.0.0-beta.34" -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.35.tgz", "integrity": "sha512-S+zW2h17ZZQU9oe3yaCJE0E7aJS4C3Kf4kGPDv+nXjW0gKhQQhgVhw1Doq/aYQGqNSWJp7f1VHkz5gQWwg6RRg==", @@ -8721,7 +8453,6 @@ "web3-providers-http": "1.0.0-beta.35", "web3-providers-ipc": "1.0.0-beta.35", "web3-providers-ws": "1.0.0-beta.35" ->>>>>>> flow_test }, "dependencies": { "underscore": { @@ -8732,15 +8463,6 @@ } }, "web3-core-subscriptions": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz", - "integrity": "sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4=", - "requires": { - "eventemitter3": "1.1.1", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34" -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.35.tgz", "integrity": "sha512-gXzLrWvcGkGiWq1y33Z4Y80XI8XMrwowiQJkrPSjQ81K5PBKquOGwcMffLaKcwdmEy/NpsOXDeFo3eLE1Ghvvw==", @@ -8748,7 +8470,6 @@ "eventemitter3": "1.1.1", "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.35" ->>>>>>> flow_test }, "dependencies": { "underscore": { @@ -8759,26 +8480,15 @@ } }, "web3-eth-abi": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz", - "integrity": "sha1-A0Uz46ovfln/MXk+rqaFwO1a9no=", -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz", "integrity": "sha512-KUDC+EtFFYG8z01ZleKrASdjj327/rtWHzEt6RWsEj7bBa0bGp9nEh+nqdZx/Sdgz1O8tnfFzJlrRcXpfr1vGg==", ->>>>>>> flow_test "dev": true, "requires": { "bn.js": "4.11.6", "underscore": "1.8.3", -<<<<<<< HEAD - "web3-core-helpers": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" -======= "web3-core-helpers": "1.0.0-beta.35", "web3-utils": "1.0.0-beta.35" ->>>>>>> flow_test }, "dependencies": { "bn.js": { @@ -8796,15 +8506,9 @@ } }, "web3-eth-accounts": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz", - "integrity": "sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM=", -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz", "integrity": "sha512-duIgRsfht/0kAW/eQ0X9lKtVIykbETrnM2H7EnvplCzPHtQLodpib4o9JXfh9n6ZDgdDC7cuJoiVB9QJg089ew==", ->>>>>>> flow_test "requires": { "any-promise": "1.3.0", "crypto-browserify": "3.12.0", @@ -8812,62 +8516,26 @@ "scrypt.js": "0.2.0", "underscore": "1.8.3", "uuid": "2.0.1", -<<<<<<< HEAD - "web3-core": "1.0.0-beta.34", - "web3-core-helpers": "1.0.0-beta.34", - "web3-core-method": "1.0.0-beta.34", - "web3-utils": "1.0.0-beta.34" - }, - "dependencies": { - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0", - "xhr-request-promise": "0.1.2" - } - }, -======= "web3-core": "1.0.0-beta.35", "web3-core-helpers": "1.0.0-beta.35", "web3-core-method": "1.0.0-beta.35", "web3-utils": "1.0.0-beta.35" }, "dependencies": { ->>>>>>> flow_test "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" -<<<<<<< HEAD - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" -======= ->>>>>>> flow_test } } }, "web3-eth-iban": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz", - "integrity": "sha1-mvRYYFhnzPdOqXmq8yazi6alugw=", - "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.34" -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz", "integrity": "sha512-H5wkcNcAIc+h/WoDIKv7ZYmrM2Xqu3O7jBQl1IWo73EDVQji+AoB2i3J8tuwI1yZRInRwrfpI3Zuwuf54hXHmQ==", "requires": { "bn.js": "4.11.6", "web3-utils": "1.0.0-beta.35" ->>>>>>> flow_test }, "dependencies": { "bn.js": { @@ -8878,24 +8546,6 @@ } }, "web3-providers-http": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz", - "integrity": "sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno=", - "requires": { - "web3-core-helpers": "1.0.0-beta.34", - "xhr2": "0.1.4" - } - }, - "web3-providers-ipc": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz", - "integrity": "sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao=", - "requires": { - "oboe": "2.1.3", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34" -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.35.tgz", "integrity": "sha512-DcIMFq52Fb08UpWyZ3ZlES6NsNqJnco4hBS/Ej6eOcASfuUayPI+GLkYVZsnF3cBYqlH+DOKuArcKSuIxK7jIA==", @@ -8912,7 +8562,6 @@ "oboe": "2.1.3", "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.35" ->>>>>>> flow_test }, "dependencies": { "underscore": { @@ -8923,21 +8572,12 @@ } }, "web3-providers-ws": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz", - "integrity": "sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM=", - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.34", -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.35.tgz", "integrity": "sha512-Cx64NgDStynKaUGDIIOfaCd0fZusL8h5avKTkdTjUu2aHhFJhZoVBGVLhoDtUaqZGWIZGcBJOoVf2JkGUOjDRQ==", "requires": { "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.35", ->>>>>>> flow_test "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" }, "dependencies": { @@ -8945,7 +8585,6 @@ "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" -<<<<<<< HEAD }, "websocket": { "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", @@ -8955,21 +8594,13 @@ "typedarray-to-buffer": "3.1.5", "yaeti": "0.0.6" } -======= ->>>>>>> flow_test } } }, "web3-utils": { -<<<<<<< HEAD - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", - "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", -======= "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.35.tgz", "integrity": "sha512-Dq6f0SOKj3BDFRgOPnE6ALbzBDCKVIW8mKWVf7tGVhTDHf+wQaWwQSC3aArFSqdExB75BPBPyDpuMTNszhljpA==", ->>>>>>> flow_test "requires": { "bn.js": "4.11.6", "eth-lib": "0.1.27", @@ -8985,8 +8616,6 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" }, -<<<<<<< HEAD -======= "eth-lib": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", @@ -9001,7 +8630,6 @@ "xhr-request-promise": "0.1.2" } }, ->>>>>>> flow_test "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", @@ -9043,11 +8671,7 @@ "babel-preset-stage-1": "6.24.1", "babel-register": "6.26.0", "babylon": "6.18.0", -<<<<<<< HEAD - "colors": "1.3.0", -======= "colors": "1.3.1", ->>>>>>> flow_test "flow-parser": "0.76.0", "lodash": "4.17.10", "micromatch": "2.3.11", @@ -9065,11 +8689,7 @@ "requires": { "ast-types": "0.10.1", "core-js": "2.5.7", -<<<<<<< HEAD - "esprima": "4.0.0", -======= "esprima": "4.0.1", ->>>>>>> flow_test "private": "0.1.8", "source-map": "0.6.1" } @@ -9100,20 +8720,12 @@ "mkdirp": "0.5.1", "p-each-series": "1.0.0", "p-lazy": "1.0.0", -<<<<<<< HEAD - "prettier": "1.13.7", -======= "prettier": "1.14.0", ->>>>>>> flow_test "supports-color": "5.4.0", "v8-compile-cache": "2.0.0", "webpack-addons": "1.1.5", "yargs": "11.1.0", -<<<<<<< HEAD - "yeoman-environment": "2.3.0", -======= "yeoman-environment": "2.3.1", ->>>>>>> flow_test "yeoman-generator": "2.0.5" }, "dependencies": { @@ -9274,18 +8886,6 @@ } } }, -<<<<<<< HEAD -======= - "websocket": { - "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", - "requires": { - "debug": "2.6.9", - "nan": "2.10.0", - "typedarray-to-buffer": "3.1.5", - "yaeti": "0.0.6" - } - }, ->>>>>>> flow_test "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -9409,8 +9009,6 @@ "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" }, -<<<<<<< HEAD -======= "xhr2-cookies": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", @@ -9419,7 +9017,6 @@ "cookiejar": "2.1.2" } }, ->>>>>>> flow_test "xmlhttprequest": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", @@ -9479,15 +9076,9 @@ } }, "yeoman-environment": { -<<<<<<< HEAD - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.3.0.tgz", - "integrity": "sha512-PHSAkVOqYdcR+C+Uht1SGC4eVD/9OhygYFkYaI66xF8vKIeS1RNYay+umj2ZrQeJ50tF5Q/RSO6qGDz9y3Ifug==", -======= "version": "2.3.1", "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.3.1.tgz", "integrity": "sha512-7BFbWNnJqG8f0TFR/awcccHj7Vl9CeG66Yuu81DiVIamqO7Uo/EOrdryjNICdRJNFdaQTliN4HUkM1zQBzszCQ==", ->>>>>>> flow_test "requires": { "chalk": "2.4.1", "cross-spawn": "6.0.5", @@ -9654,11 +9245,7 @@ "shelljs": "0.8.2", "text-table": "0.2.0", "through2": "2.0.3", -<<<<<<< HEAD - "yeoman-environment": "2.3.0" -======= "yeoman-environment": "2.3.1" ->>>>>>> flow_test }, "dependencies": { "ansi-styles": { From 739f4f26a2f9e56674fcd6960a1c6a0ccdbf4736 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 6 Aug 2018 16:23:36 +0100 Subject: [PATCH 115/203] Fixed the register chain test --- ion-cli/cli/cli.go | 231 ++++++++------- ion-cli/config/init.go | 18 +- ion-cli/ionflow/flow_test.go | 21 +- ion-cli/ionflow/utils.go | 15 + ion-cli/ionflow/utils_test.go | 338 ++++++---------------- ion-cli/main.go | 14 +- ion-cli/{ionflow => utils}/client.go | 2 +- ion-cli/{ionflow => utils}/client_test.go | 16 +- ion-cli/utils/proof.go | 25 +- ion-cli/utils/proof_test.go | 3 +- ion-cli/{ionflow => utils}/trie.go | 2 +- 11 files changed, 263 insertions(+), 422 deletions(-) rename ion-cli/{ionflow => utils}/client.go (99%) rename ion-cli/{ionflow => utils}/client_test.go (80%) rename ion-cli/{ionflow => utils}/trie.go (99%) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 4c0cf89..4e00c00 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "math/big" + "net/rpc" "strconv" "strings" @@ -14,7 +15,6 @@ import ( "github.com/abiosoft/ishell" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/ethclient" "github.com/clearmatics/ion/ion-cli/config" contract "github.com/clearmatics/ion/ion-cli/contracts" @@ -22,7 +22,7 @@ import ( ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contract.Validation, Ion *contract.Ion, Trigger *contract.Trigger) { +func Launch(setup config.Setup, clientFrom *rpc.Client, Validation *contract.Validation, Ion *contract.Ion, Trigger *contract.Trigger) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -138,145 +138,144 @@ func Launch(setup config.Setup, clientFrom *ethclient.Client, Validation *contra }, }) - shell.AddCmd(&ishell.Cmd{ - Name: "checkBlockValidation", - Help: "use: checkBlockValidation [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrTo) - c.ShowPrompt(false) - defer c.ShowPrompt(true) // yes, revert after login. - - // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } - - // Get the blockHash - c.Print("Enter BlockHash: ") - blockHash := c.ReadLine() - bytesBlockHash, err := utils.StringToBytes32(blockHash) - if err != nil { - c.Printf("Error: %s", err) - return - } + // shell.AddCmd(&ishell.Cmd{ + // Name: "checkBlockValidation", + // Help: "use: checkBlockValidation [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrTo) + // c.ShowPrompt(false) + // defer c.ShowPrompt(true) // yes, revert after login. + + // // Get the chainId + // bytesChainId, err := utils.StringToBytes32(setup.ChainId) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } - result, err := Validation.MBlockhashes(&bind.CallOpts{}, bytesChainId, bytesBlockHash) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Println("Checking for valid block:") - c.Printf("ChainId:\t%x\nBlockHash:\t%x\nValid:\t\t%v\n", bytesChainId, bytesBlockHash, result) + // // Get the blockHash + // c.Print("Enter BlockHash: ") + // blockHash := c.ReadLine() + // bytesBlockHash, err := utils.StringToBytes32(blockHash) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } - c.Println("===============================================================") - }, - }) + // result, err := Validation.MBlockhashes(&bind.CallOpts{}, bytesChainId, bytesBlockHash) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } + // c.Println("Checking for valid block:") + // c.Printf("ChainId:\t%x\nBlockHash:\t%x\nValid:\t\t%v\n", bytesChainId, bytesBlockHash, result) - shell.AddCmd(&ishell.Cmd{ - Name: "submitBlockValidation", - Help: "use: submitBlockValidation [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.ShowPrompt(false) - defer c.ShowPrompt(true) // yes, revert after login. + // c.Println("===============================================================") + // }, + // }) - // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } + // shell.AddCmd(&ishell.Cmd{ + // Name: "submitBlockValidation", + // Help: "use: submitBlockValidation [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.ShowPrompt(false) + // defer c.ShowPrompt(true) // yes, revert after login. + + // // Get the chainId + // bytesChainId, err := utils.StringToBytes32(setup.ChainId) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } - // Get the block number - c.Print("Enter Block Number: ") - blockNum := c.ReadLine() - c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) + // // Get the block number + // c.Print("Enter Block Number: ") + // blockNum := c.ReadLine() + // c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) - signedBlock, unsignedBlock := calculateRlpEncoding(clientFrom, blockNum) - res, err := Validation.SubmitBlock(authTo, bytesChainId, unsignedBlock, signedBlock) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) - c.Println("===============================================================") - }, - }) + // signedBlock, unsignedBlock := calculateRlpEncoding(clientFrom, blockNum) + // res, err := Validation.SubmitBlock(authTo, bytesChainId, unsignedBlock, signedBlock) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } + // c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) + // c.Println("===============================================================") + // }, + // }) - shell.AddCmd(&ishell.Cmd{ - Name: "latestValidationBlock", - Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrTo) - // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } + // shell.AddCmd(&ishell.Cmd{ + // Name: "latestValidationBlock", + // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrTo) + // // Get the chainId + // bytesChainId, err := utils.StringToBytes32(setup.ChainId) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } - result, err := Validation.MLatestblock(&bind.CallOpts{}, bytesChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Printf("Latest Block Submitted:\nBlockHash:\t0x%x\nChainId:\t%s\n", result, setup.ChainId) - c.Println("===============================================================") - }, - }) + // result, err := Validation.MLatestblock(&bind.CallOpts{}, bytesChainId) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } + // c.Printf("Latest Block Submitted:\nBlockHash:\t0x%x\nChainId:\t%s\n", result, setup.ChainId) + // c.Println("===============================================================") + // }, + // }) //--------------------------------------------------------------------------------------------- // Trigger Specific Commands //--------------------------------------------------------------------------------------------- - shell.AddCmd(&ishell.Cmd{ - Name: "triggerEvent", - Help: "use: triggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrFrom) - lastBlock := latestBlock(clientFrom) + // shell.AddCmd(&ishell.Cmd{ + // Name: "triggerEvent", + // Help: "use: triggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + // Func: func(c *ishell.Context) { + // c.Println("===============================================================") + // c.Println("Connecting to: " + setup.AddrFrom) + // lastBlock := latestBlock(clientFrom) - result, err := Trigger.Fire(authFrom) - if err != nil { - c.Printf("Error: %s", err) - return - } - c.Printf("Triggered Event:\nResult:\t%+v\n", result.Hash) - block := lastBlock.Number - blockNumber, _ := strconv.ParseUint(block.String(), 0, 64) - // s := []uint32{} - ch := make(chan *contract.TriggerTriggered) - opts := &bind.WatchOpts{} - opts.Start = &blockNumber - _, err = Trigger.WatchTriggered(opts, ch) - if err != nil { - log.Fatalf("Failed WatchTriggered: %v", err) - } - var newEvent *contract.TriggerTriggered = <-ch - fmt.Println(newEvent.Caller) + // result, err := Trigger.Fire(authFrom) + // if err != nil { + // c.Printf("Error: %s", err) + // return + // } + // c.Printf("Triggered Event:\nResult:\t%+v\n", result.Hash) + // block := lastBlock.Number + // blockNumber, _ := strconv.ParseUint(block.String(), 0, 64) + // // s := []uint32{} + // ch := make(chan *contract.TriggerTriggered) + // opts := &bind.WatchOpts{} + // opts.Start = &blockNumber + // _, err = Trigger.WatchTriggered(opts, ch) + // if err != nil { + // log.Fatalf("Failed WatchTriggered: %v", err) + // } + // var newEvent *contract.TriggerTriggered = <-ch + // fmt.Println(newEvent.Caller) - c.Println("===============================================================") - }, - }) + // c.Println("===============================================================") + // }, + // }) // shell.AddCmd(&ishell.Cmd{ // Name: "verifyAndExecute", - // Help: "use: verifyAndExecute [Transaction Hash] [Block Number] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + // Help: "use: verifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", // Func: func(c *ishell.Context) { // c.Println("===============================================================") // c.Println("Connecting to: " + setup.AddrTo) // if len(c.Args) == 0 { // c.Println("Select a block") - // } else if len(c.Args) > 2 { + // } else if len(c.Args) > 1 { // c.Println("Too many arguments entered.") // } else { // c.Println("RLP encode block: " + c.Args[0]) - // rootHash, idx, leaf, proof := GenerateTxProof(clientFrom, c.Args[0], c.Args[1]) - // c.Printf("\nRoot Hash:\n% 0x\nTransaction Index:\n% 0x\nTransaction Leaf:\n% 0x\nProof:\n% 0x\n", rootHash, idx, leaf, proof) + // PATH, TX_VALUE, TX_NODES, RECEIPT_VALUE, RECEIPT_NODES := utils.GenerateProof(context.Background(), clientFrom, c.args[0]) // } // c.Println("===============================================================") // }, diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go index 5d0cce4..bb4cc8e 100644 --- a/ion-cli/config/init.go +++ b/ion-cli/config/init.go @@ -10,15 +10,15 @@ import ( "github.com/ethereum/go-ethereum/ethclient" ) -func InitClient(addr string) (clientTo *ethclient.Client) { - // Connect to the RPC Client - clientTo, err := ethclient.Dial(addr) - if err != nil { - log.Fatalf("could not create RPC client: %v", err) - } - - return -} +// func InitClient(addr string) (clientTo *ethclient.Client) { +// // Connect to the RPC Client +// clientTo, err := ethclient.Dial(addr) +// if err != nil { +// log.Fatalf("could not create RPC client: %v", err) +// } + +// return +// } func InitIon(setup Setup, client *ethclient.Client) (Ion *contract.Ion) { // Initialise the contract diff --git a/ion-cli/ionflow/flow_test.go b/ion-cli/ionflow/flow_test.go index 136770f..ae5b2ff 100644 --- a/ion-cli/ionflow/flow_test.go +++ b/ion-cli/ionflow/flow_test.go @@ -6,6 +6,7 @@ import ( "math/big" "testing" + "github.com/clearmatics/ion/ion-cli/utils" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" @@ -20,7 +21,7 @@ import ( // avoid having to get data from Rinkeby, make it deploy a trigger function into a PoA chain // TestVerifyTx test for the full flow of Ion -func TestVerifyTx(t *testing.T) { +func Test_VerifyTx(t *testing.T) { ctx := context.Background() // --------------------------------------------- @@ -51,10 +52,10 @@ func TestVerifyTx(t *testing.T) { // GET BLOCK WITH EVENT FROM RINKEBY CHAIN // --------------------------------------------- - clientRPC := ClientRPC(urlEventChain) + clientRPC := utils.ClientRPC(urlEventChain) defer clientRPC.Close() - blockNumberStr, txTrigger, err := BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) + blockNumberStr, txTrigger, err := utils.BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) if err != nil { t.Fatal("ERROR couldn't find block by tx hash: ", err) } @@ -152,14 +153,14 @@ func TestVerifyTx(t *testing.T) { // CHECK ROOTS PROOF ON ION // --------------------------------------------- blockHash := block.Hash() - txTrie := TxTrie(block.Transactions()) - blockReceipts := GetBlockTxReceipts(client, block) - receiptTrie := ReceiptTrie(blockReceipts) + txTrie := utils.TxTrie(block.Transactions()) + blockReceipts := utils.GetBlockTxReceipts(client, block) + receiptTrie := utils.ReceiptTrie(blockReceipts) txKey := []byte{0x01} - txProofArr := Proof(txTrie, txKey) + txProofArr := utils.Proof(txTrie, txKey) receiptKey := []byte{0x01} - receiptProofArr := Proof(receiptTrie, receiptKey) + receiptProofArr := utils.Proof(receiptTrie, receiptKey) checkRootsProofIon := TransactionContract( ctx, @@ -201,9 +202,9 @@ func TestVerifyTx(t *testing.T) { // --------------------------------------------- txTriggerPath := []byte{0x13} // SHOULD SOMEHOW BE DYNAMIC! txTriggerRLP, _ := rlp.EncodeToBytes(txTrigger) - txTriggerProofArr := Proof(txTrie, txTriggerPath[:]) + txTriggerProofArr := utils.Proof(txTrie, txTriggerPath[:]) receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[0x13]) - receiptTriggerProofArr := Proof(receiptTrie, txTriggerPath[:]) + receiptTriggerProofArr := utils.Proof(receiptTrie, txTriggerPath[:]) triggerCalledBy, _ := types.Sender(signer, txTrigger) txVerifyAndExecuteFunction := TransactionContract( diff --git a/ion-cli/ionflow/utils.go b/ion-cli/ionflow/utils.go index ef6c615..6202a5b 100644 --- a/ion-cli/ionflow/utils.go +++ b/ion-cli/ionflow/utils.go @@ -280,6 +280,21 @@ func CompileAndDeployIon( return resChan } +func CompileContract(contract string) (contracts map[string]*compiler.Contract) { + // --------------------------------------------- + // COMPILE VALIDATION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + contractPath := basePath + contract + + contracts, err := compiler.CompileSolidity("", contractPath) + if err != nil { + log.Fatal("ERROR failed to compile contract:", err) + } + + return +} + // CompileAndDeployValidation method func CompileAndDeployValidation( ctx context.Context, diff --git a/ion-cli/ionflow/utils_test.go b/ion-cli/ionflow/utils_test.go index 02dd897..e8a0247 100644 --- a/ion-cli/ionflow/utils_test.go +++ b/ion-cli/ionflow/utils_test.go @@ -3,15 +3,18 @@ package ionflow import ( "bytes" "context" + "log" "math/big" "testing" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" ) -func TestCompileAndDeployIon(t *testing.T) { +func Test_CompileAndDeployIon(t *testing.T) { // --------------------------------------------- // START BLOCKCHAIN SIMULATOR // --------------------------------------------- @@ -20,11 +23,11 @@ func TestCompileAndDeployIon(t *testing.T) { initialBalance := big.NewInt(1000000000) userAKey, _ := crypto.GenerateKey() - userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) + userAddr := crypto.PubkeyToAddress(userAKey.PublicKey) // start simulated blockchain alloc := make(core.GenesisAlloc) - alloc[userAAddr] = core.GenesisAccount{ + alloc[userAddr] = core.GenesisAccount{ Balance: initialBalance, } blockchain := backends.NewSimulatedBackend(alloc) @@ -47,261 +50,94 @@ func TestCompileAndDeployIon(t *testing.T) { // call contract variable methodName := "chainId" out := new([32]byte) - CallContract(ctx, blockchain, ionContractInstance.Contract, userAAddr, ionContractInstance.Address, methodName, out) + CallContract(ctx, blockchain, ionContractInstance.Contract, userAddr, ionContractInstance.Address, methodName, out) if !bytes.Equal((*out)[:], chainID.Bytes()) { t.Fatal("ERROR chainID result from contract call, and sent to contract constructor differ") } } -// func TestRegisterChain(t *testing.T) { -// // check comments on TestCompileAndDeploy() -// ctx := context.Background() -// initialBalance := big.NewInt(1000000000) -// userAKey, _ := crypto.GenerateKey() -// userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) -// alloc := make(core.GenesisAlloc) -// alloc[userAAddr] = core.GenesisAccount{ -// Balance: initialBalance, -// } -// blockchain := backends.NewSimulatedBackend(alloc) -// var chainID [32]byte -// copy(chainID[:], crypto.Keccak256Hash([]byte("DEPLOYEDCHAINID")).Bytes()) -// contractChan := CompileAndDeployIon(ctx, blockchain, userAKey, chainID) -// blockchain.Commit() -// <-contractChan -// blockchain.Commit() -// ionContractInstance := <-contractChan - -// // deploy validation contract -// contractChan = CompileAndDeployValidation(ctx, blockchain, userAKey, chainID) -// blockchain.Commit() -// validationContractInstance := <-contractChan - -// var chainIDA, addressArray [32]byte -// copy(addressArray[:], validationContractInstance.Address.Bytes()) -// copy(chainIDA[:], crypto.Keccak256Hash([]byte("TESTCHAINID")).Bytes()) -// txRegisterChain := TransactionContract( -// ctx, -// blockchain, -// userAKey, -// ionContractInstance.Contract, -// ionContractInstance.Address, -// nil, -// uint64(3000000), -// "RegisterChain", -// chainIDA, -// addressArray, -// ) -// blockchain.Commit() - -// registerChainReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChain) -// if err != nil { -// log.Fatal("ERROR while waiting for contract deployment") -// } -// if registerChainReceipt.Status == 0 { -// t.Fatalf("ERROR transaction of RegisterChain failed!: %#v\n", registerChainReceipt) -// } - -// methodName := "chains" -// var isChainRegistered bool -// CallContract( -// ctx, -// blockchain, -// ionContractInstance.Contract, -// userAAddr, -// ionContractInstance.Address, -// methodName, -// &isChainRegistered, -// chainIDA, -// ) - -// if !isChainRegistered { -// t.Log("ERROR expecting value of chains(validation.address) to be true, but it was ", isChainRegistered) -// } -// } - -// func TestVerifyTx(t *testing.T) { -// ctx := context.Background() - -// testValidators := [7]common.Hash{ -// common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), -// common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), -// common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), -// common.HexToHash("0xb279182d99e65703f0076e4812653aab85fca0f0"), -// common.HexToHash("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), -// common.HexToHash("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), -// common.HexToHash("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), -// } - -// deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") -// testChainID := common.HexToHash("0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254") - -// urlEventChain := "https://rinkeby.infura.io" -// txHashWithEvent := common.HexToHash("0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") - -// userKey, _ := crypto.GenerateKey() -// userAddr := crypto.PubkeyToAddress(userKey.PublicKey) -// userIntialBalance := big.NewInt(1000000000) - -// // --------------------------------------------- -// // GET BLOCK WITH EVENT FROM RINKEBY CHAIN -// // --------------------------------------------- - -// clientRPC := ClientRPC(urlEventChain) -// defer clientRPC.Close() - -// blockNumberStr, _, err := BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) -// if err != nil { -// t.Fatal("ERROR couldn't find block by tx hash: ", err) -// } - -// var blockNumber big.Int -// blockNumber.SetString((*blockNumberStr)[2:], 16) - -// client := ethclient.NewClient(clientRPC) -// eventTxBlockNumber := blockNumber -// block, err := client.BlockByNumber(ctx, &eventTxBlockNumber) -// if err != nil { -// t.Fatal("ERROR retriving block: ", err) -// } - -// // --------------------------------------------- -// // START BLOCKCHAIN SIMULATOR -// // --------------------------------------------- -// alloc := make(core.GenesisAlloc) -// alloc[userAddr] = core.GenesisAccount{Balance: userIntialBalance} -// blockchain := backends.NewSimulatedBackend(alloc) - -// // --------------------------------------------- -// // COMPILE AND DEPLOY ION -// // --------------------------------------------- -// contractChan := CompileAndDeployIon(ctx, blockchain, userKey, deployedChainID) -// blockchain.Commit() -// <-contractChan // PatriciaTrie libraryContractInstance -// blockchain.Commit() -// ionContractInstance := <-contractChan - -// // --------------------------------------------- -// // COMPILE AND DEPLOY VALIDATION -// // --------------------------------------------- -// contractChan = CompileAndDeployValidation(ctx, blockchain, userKey, deployedChainID) -// blockchain.Commit() -// validationContractInstance := <-contractChan - -// // --------------------------------------------- -// // REGISTER CHAIN ON ION -// // --------------------------------------------- -// var validationContractAddr [20]byte -// copy(validationContractAddr[:], validationContractInstance.Address.Bytes()) -// txRegisterChainIon := TransactionContract( -// ctx, -// blockchain, -// userKey, -// ionContractInstance.Contract, -// ionContractInstance.Address, -// nil, -// uint64(3000000), -// "RegisterChain", -// testChainID, -// validationContractAddr, -// ) -// blockchain.Commit() -// registerChainIonReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainIon) -// if err != nil || registerChainIonReceipt.Status == 0 { -// t.Fatal("ERROR while waiting for contract deployment") -// } - -// // --------------------------------------------- -// // REGISTER CHAIN ON VALIDATION -// // --------------------------------------------- -// var genesisHash [32]byte -// copy(genesisHash[:], block.ParentHash().Bytes()) -// txRegisterChainValidation := TransactionContract( -// ctx, -// blockchain, -// userKey, -// validationContractInstance.Contract, -// validationContractInstance.Address, -// nil, -// uint64(3000000), -// "RegisterChain", -// testChainID, -// testValidators, -// genesisHash, -// ) -// blockchain.Commit() -// registerChainValidationReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainValidation) -// if err != nil || registerChainValidationReceipt.Status == 0 { -// t.Fatal("ERROR while waiting for contract deployment") -// } - -// // --------------------------------------------- -// // SUBMIT BLOCK ON VALIDATION -// // --------------------------------------------- -// blockHeader := block.Header() -// extraData := blockHeader.Extra -// unsignedExtraData := extraData[:len(extraData)-(64+1)] // 64 bytes + 1 vanity byte -// signedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) -// blockHeader.Extra = unsignedExtraData -// unsignedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) -// txSubmitBlockValidation := TransactionContract( -// ctx, -// blockchain, -// userKey, -// validationContractInstance.Contract, -// validationContractInstance.Address, -// nil, -// uint64(3000000), -// "SubmitBlock", -// testChainID, -// unsignedBlockHeaderRLP, -// signedBlockHeaderRLP, -// ) - -// blockchain.Commit() -// submitBlockValidationReceipt, err := bind.WaitMined(ctx, blockchain, txSubmitBlockValidation) -// if err != nil || submitBlockValidationReceipt.Status == 0 { -// t.Fatal("ERROR while waiting for contract deployment") -// } - -// // --------------------------------------------- -// // CHECK ROOTS PROOF ON ION -// // --------------------------------------------- -// blockHash := block.Hash() -// txTrie := TxTrie(block.Transactions()) -// blockReceipts := GetBlockTxReceipts(client, block) -// receiptTrie := ReceiptTrie(blockReceipts) +func Test_RegisterChain(t *testing.T) { + // --------------------------------------------- + // HARD CODED DATA + // --------------------------------------------- + testValidators := [7]common.Hash{ + common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), + common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), + common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), + common.HexToHash("0xb279182d99e65703f0076e4812653aab85fca0f0"), + common.HexToHash("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), + common.HexToHash("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), + common.HexToHash("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), + } -// txKey := []byte{0x01} -// txProofArr := Proof(txTrie, txKey) -// receiptKey := []byte{0x01} -// receiptProofArr := Proof(receiptTrie, receiptKey) + // check comments on TestCompileAndDeploy() + ctx := context.Background() + initialBalance := big.NewInt(1000000000) + userAKey, _ := crypto.GenerateKey() + userAddr := crypto.PubkeyToAddress(userAKey.PublicKey) + alloc := make(core.GenesisAlloc) + alloc[userAddr] = core.GenesisAccount{ + Balance: initialBalance, + } + blockchain := backends.NewSimulatedBackend(alloc) + var chainID [32]byte + copy(chainID[:], crypto.Keccak256Hash([]byte("DEPLOYEDCHAINID")).Bytes()) + contractChan := CompileAndDeployIon(ctx, blockchain, userAKey, chainID) + blockchain.Commit() + <-contractChan + blockchain.Commit() + ionContractInstance := <-contractChan -// checkRootsProofIon := TransactionContract( -// ctx, -// blockchain, -// userKey, -// ionContractInstance.Contract, -// ionContractInstance.Address, -// nil, -// uint64(3000000), -// "CheckRootsProof", -// testChainID, -// blockHash, -// txProofArr, -// receiptProofArr, -// ) + // deploy validation contract + contractChan = CompileAndDeployValidation(ctx, blockchain, userAKey, chainID) + blockchain.Commit() + validationContractInstance := <-contractChan + + var chainIDA [32]byte + var ionAddress, validationAddress [20]byte + copy(ionAddress[:], ionContractInstance.Address.Bytes()) + copy(validationAddress[:], validationContractInstance.Address.Bytes()) + copy(chainIDA[:], crypto.Keccak256Hash([]byte("TESTCHAINID")).Bytes()) + deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") + txRegisterChain := TransactionContract( + ctx, + blockchain, + userAKey, + validationContractInstance.Contract, + validationContractInstance.Address, + nil, + uint64(3000000), + "RegisterChain", + chainIDA, + ionAddress, + testValidators, + deployedChainID, + ) + blockchain.Commit() -// blockchain.Commit() -// chackRootsProofIonReceipt, err := bind.WaitMined(ctx, blockchain, checkRootsProofIon) -// if err != nil || chackRootsProofIonReceipt.Status == 0 { -// t.Fatal("ERROR while waiting for contract deployment", err) -// } + registerChainReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChain) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + if registerChainReceipt.Status == 0 { + t.Fatalf("ERROR transaction of RegisterChain failed!: %#v\n", registerChainReceipt) + } -// // ==================================================================================================== -// // TODO -// // let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); -// // let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, "0x"+nodes.toString('hex'), TEST_PATH); -// // let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); -// } + methodName := "chains" + var isChainRegistered bool + CallContract( + ctx, + blockchain, + validationContractInstance.Contract, + userAddr, + validationContractInstance.Address, + methodName, + &isChainRegistered, + chainID, + ) + + if !isChainRegistered { + t.Log("ERROR expecting value of chains(validation.address) to be true, but it was ", isChainRegistered) + } +} diff --git a/ion-cli/main.go b/ion-cli/main.go index fd4f94e..50f54e8 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -9,6 +9,8 @@ import ( "github.com/clearmatics/ion/ion-cli/cli" "github.com/clearmatics/ion/ion-cli/config" + "github.com/clearmatics/ion/ion-cli/ionflow" + "github.com/clearmatics/ion/ion-cli/utils" ) var configFile = flag.String("config", "setup.json", "Description:\n path to the configuration file") @@ -19,17 +21,17 @@ func main() { if *configFile != "" { setup := config.ReadSetup(*configFile) - clientTo := config.InitClient(setup.AddrTo) - clientFrom := config.InitClient(setup.AddrFrom) + clientTo := utils.Client(setup.AddrTo) + clientFrom := utils.Client(setup.AddrFrom) - Ion := config.InitIon(setup, clientTo) - Validation := config.InitValidation(setup, clientTo) - Trigger := config.InitTrigger(setup, clientFrom) + // Ion := ionflow.CompileContract("Ion.Sol") + Validation := ionflow.CompileContract("Validation.Sol") + // Trigger := ionflow.CompileContract("Trigger.Sol") printInfo(setup) // Launch the CLI - cli.Launch(setup, clientFrom, Validation, Ion, Trigger) + cli.Launch(setup, clientFrom, Validation) } else { fmt.Print("Error: empty config!\n") os.Exit(3) diff --git a/ion-cli/ionflow/client.go b/ion-cli/utils/client.go similarity index 99% rename from ion-cli/ionflow/client.go rename to ion-cli/utils/client.go index b841f07..31112a4 100644 --- a/ion-cli/ionflow/client.go +++ b/ion-cli/utils/client.go @@ -1,4 +1,4 @@ -package ionflow +package utils import ( "context" diff --git a/ion-cli/ionflow/client_test.go b/ion-cli/utils/client_test.go similarity index 80% rename from ion-cli/ionflow/client_test.go rename to ion-cli/utils/client_test.go index 5edcc1b..884d8d6 100644 --- a/ion-cli/ionflow/client_test.go +++ b/ion-cli/utils/client_test.go @@ -1,9 +1,11 @@ -package ionflow +package utils_test import ( "context" "math/big" "testing" + + "github.com/clearmatics/ion/ion-cli/utils" ) const URL = "https://mainnet.infura.io" @@ -11,14 +13,14 @@ const URL = "https://mainnet.infura.io" // NOTE: This tests depend on an external network (not really good) func TestClient(t *testing.T) { - client := Client(URL) + client := utils.Client(URL) client.Close() } func TestGetReceipts(t *testing.T) { expectedTotalReceipts := 92 - client := Client(URL) + client := utils.Client(URL) defer client.Close() blockNumber := big.NewInt(6021002) @@ -27,7 +29,7 @@ func TestGetReceipts(t *testing.T) { t.Error(err) } - receiptArr := GetBlockTxReceipts(client, block) + receiptArr := utils.GetBlockTxReceipts(client, block) if len(receiptArr) != expectedTotalReceipts { t.Errorf("Got %d receipts and expected %d receipts!\n", len(receiptArr), expectedTotalReceipts) @@ -35,7 +37,7 @@ func TestGetReceipts(t *testing.T) { } func TestBlockNumberByTransactionHash(t *testing.T) { - client := Client(URL) + client := utils.Client(URL) defer client.Close() blockNumber := big.NewInt(6021002) @@ -48,10 +50,10 @@ func TestBlockNumberByTransactionHash(t *testing.T) { txHash := tx.Hash() // needs to use the ClientRPC because we make the request directly to the RPC in order to get the blocknumber - clientRPC := ClientRPC(URL) + clientRPC := utils.ClientRPC(URL) defer clientRPC.Close() - bNumber, _, err := BlockNumberByTransactionHash(context.Background(), clientRPC, txHash) + bNumber, _, err := utils.BlockNumberByTransactionHash(context.Background(), clientRPC, txHash) if err != nil { t.Fatal(err) } diff --git a/ion-cli/utils/proof.go b/ion-cli/utils/proof.go index 664aef4..9fb3f3b 100644 --- a/ion-cli/utils/proof.go +++ b/ion-cli/utils/proof.go @@ -5,27 +5,14 @@ import ( "fmt" "math/big" - "github.com/clearmatics/ion/ion-cli/ionflow" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" ) -type rpcTransaction struct { - tx *types.Transaction - txExtraInfo -} - -type txExtraInfo struct { - BlockNumber *string `json:"blockNumber,omitempty"` - BlockHash *common.Hash `json:"blockHash,omitempty"` - From *common.Address `json:"from,omitempty"` -} - func GenerateProof(ctx context.Context, client *rpc.Client, txHash common.Hash) (txTriggerPath []byte, txTriggerRLP []byte, txTriggerProofArr []byte, receiptTrigger []byte, receiptTriggerProofArr []byte) { - blockNumberStr, txTrigger, err := ionflow.BlockNumberByTransactionHash(ctx, client, txHash) + blockNumberStr, txTrigger, err := BlockNumberByTransactionHash(ctx, client, txHash) if err != nil { fmt.Printf("Error: couldn't find block by tx hash: %s\n", err) } @@ -43,9 +30,9 @@ func GenerateProof(ctx context.Context, client *rpc.Client, txHash common.Hash) var idx byte tx := block.Transactions() - txTrie := ionflow.TxTrie(tx) - blockReceipts := ionflow.GetBlockTxReceipts(clientETH, block) - receiptTrie := ionflow.ReceiptTrie(blockReceipts) + txTrie := TxTrie(tx) + blockReceipts := GetBlockTxReceipts(clientETH, block) + receiptTrie := ReceiptTrie(blockReceipts) // Calculate transaction index) for i := 0; i < len(tx); i++ { @@ -56,9 +43,9 @@ func GenerateProof(ctx context.Context, client *rpc.Client, txHash common.Hash) txTriggerPath = append(txTriggerPath, idx) txTriggerRLP, _ = rlp.EncodeToBytes(txTrigger) - txTriggerProofArr = ionflow.Proof(txTrie, txTriggerPath[:]) + txTriggerProofArr = Proof(txTrie, txTriggerPath[:]) receiptTrigger, _ = rlp.EncodeToBytes(blockReceipts[txTriggerPath[0]]) - receiptTriggerProofArr = ionflow.Proof(receiptTrie, txTriggerPath[:]) + receiptTriggerProofArr = Proof(receiptTrie, txTriggerPath[:]) return } diff --git a/ion-cli/utils/proof_test.go b/ion-cli/utils/proof_test.go index 9b95ab0..23ecac0 100644 --- a/ion-cli/utils/proof_test.go +++ b/ion-cli/utils/proof_test.go @@ -7,7 +7,6 @@ import ( "encoding/hex" "testing" - "github.com/clearmatics/ion/ion-cli/ionflow" "github.com/clearmatics/ion/ion-cli/utils" "github.com/stretchr/testify/assert" ) @@ -25,7 +24,7 @@ func Test_GenerateProof(t *testing.T) { TXHASH, _ := utils.StringToBytes32("afc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") // Connect to the RPC Client - client := ionflow.ClientRPC("https://rinkeby.infura.io") + client := utils.ClientRPC("https://rinkeby.infura.io") defer client.Close() PATH, TX_VALUE, TX_NODES, RECEIPT_VALUE, RECEIPT_NODES := utils.GenerateProof(ctx, client, TXHASH) diff --git a/ion-cli/ionflow/trie.go b/ion-cli/utils/trie.go similarity index 99% rename from ion-cli/ionflow/trie.go rename to ion-cli/utils/trie.go index bb72cd3..607fbde 100644 --- a/ion-cli/ionflow/trie.go +++ b/ion-cli/utils/trie.go @@ -1,4 +1,4 @@ -package ionflow +package utils import ( "log" From 0f3065d0655016cac0c1d8af13f73b852a0b9396 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 7 Aug 2018 10:21:30 +0100 Subject: [PATCH 116/203] Created registerChains function --- ion-cli/Makefile | 14 +- ion-cli/cli/cli.go | 43 ++-- ion-cli/cli/rpc_test.go | 16 +- ion-cli/config/config.go | 27 ++ ion-cli/config/config_test.go | 21 +- ion-cli/config/init.go | 54 ---- .../utils.go => contracts/contract.go} | 2 +- .../contract_test.go} | 23 +- ion-cli/{ionflow => contracts}/flow_test.go | 9 +- ion-cli/contracts/ion_test.go | 237 ------------------ ion-cli/contracts/link.go | 30 --- .../raw_example_test.go | 2 +- ion-cli/contracts/validation.go | 30 +++ ion-cli/contracts/validation_test.go | 132 ---------- ion-cli/main.go | 10 +- 15 files changed, 130 insertions(+), 520 deletions(-) delete mode 100644 ion-cli/config/init.go rename ion-cli/{ionflow/utils.go => contracts/contract.go} (99%) rename ion-cli/{ionflow/utils_test.go => contracts/contract_test.go} (91%) rename ion-cli/{ionflow => contracts}/flow_test.go (98%) delete mode 100644 ion-cli/contracts/ion_test.go delete mode 100644 ion-cli/contracts/link.go rename ion-cli/{ionflow => contracts}/raw_example_test.go (99%) create mode 100644 ion-cli/contracts/validation.go delete mode 100644 ion-cli/contracts/validation_test.go diff --git a/ion-cli/Makefile b/ion-cli/Makefile index b5f3a7b..e91f390 100644 --- a/ion-cli/Makefile +++ b/ion-cli/Makefile @@ -5,11 +5,6 @@ SHELL=/bin/bash clean: @rm -f ion-cli - @rm contracts/validation.go - @rm contracts/ion.go - @rm contracts/patricia.go - @rm contracts/trigger.go - @rm contracts/function.go test: @go test ./... -v -short @@ -28,14 +23,7 @@ coverage: go tool cover -html=coverage-all.out build: - # Auto generate the smart contracts - @abigen --bin=../abi/Validation.bin --abi=../abi/Validation.abi --pkg=contract --type=validation --out=contracts/validation.go - @abigen --bin=../abi/Ion.bin --abi=../abi/Ion.abi --pkg=contract --type=ion --out=contracts/ion.go - @abigen --bin=../abi/PatriciaTrie.bin --abi=../abi/PatriciaTrie.abi --pkg=contract --type=patricia --out=contracts/patricia.go - @abigen --bin=../abi/Function.bin --abi=../abi/Function.abi --pkg=contract --type=function --out=contracts/function.go - @abigen --bin=../abi/Trigger.bin --abi=../abi/Trigger.abi --pkg=contract --type=trigger --out=contracts/trigger.go - - # Now build project + # Build project @go get -t -v ./... @go build -o ion-cli . diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 4e00c00..044902a 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -7,51 +7,45 @@ import ( "fmt" "log" "math/big" - "net/rpc" "strconv" "strings" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/compiler" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" "github.com/abiosoft/ishell" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/clearmatics/ion/ion-cli/config" - contract "github.com/clearmatics/ion/ion-cli/contracts" "github.com/clearmatics/ion/ion-cli/utils" ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientFrom *rpc.Client, Validation *contract.Validation, Ion *contract.Ion, Trigger *contract.Trigger) { +func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Validation map[string]*compiler.Contract) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() + _ = ethclient.NewClient(clientTo) + // ethclientTo := ethclient.NewClient(clientTo) + ethclientFrom := ethclient.NewClient(clientFrom) + // Get a suggested gas price - gasPrice, err := clientFrom.SuggestGasPrice(context.Background()) + gasPrice, err := ethclientFrom.SuggestGasPrice(context.Background()) if err != nil { log.Fatal(err) } - // Create an authorized transactor and spend 1 unicorn - keyTo := config.ReadString(setup.KeystoreTo) - authTo, err := bind.NewTransactor(strings.NewReader(keyTo), "password1") - if err != nil { - log.Fatalf("Failed to create authorized transactor: %v", err) - } - authTo.Value = big.NewInt(0) // in wei - authTo.From = common.HexToAddress(setup.AccountTo) + // Create an authorized transactor and corrsponding privateKey + authTo, _ := config.InitUser(setup.KeystoreTo, "password1") + authTo.Value = big.NewInt(0) // in wei authTo.GasLimit = uint64(100000) // in units authTo.GasPrice = gasPrice // Create an authorized transactor and spend 1 unicorn - keyFrom := config.ReadString(setup.KeystoreFrom) - authFrom, err := bind.NewTransactor(strings.NewReader(keyFrom), "password1") - if err != nil { - log.Fatalf("Failed to create authorized transactor: %v", err) - } - authFrom.Value = big.NewInt(0) // in wei - authFrom.From = common.HexToAddress(setup.AccountFrom) // in wei - authFrom.GasLimit = uint64(100000) // in units + authFrom, _ := config.InitUser(setup.KeystoreFrom, "password1") + authFrom.Value = big.NewInt(0) // in wei + authFrom.GasLimit = uint64(100000) // in units authFrom.GasPrice = gasPrice //--------------------------------------------------------------------------------------------- @@ -65,7 +59,7 @@ func Launch(setup config.Setup, clientFrom *rpc.Client, Validation *contract.Val c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrFrom) c.Println("Get latest block number:") - lastBlock := latestBlock(clientFrom) + lastBlock := latestBlock(ethclientFrom) c.Printf("latest block: %v\n", lastBlock.Number) c.Println("===============================================================") @@ -83,7 +77,7 @@ func Launch(setup config.Setup, clientFrom *rpc.Client, Validation *contract.Val } else if len(c.Args) > 1 { c.Println("Only enter single argument") } else { - getBlock(clientFrom, c.Args[0]) + getBlock(ethclientFrom, c.Args[0]) } c.Println("===============================================================") }, @@ -92,7 +86,6 @@ func Launch(setup config.Setup, clientFrom *rpc.Client, Validation *contract.Val //--------------------------------------------------------------------------------------------- // Validation Specific Commands //--------------------------------------------------------------------------------------------- - shell.AddCmd(&ishell.Cmd{ Name: "registerChainValidation", Help: "use: registerChainValidation \n\t\t\t\tdescription: Register new chain with validation contract", @@ -128,7 +121,7 @@ func Launch(setup config.Setup, clientFrom *rpc.Client, Validation *contract.Val } ionAddress := common.HexToAddress(setup.Ion) - tx, err := Validation.RegisterChain(authTo, bytesChainId, ionAddress, validators, bytesGenesis) + tx, err := contract.RegisterChain(authTo, keyTo, bytesChainId, ionAddress, validators, bytesGenesis) if err != nil { c.Printf("Error: %s", err) return diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index 05ae19b..f8f599e 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -14,8 +14,8 @@ import ( ) func Test_EncodeSignedBlock(t *testing.T) { - TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" - EXPECTED_SIGNED_BYTES, _ := hex.DecodeString(TEST_SIGNED) + TestSigned := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + ExpectedSignedBytes, _ := hex.DecodeString(TestSigned) // read a fake block raw, err := ioutil.ReadFile("./block.json") @@ -27,15 +27,15 @@ func Test_EncodeSignedBlock(t *testing.T) { // Marshall fake block into the Header var blockHeader *types.Header json.Unmarshal(raw, &blockHeader) - SIGNED_BLOCK := encodeSignedBlock(blockHeader) + SignedBlock := encodeSignedBlock(blockHeader) - assert.Equal(t, EXPECTED_SIGNED_BYTES, SIGNED_BLOCK) + assert.Equal(t, ExpectedSignedBytes, SignedBlock) } func Test_EncodeUnsignedBlock(t *testing.T) { // TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" - TEST_UNSIGNED := "f9021aa03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1da0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" - EXPECTED_UNSIGNED_BYTES, _ := hex.DecodeString(TEST_UNSIGNED) + TestUnsigned := "f9021aa03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1da0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + ExpectedUnsignedBytes, _ := hex.DecodeString(TestUnsigned) // read a fake block raw, err := ioutil.ReadFile("./block.json") @@ -47,8 +47,8 @@ func Test_EncodeUnsignedBlock(t *testing.T) { // Marshall fake block into the Header var blockHeader *types.Header json.Unmarshal(raw, &blockHeader) - UNSIGNED_BLOCK := encodeUnsignedBlock(blockHeader) + UnsignedBlock := encodeUnsignedBlock(blockHeader) - assert.Equal(t, EXPECTED_UNSIGNED_BYTES, UNSIGNED_BLOCK) + assert.Equal(t, ExpectedUnsignedBytes, UnsignedBlock) } diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index ebcc42c..901d316 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -6,6 +6,11 @@ import ( "encoding/json" "fmt" "io/ioutil" + "log" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" ) // Settings @@ -46,3 +51,25 @@ func ReadString(path string) (contents string) { return } + +func InitUser(privkeystore string, password string) (auth *bind.TransactOpts, userkey *keystore.Key) { + // retrieve private key + keyjson, err := ioutil.ReadFile(privkeystore) + if err != nil { + fmt.Println("Error failed to read keystore: %v", err) + } + + userkey, err = keystore.DecryptKey(keyjson, password) + if err != nil { + fmt.Println("Error json key failed to decrypt: %v", err) + } + + // Create an authorized transactor + key := ReadString(privkeystore) + auth, err = bind.NewTransactor(strings.NewReader(key), password) + if err != nil { + log.Fatalf("Error failed to create authorized transactor: %v", err) + } + + return +} diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index a3c6e2f..bfd4a27 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -3,16 +3,19 @@ package config_test import ( + "fmt" "runtime" "strings" "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" "github.com/clearmatics/ion/ion-cli/config" ) -func Test_Read_ValidSetupJson(t *testing.T) { +func Test_ReadValidSetupJson(t *testing.T) { path := findPath() + "./test.json" setup := config.ReadSetup(path) @@ -21,7 +24,7 @@ func Test_Read_ValidSetupJson(t *testing.T) { assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) } -func Test_Read_ValidKeystore(t *testing.T) { +func Test_ReadValidKeystore(t *testing.T) { path := findPath() + "./UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" contents := config.ReadString(path) @@ -31,6 +34,20 @@ func Test_Read_ValidKeystore(t *testing.T) { } +func Test_InitUser(t *testing.T) { + keystore := "./UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + password := "password1" + expectedFrom := common.HexToAddress("2be5ab0e43b6dc2908d5321cf318f35b80d0c10d") + expectedPrivateKey := "e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b" + + auth, userkey := config.InitUser(keystore, password) + + assert.Equal(t, auth.From, expectedFrom) + privateKey := fmt.Sprintf("%x", crypto.FromECDSA(userkey.PrivateKey)) + assert.Equal(t, privateKey, expectedPrivateKey) + +} + func findPath() string { _, path, _, _ := runtime.Caller(0) pathSlice := strings.Split(path, "/") diff --git a/ion-cli/config/init.go b/ion-cli/config/init.go deleted file mode 100644 index bb4cc8e..0000000 --- a/ion-cli/config/init.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd - -package config - -import ( - "log" - - contract "github.com/clearmatics/ion/ion-cli/contracts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" -) - -// func InitClient(addr string) (clientTo *ethclient.Client) { -// // Connect to the RPC Client -// clientTo, err := ethclient.Dial(addr) -// if err != nil { -// log.Fatalf("could not create RPC client: %v", err) -// } - -// return -// } - -func InitIon(setup Setup, client *ethclient.Client) (Ion *contract.Ion) { - // Initialise the contract - address := common.HexToAddress(setup.Ion) - Ion, err := contract.NewIon(address, client) - if err != nil { - log.Fatal(err) - } - - return -} - -func InitValidation(setup Setup, client *ethclient.Client) (Validation *contract.Validation) { - // Initialise the contract - address := common.HexToAddress(setup.Validation) - Validation, err := contract.NewValidation(address, client) - if err != nil { - log.Fatal(err) - } - - return -} - -func InitTrigger(setup Setup, client *ethclient.Client) (Trigger *contract.Trigger) { - // Initialise the contract - address := common.HexToAddress(setup.Trigger) - Trigger, err := contract.NewTrigger(address, client) - if err != nil { - log.Fatal(err) - } - - return -} diff --git a/ion-cli/ionflow/utils.go b/ion-cli/contracts/contract.go similarity index 99% rename from ion-cli/ionflow/utils.go rename to ion-cli/contracts/contract.go index 6202a5b..4509ee1 100644 --- a/ion-cli/ionflow/utils.go +++ b/ion-cli/contracts/contract.go @@ -1,4 +1,4 @@ -package ionflow +package contract import ( "context" diff --git a/ion-cli/ionflow/utils_test.go b/ion-cli/contracts/contract_test.go similarity index 91% rename from ion-cli/ionflow/utils_test.go rename to ion-cli/contracts/contract_test.go index e8a0247..ab82ca0 100644 --- a/ion-cli/ionflow/utils_test.go +++ b/ion-cli/contracts/contract_test.go @@ -1,4 +1,4 @@ -package ionflow +package contract import ( "bytes" @@ -61,7 +61,7 @@ func Test_RegisterChain(t *testing.T) { // --------------------------------------------- // HARD CODED DATA // --------------------------------------------- - testValidators := [7]common.Hash{ + testValidators := []common.Hash{ common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), @@ -100,20 +100,31 @@ func Test_RegisterChain(t *testing.T) { copy(validationAddress[:], validationContractInstance.Address.Bytes()) copy(chainIDA[:], crypto.Keccak256Hash([]byte("TESTCHAINID")).Bytes()) deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") - txRegisterChain := TransactionContract( + txRegisterChain := RegisterChain( ctx, blockchain, userAKey, validationContractInstance.Contract, validationContractInstance.Address, - nil, - uint64(3000000), - "RegisterChain", chainIDA, ionAddress, testValidators, deployedChainID, ) + // txRegisterChain := TransactionContract( + // ctx, + // blockchain, + // userAKey, + // validationContractInstance.Contract, + // validationContractInstance.Address, + // nil, + // uint64(3000000), + // "RegisterChain", + // chainIDA, + // ionAddress, + // testValidators, + // deployedChainID, + // ) blockchain.Commit() registerChainReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChain) diff --git a/ion-cli/ionflow/flow_test.go b/ion-cli/contracts/flow_test.go similarity index 98% rename from ion-cli/ionflow/flow_test.go rename to ion-cli/contracts/flow_test.go index ae5b2ff..5ffbec8 100644 --- a/ion-cli/ionflow/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -1,4 +1,4 @@ -package ionflow +package contract import ( "bytes" @@ -27,7 +27,7 @@ func Test_VerifyTx(t *testing.T) { // --------------------------------------------- // HARD CODED DATA // --------------------------------------------- - testValidators := [7]common.Hash{ + testValidators := []common.Hash{ common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), @@ -100,15 +100,12 @@ func Test_VerifyTx(t *testing.T) { copy(ionContractAddr[:], ionContractInstance.Address.Bytes()) var genesisHash [32]byte copy(genesisHash[:], block.ParentHash().Bytes()) - txRegisterChainValidation := TransactionContract( + txRegisterChainValidation := RegisterChain( ctx, blockchain, userKey, validationContractInstance.Contract, validationContractInstance.Address, - nil, - uint64(3000000), - "RegisterChain", testChainID, ionContractAddr, testValidators, diff --git a/ion-cli/contracts/ion_test.go b/ion-cli/contracts/ion_test.go deleted file mode 100644 index 55c10b0..0000000 --- a/ion-cli/contracts/ion_test.go +++ /dev/null @@ -1,237 +0,0 @@ -package contract - -import ( - "github.com/ethereum/go-ethereum/common" -) - -var CLIENT = "http://127.0.0.1:8501" -var KEY = `{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3}` -var IONADDR = common.HexToAddress("0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613") - -var DEPLOYEDCHAINID = `ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075` -var TESTCHAINID = `22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254` -var TESTBLOCK = `{"difficulty": "2","extraData": "0xd88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00", "gasLimit": "5635559972940396", "gasUsed": "273138", "hash": "0x6f98a4b7bffb6c5b3dce3923be8a87eeef94ba22e3266cfcfd53407e70294fa4", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "miner":"0x0000000000000000000000000000000000000000","mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number": "5446","parentHash": "0xaa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284","receiptsRoot": "0x1d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size": "2027","stateRoot":"0xb347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967","timestamp": "1531327572","totalDifficulty": "10893","transactions": [ "0x63eff998322fd9ec22bbe141ea74ab929197d2db65834e6f4db65743a214cea3","0xa581c3669e5c927e624949d378a5a9df949d4e7f15e1e974c754929408e4b8a5","0x51f1e414334270b7a338f4d81eb82a5560b406f992bf1b3a2371964425e7c0d8","0xc199cd22b3285ea30d798204c3c2fdb8cebfb4648589aa9687aecd9296705ff6","0x4da9368a70e4cfcee28f4c95d69d1256a7d649505f6971b0435bc90f963833f8","0x3cd690a88f4eff005e85f12492afe84344355e9913ea391e52cc0c39debc19e1","0x5dc2e7ea90a0b2630c8138d1357c78ec3d0f55ed23d2951f3c3754ccb9d47446","0xc7f92719dd9f10e8e49ce31a1d271a268269f5c6103629b65869f595109d0462","0x97ff99ad8a3ae45e933464d09b485b7e1adf2fae15ea88d4215cd676b9ca959e","0x343b25b3c1140eb6bf24dbb7ef8595d62178e9ed686fb5d7e6431840c1194314","0x15eb2874404febc7c5cf63bc8ee8100d3f66bf32b69c66805f2fd24732cee39d","0xdfa64978248b67cd5941fe29fc4297ea311aca517ad0e43d71ca59b760fa9ede","0x63f77993f0db424f3bfc202d6f2d3a4cc33979588ef156deff28987c352d44bc"],"transactionsRoot": "0xcb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35","uncles": []}` -var TESTRLPENCODING = `f9025fa0aa912ad61a8aa3e2d1144e4c76b746720e41682122a8b77eff890099a0ff6284a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0b347dd25d9a8a456448aed25e072c9db54f464be5e3ce1f505cc171cacf3a967a0cb9ecdf5483a1435113250201f690124501cfb0c071b697fcfee88c9a368ef35a01d000ef3f5ca9ebc62cc8aaa07e8fbd103583d1e3cbd28c13e62bc8eac5eb2f1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002821546871405830e4c2a6c83042af2845b463454b861d88301080b846765746888676f312e31302e32856c696e757800000000000000dd2ba07230e2186ee83ef77d88298c068205167718d48ba5b6ba1de552d0c6ce156011a58b49ed91855de154346968a7eeaaf20914022e58e4f6c0e1e02567ec00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000` -var TEST_NODE_VALUE = `0xf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a` -var TEST_PATH = `0x80` -var TEST_PARENT_NODES = `0xf8c3f851a0448f4ee6a987bf17a91096e25247c3d7d78dbd08afddb5cfd4186d6a9f36bbc080808080808080a0c47289442eb85e0ca1f12c5ac6168f15513036935879931655dadfad3586dcb78080808080808080f86e30b86bf86982093f85174876e80083015f909407340652d03d131cd5737aac4a88623682e7e4c40180820bf9a070d26860a32ef4d08d6d91afa73c067af3211dd692a372770927dc9cbddd7869a05aac135e61c984c356509fc27d41b9f0c9c1f23c76d99571491bb0d15936608a` - -// NOTE: These tests are skipped if go test -short is called - -// Ensure that Ion is deployed as expected -// func Test_IonDeployement(t *testing.T) { -// // Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} -// blockchain := backends.NewSimulatedBackend(alloc) - -// patriciaAddress, _, _, err := DeployPatricia( -// auth, -// blockchain, -// ) -// if err != nil { -// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) -// } - -// // Register id of another chain -// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - -// _, _, ion, err := LinkDeployIon( -// auth, -// blockchain, -// deployedChainID, -// patriciaAddress, -// "__./contracts/libraries/PatriciaTrie.s__", -// ) -// if err != nil { -// log.Fatalf("Failed to link and deploy Ion: %v", err) -// } - -// // commit all pending transactions -// blockchain.Commit() - -// chainID, err := ion.ChainId(nil) -// if err != nil { -// log.Fatalf("Failed to retrieve chainID: %v", err) -// } - -// // Transform into string -// CHAINID := fmt.Sprintf("%x", chainID) -// assert.Equal(t, DEPLOYEDCHAINID, CHAINID) -// } - -// // Ensure chains are registered correctly -// func Test_RegisterChain(t *testing.T) { -// // Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} -// blockchain := backends.NewSimulatedBackend(alloc) - -// patriciaAddress, _, _, err := DeployPatricia( -// auth, -// blockchain, -// ) -// if err != nil { -// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) -// } - -// // Register id of another chain -// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - -// _, _, ion, err := LinkDeployIon( -// auth, -// blockchain, -// deployedChainID, -// patriciaAddress, -// "__./contracts/libraries/PatriciaTrie.s__", -// ) -// if err != nil { -// log.Fatalf("Failed to link and deploy Ion: %v", err) -// } - -// // commit all pending transactions -// blockchain.Commit() - -// testChainID, _ := utils.StringToBytes32(TESTCHAINID) - -// // Register an alternate chain -// _, err = ion.RegisterChain(auth, testChainID) -// if err != nil { -// log.Fatalf("Failed to register chain: %v", err) -// } - -// // commit all pending transactions -// blockchain.Commit() - -// // Find deployed chainId -// chain, err := ion.Chains(nil, big.NewInt(0)) -// if err != nil { -// log.Fatalf("Failed to retrieve chainID: %v", err) -// } - -// // Transform into string -// CHAIN := fmt.Sprintf("%x", chain) -// assert.Equal(t, TESTCHAINID, CHAIN) - -// } - -// // Fail if chain is registered more than once -// func Test_FailRegisterChain(t *testing.T) { -// // Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} -// blockchain := backends.NewSimulatedBackend(alloc) - -// patriciaAddress, _, _, err := DeployPatricia( -// auth, -// blockchain, -// ) -// if err != nil { -// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) -// } - -// // Register id of another chain -// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - -// _, _, ion, err := LinkDeployIon( -// auth, -// blockchain, -// deployedChainID, -// patriciaAddress, -// "__./contracts/libraries/PatriciaTrie.s__", -// ) -// if err != nil { -// log.Fatalf("Failed to link and deploy Ion: %v", err) -// } - -// // commit all pending transactions -// blockchain.Commit() - -// testChainID, _ := utils.StringToBytes32(TESTCHAINID) - -// // Register an alternate chain -// _, err = ion.RegisterChain(auth, testChainID) -// if err != nil { -// log.Fatalf("Failed to register chain: %v", err) -// } - -// // commit all pending transactions -// blockchain.Commit() - -// // Register the same chain again -// _, err = ion.RegisterChain(auth, testChainID) -// assert.NotEqual(t, nil, err) -// } - -// // Ensure chains are registered correctly -// func Test_SubmitBlock(t *testing.T) { -// // Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000000000000)} -// auth.GasPrice = big.NewInt(1) -// auth.GasLimit = uint64(1000000) -// blockchain := backends.NewSimulatedBackend(alloc) - -// patriciaAddress, _, _, err := DeployPatricia( -// auth, -// blockchain, -// ) -// if err != nil { -// log.Fatalf("Failed to deploy PatriciaTrie library: %v", err) -// } - -// // Register id of another chain -// deployedChainID, _ := utils.StringToBytes32(DEPLOYEDCHAINID) - -// _, _, ion, err := LinkDeployIon( -// auth, -// blockchain, -// deployedChainID, -// patriciaAddress, -// "__./contracts/libraries/PatriciaTrie.s__", -// ) -// if err != nil { -// log.Fatalf("Failed to link and deploy Ion: %v", err) -// } - -// // commit all pending transactions -// blockchain.Commit() - -// testChainID, _ := utils.StringToBytes32(TESTCHAINID) - -// // Register an alternate chain -// _, err = ion.RegisterChain(auth, testChainID) -// if err != nil { -// log.Fatalf("Failed to register chain: %v", err) -// } - -// // commit all pending transactions -// blockchain.Commit() - -// // Submit block -// var blockHeader utils.Header -// err = json.Unmarshal([]byte(TESTBLOCK), &blockHeader) -// if err != nil { -// log.Fatal("Unmarshal failed", err) -// } -// blockHash, _ := utils.StringToBytes32(blockHeader.Root) -// // blockParentHash, _ := utils.StringToBytes32(blockHeader.ParentHash) -// // blockTxHash, _ := utils.StringToBytes32(blockHeader.TxHash) -// // blockReceiptHash, _ := utils.StringToBytes32(blockHeader.ReceiptHash) - -// rlpEncodingBytes, err := hex.DecodeString(TESTRLPENCODING) - -// _, err = ion.SubmitBlock(auth, testChainID, blockHash, rlpEncodingBytes) -// if err != nil { -// log.Fatalf("Failed to submit block: %v", err) -// } - -// } diff --git a/ion-cli/contracts/link.go b/ion-cli/contracts/link.go deleted file mode 100644 index c474a8e..0000000 --- a/ion-cli/contracts/link.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contract - -import ( - "encoding/hex" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -func LinkDeployIon(auth *bind.TransactOpts, backend bind.ContractBackend, _id [32]byte, linkAddr common.Address, linkString string) (common.Address, *types.Transaction, *Ion, error) { - // Convert address to string and replace library reference in Bin - linkAddrStr := hex.EncodeToString(linkAddr.Bytes()) - NewIonBin := strings.Replace(IonBin, linkString, linkAddrStr, 1) - - parsed, err := abi.JSON(strings.NewReader(IonABI)) - if err != nil { - return common.Address{}, nil, nil, err - } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(NewIonBin), backend, _id) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Ion{IonCaller: IonCaller{contract: contract}, IonTransactor: IonTransactor{contract: contract}, IonFilterer: IonFilterer{contract: contract}}, nil -} diff --git a/ion-cli/ionflow/raw_example_test.go b/ion-cli/contracts/raw_example_test.go similarity index 99% rename from ion-cli/ionflow/raw_example_test.go rename to ion-cli/contracts/raw_example_test.go index 04163d5..c4d5a93 100644 --- a/ion-cli/ionflow/raw_example_test.go +++ b/ion-cli/contracts/raw_example_test.go @@ -1,4 +1,4 @@ -package ionflow +package contract import ( "bytes" diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go new file mode 100644 index 0000000..2e8a335 --- /dev/null +++ b/ion-cli/contracts/validation.go @@ -0,0 +1,30 @@ +package contract + +import ( + "context" + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/compiler" + "github.com/ethereum/go-ethereum/core/types" +) + +func RegisterChain(ctx context.Context, client bind.ContractTransactor, userKey *ecdsa.PrivateKey, contract *compiler.Contract, to common.Address, chainId common.Hash, ionAddr common.Address, validators []common.Hash, registerHash common.Hash) (tx *types.Transaction) { + tx = TransactionContract( + ctx, + client, + userKey, + contract, + to, + nil, + uint64(3000000), + "RegisterChain", + chainId, + ionAddr, + validators, + registerHash, + ) + + return +} diff --git a/ion-cli/contracts/validation_test.go b/ion-cli/contracts/validation_test.go deleted file mode 100644 index 4c485be..0000000 --- a/ion-cli/contracts/validation_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package contract - -import ( - "github.com/ethereum/go-ethereum/common" -) - -// Initialisation array -var val1 = common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") -var val2 = common.HexToAddress("0x8671e5e08d74f338ee1c462340842346d797afd3") -var initValidators = []common.Address{val1, val2} - -var GENESISHASH = "c3bac257bbd04893316a76d41b6ff70de5f65c9f24db128864a6322d8e0e2f28" - -// Test validation contract gets deployed correctly -// func Test_DeployValidation(t *testing.T) { - -// // Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} -// blockchain := backends.NewSimulatedBackend(alloc) - -// genesisHash := [32]byte{} -// copy(genesisHash[:], []byte(GENESISHASH)) - -// // Deploy contract -// address, _, _, err := DeployValidation( -// auth, -// blockchain, -// initValidators, -// genesisHash, -// ) -// // commit all pending transactions -// blockchain.Commit() - -// if err != nil { -// t.Fatalf("Failed to deploy the Validation contract: %v", err) -// } - -// if len(address.Bytes()) == 0 { -// t.Error("Expected a valid deployment address. Received empty address byte array instead") -// } - -// } - -// // Test inbox contract gets deployed correctly -// func TestGetValidators(t *testing.T) { - -// //Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} -// blockchain := backends.NewSimulatedBackend(alloc) - -// genesisHash := [32]byte{} -// copy(genesisHash[:], []byte(GENESISHASH)) - -// // Deploy contract -// _, _, contract, _ := DeployValidation( -// auth, -// blockchain, -// initValidators, -// genesisHash, -// ) -// // commit all pending transactions -// blockchain.Commit() - -// validators, _ := contract.GetValidators(&bind.CallOpts{}) -// assert.Equal(t, validators[0], val1) -// assert.Equal(t, validators[1], val2) - -// } - -// // Test that the latest block returns the last submitted block hash -// func Test_LatestBlock(t *testing.T) { - -// //Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} -// blockchain := backends.NewSimulatedBackend(alloc) - -// genesisHash := [32]byte{} -// copy(genesisHash[:], []byte(GENESISHASH)) - -// // Deploy contract -// _, _, contract, _ := DeployValidation( -// auth, -// blockchain, -// initValidators, -// genesisHash, -// ) -// // commit all pending transactions -// blockchain.Commit() - -// latestBlock, _ := contract.LatestBlock(&bind.CallOpts{}) -// assert.Equal(t, latestBlock, genesisHash) -// } - -// // Test that the Validators is updated upon deployment -// func Test_Validators(t *testing.T) { - -// //Setup simulated block chain -// key, _ := crypto.GenerateKey() -// auth := bind.NewKeyedTransactor(key) -// alloc := make(core.GenesisAlloc) -// alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1000000000)} -// blockchain := backends.NewSimulatedBackend(alloc) - -// genesisHash := [32]byte{} -// copy(genesisHash[:], []byte(GENESISHASH)) - -// // Deploy contract -// _, _, contract, _ := DeployValidation( -// auth, -// blockchain, -// initValidators, -// genesisHash, -// ) -// // commit all pending transactions -// blockchain.Commit() - -// idx := big.NewInt(0) -// validator, err := contract.Validators(&bind.CallOpts{}, idx) -// if err != nil { -// log.Fatalf("Failed to deploy new token contract: %v", err) -// } -// assert.Equal(t, initValidators[0], validator) -// } diff --git a/ion-cli/main.go b/ion-cli/main.go index 50f54e8..efd45e8 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -9,7 +9,7 @@ import ( "github.com/clearmatics/ion/ion-cli/cli" "github.com/clearmatics/ion/ion-cli/config" - "github.com/clearmatics/ion/ion-cli/ionflow" + contract "github.com/clearmatics/ion/ion-cli/contracts" "github.com/clearmatics/ion/ion-cli/utils" ) @@ -21,17 +21,17 @@ func main() { if *configFile != "" { setup := config.ReadSetup(*configFile) - clientTo := utils.Client(setup.AddrTo) - clientFrom := utils.Client(setup.AddrFrom) + clientTo := utils.ClientRPC(setup.AddrTo) + clientFrom := utils.ClientRPC(setup.AddrFrom) // Ion := ionflow.CompileContract("Ion.Sol") - Validation := ionflow.CompileContract("Validation.Sol") + Validation := contract.CompileContract("Validation.sol") // Trigger := ionflow.CompileContract("Trigger.Sol") printInfo(setup) // Launch the CLI - cli.Launch(setup, clientFrom, Validation) + cli.Launch(setup, clientTo, clientFrom, Validation) } else { fmt.Print("Error: empty config!\n") os.Exit(3) From bc2aa89d7a8fa11004e34aa5924fc11957850b58 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 7 Aug 2018 11:35:03 +0100 Subject: [PATCH 117/203] RegisterChains implemented --- .travis.yml | 1 - ion-cli/cli/cli.go | 26 ++++++++++++++++++------- ion-cli/contracts/contract.go | 31 ++++++++++++++++-------------- ion-cli/contracts/contract_test.go | 30 ++++++++--------------------- ion-cli/contracts/flow_test.go | 16 +++++++-------- ion-cli/contracts/validation.go | 4 ++-- ion-cli/main.go | 6 +++--- test/validation.js | 24 ++++++++++++----------- 8 files changed, 70 insertions(+), 68 deletions(-) diff --git a/.travis.yml b/.travis.yml index f37fda1..1c583ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,6 @@ matrix: - go get -t ./... - make build - make test - - make integration-test notifications: slack: diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 044902a..09d614f 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -18,26 +18,29 @@ import ( "github.com/abiosoft/ishell" "github.com/clearmatics/ion/ion-cli/config" + contract "github.com/clearmatics/ion/ion-cli/contracts" "github.com/clearmatics/ion/ion-cli/utils" ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Validation map[string]*compiler.Contract) { +func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Validation *compiler.Contract) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() - _ = ethclient.NewClient(clientTo) - // ethclientTo := ethclient.NewClient(clientTo) + // Create new context + ctx := context.Background() + + ethclientTo := ethclient.NewClient(clientTo) ethclientFrom := ethclient.NewClient(clientFrom) // Get a suggested gas price - gasPrice, err := ethclientFrom.SuggestGasPrice(context.Background()) + gasPrice, err := ethclientFrom.SuggestGasPrice(ctx) if err != nil { log.Fatal(err) } // Create an authorized transactor and corrsponding privateKey - authTo, _ := config.InitUser(setup.KeystoreTo, "password1") + authTo, keyTo := config.InitUser(setup.KeystoreTo, "password1") authTo.Value = big.NewInt(0) // in wei authTo.GasLimit = uint64(100000) // in units authTo.GasPrice = gasPrice @@ -120,8 +123,17 @@ func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Va return } - ionAddress := common.HexToAddress(setup.Ion) - tx, err := contract.RegisterChain(authTo, keyTo, bytesChainId, ionAddress, validators, bytesGenesis) + tx := contract.RegisterChain( + ctx, + ethclientTo, + keyTo.PrivateKey, + Validation, + common.HexToAddress(setup.Validation), + bytesChainId, + common.HexToAddress(setup.Ion), + validators, + bytesGenesis, + ) if err != nil { c.Printf("Error: %s", err) return diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index 4509ee1..b2f13a5 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -58,18 +58,18 @@ func generateContractPayload(contractBinStr string, contractABIStr string, const func newTx( ctx context.Context, - client bind.ContractTransactor, + backend bind.ContractBackend, from, to *common.Address, amount *big.Int, gasLimit uint64, payloadBytecode []byte, ) *types.Transaction { - nonce, err := client.PendingNonceAt(ctx, *from) // uint64(0) + nonce, err := backend.PendingNonceAt(ctx, *from) // uint64(0) if err != nil { log.Fatal("Error getting pending nonce ", err) } - gasPrice, err := client.SuggestGasPrice(ctx) //new(big.Int) + gasPrice, err := backend.SuggestGasPrice(ctx) //new(big.Int) if err != nil { log.Fatal("Error suggesting gas price ", err) } @@ -97,7 +97,7 @@ func signTx(tx *types.Transaction, userKey *ecdsa.PrivateKey) *types.Transaction func compileAndDeployContract( ctx context.Context, - client bind.ContractTransactor, + backend bind.ContractBackend, userKey *ecdsa.PrivateKey, binStr string, abiStr string, @@ -107,10 +107,10 @@ func compileAndDeployContract( ) *types.Transaction { payload := generateContractPayload(binStr, abiStr, constructorArgs...) userAddr := crypto.PubkeyToAddress(userKey.PublicKey) - tx := newTx(ctx, client, &userAddr, nil, amount, gasLimit, payload) + tx := newTx(ctx, backend, &userAddr, nil, amount, gasLimit, payload) signedTx := signTx(tx, userKey) - err := client.SendTransaction(ctx, signedTx) + err := backend.SendTransaction(ctx, signedTx) if err != nil { log.Fatal("ERROR sending contract deployment transaction") } @@ -155,7 +155,7 @@ func CallContract( // TransactionContract execute function in contract func TransactionContract( ctx context.Context, - client bind.ContractTransactor, + backend bind.ContractBackend, userKey *ecdsa.PrivateKey, contract *compiler.Contract, to common.Address, @@ -180,10 +180,10 @@ func TransactionContract( } from := crypto.PubkeyToAddress(userKey.PublicKey) - tx := newTx(ctx, client, &from, &to, amount, gasLimit, payload) + tx := newTx(ctx, backend, &from, &to, amount, gasLimit, payload) signedTx := signTx(tx, userKey) - err = client.SendTransaction(ctx, signedTx) + err = backend.SendTransaction(ctx, signedTx) if err != nil { log.Fatal("ERROR sending contract deployment transaction") } @@ -199,7 +199,7 @@ func TransactionContract( // CompileAndDeployIon specific compile and deploy ion contract func CompileAndDeployIon( ctx context.Context, - client bind.ContractTransactor, + client bind.ContractBackend, userKey *ecdsa.PrivateKey, chainID interface{}, ) <-chan ContractInstance { @@ -280,25 +280,28 @@ func CompileAndDeployIon( return resChan } -func CompileContract(contract string) (contracts map[string]*compiler.Contract) { +func CompileContract(contract string) (compiledContract *compiler.Contract) { // --------------------------------------------- // COMPILE VALIDATION AND DEPENDENCIES // --------------------------------------------- basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - contractPath := basePath + contract + contractPath := basePath + contract + ".sol" contracts, err := compiler.CompileSolidity("", contractPath) if err != nil { log.Fatal("ERROR failed to compile contract:", err) } + // + compiledContract = contracts[basePath+contract+".sol:"+contract] + return } // CompileAndDeployValidation method func CompileAndDeployValidation( ctx context.Context, - client bind.ContractTransactor, + client bind.ContractBackend, userKey *ecdsa.PrivateKey, chainID interface{}, ) <-chan ContractInstance { @@ -352,7 +355,7 @@ func CompileAndDeployValidation( // CompileAndDeployTriggerVerifierAndConsumerFunction method func CompileAndDeployTriggerVerifierAndConsumerFunction( ctx context.Context, - client bind.ContractTransactor, + client bind.ContractBackend, userKey *ecdsa.PrivateKey, ionContractAddress common.Address, ) <-chan ContractInstance { diff --git a/ion-cli/contracts/contract_test.go b/ion-cli/contracts/contract_test.go index ab82ca0..3155322 100644 --- a/ion-cli/contracts/contract_test.go +++ b/ion-cli/contracts/contract_test.go @@ -61,14 +61,14 @@ func Test_RegisterChain(t *testing.T) { // --------------------------------------------- // HARD CODED DATA // --------------------------------------------- - testValidators := []common.Hash{ - common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), - common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), - common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), - common.HexToHash("0xb279182d99e65703f0076e4812653aab85fca0f0"), - common.HexToHash("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), - common.HexToHash("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), - common.HexToHash("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), + testValidators := []common.Address{ + common.HexToAddress("0x42eb768f2244c8811c63729a21a3569731535f06"), + common.HexToAddress("0x6635f83421bf059cd8111f180f0727128685bae4"), + common.HexToAddress("0x7ffc57839b00206d1ad20c69a1981b489f772031"), + common.HexToAddress("0xb279182d99e65703f0076e4812653aab85fca0f0"), + common.HexToAddress("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), + common.HexToAddress("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), + common.HexToAddress("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), } // check comments on TestCompileAndDeploy() @@ -111,20 +111,6 @@ func Test_RegisterChain(t *testing.T) { testValidators, deployedChainID, ) - // txRegisterChain := TransactionContract( - // ctx, - // blockchain, - // userAKey, - // validationContractInstance.Contract, - // validationContractInstance.Address, - // nil, - // uint64(3000000), - // "RegisterChain", - // chainIDA, - // ionAddress, - // testValidators, - // deployedChainID, - // ) blockchain.Commit() registerChainReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChain) diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 5ffbec8..634be1e 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -27,14 +27,14 @@ func Test_VerifyTx(t *testing.T) { // --------------------------------------------- // HARD CODED DATA // --------------------------------------------- - testValidators := []common.Hash{ - common.HexToHash("0x42eb768f2244c8811c63729a21a3569731535f06"), - common.HexToHash("0x6635f83421bf059cd8111f180f0727128685bae4"), - common.HexToHash("0x7ffc57839b00206d1ad20c69a1981b489f772031"), - common.HexToHash("0xb279182d99e65703f0076e4812653aab85fca0f0"), - common.HexToHash("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), - common.HexToHash("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), - common.HexToHash("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), + testValidators := []common.Address{ + common.HexToAddress("0x42eb768f2244c8811c63729a21a3569731535f06"), + common.HexToAddress("0x6635f83421bf059cd8111f180f0727128685bae4"), + common.HexToAddress("0x7ffc57839b00206d1ad20c69a1981b489f772031"), + common.HexToAddress("0xb279182d99e65703f0076e4812653aab85fca0f0"), + common.HexToAddress("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), + common.HexToAddress("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), + common.HexToAddress("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), } deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index 2e8a335..b151fe0 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -10,10 +10,10 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -func RegisterChain(ctx context.Context, client bind.ContractTransactor, userKey *ecdsa.PrivateKey, contract *compiler.Contract, to common.Address, chainId common.Hash, ionAddr common.Address, validators []common.Hash, registerHash common.Hash) (tx *types.Transaction) { +func RegisterChain(ctx context.Context, backend bind.ContractBackend, userKey *ecdsa.PrivateKey, contract *compiler.Contract, to common.Address, chainId common.Hash, ionAddr common.Address, validators []common.Address, registerHash common.Hash) (tx *types.Transaction) { tx = TransactionContract( ctx, - client, + backend, userKey, contract, to, diff --git a/ion-cli/main.go b/ion-cli/main.go index efd45e8..c17cd63 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -24,9 +24,9 @@ func main() { clientTo := utils.ClientRPC(setup.AddrTo) clientFrom := utils.ClientRPC(setup.AddrFrom) - // Ion := ionflow.CompileContract("Ion.Sol") - Validation := contract.CompileContract("Validation.sol") - // Trigger := ionflow.CompileContract("Trigger.Sol") + // Ion := ionflow.CompileContract("Ion.sol") + Validation := contract.CompileContract("Validation") + // Trigger := ionflow.CompileContract("Trigger.sol") printInfo(setup) diff --git a/test/validation.js b/test/validation.js index 0ce9861..424665a 100644 --- a/test/validation.js +++ b/test/validation.js @@ -54,19 +54,20 @@ contract('Validation.js', (accounts) => { const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); - it('Test: Deploy Contract', async () => { + it('Deploy Contract', async () => { const validation = await Validation.new(DEPLOYEDCHAINID); let chainId = await validation.chainId(); assert.equal(chainId, DEPLOYEDCHAINID); }) - it('Test: Register Chain', async () => { + it('Register Chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + let tx = await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); let chain = await validation.chains(TESTCHAINID); assert.equal(chain, true); @@ -78,7 +79,7 @@ contract('Validation.js', (accounts) => { await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; }) - it('Test: Register Chain - Check Validators', async () => { + it('Register Chain - Check Validators', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); @@ -90,7 +91,7 @@ contract('Validation.js', (accounts) => { }) - it('Test: Register Chain - Check Genesis Hash', async () => { + it('Register Chain - Check Genesis Hash', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); @@ -104,7 +105,7 @@ contract('Validation.js', (accounts) => { ; }) - it('Test: Authentic Submission Happy Path - SubmitBlock()', async () => { + it('Authentic Submission Happy Path - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); @@ -166,6 +167,7 @@ contract('Validation.js', (accounts) => { const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; assert.equal(signedHeaderHash, recoveredBlockHash); + console.log("\tGas used to submit block = " + validationReceipt.receipt.gasUsed.toString() + " gas"); let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); assert.equal(blockHash, true); @@ -180,7 +182,7 @@ contract('Validation.js', (accounts) => { }) // Here the block header is signed off chain but by a whitelisted validator - it('Test: Authentic Submission Off-Chain Signature - SubmitBlock()', async () => { + it('Authentic Submission Off-Chain Signature - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); @@ -291,7 +293,7 @@ contract('Validation.js', (accounts) => { }) // Here the block header is signed off chain but by a whitelisted validator who alters the block - it('Test: Inauthentic Block Submission - SubmitBlock()', async () => { + it('Inauthentic Block Submission - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); @@ -413,7 +415,7 @@ contract('Validation.js', (accounts) => { }) // Here the block header is signed off chain but by a a non-whitelisted validator - it('Test: Fail Submit Block unkown validator - SubmitBlock()', async () => { + it('Fail Submit Block unkown validator - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); @@ -510,7 +512,7 @@ contract('Validation.js', (accounts) => { }) - it('Test: Fail Submit Block from unknown chain - SubmitBlock()', async () => { + it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); @@ -573,7 +575,7 @@ contract('Validation.js', (accounts) => { }) - it('Test: Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { + it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID); From f54e418076dee99dd99c9b6d63f1e80ec0a1bfec Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 7 Aug 2018 13:33:32 +0100 Subject: [PATCH 118/203] Submit block added to the CLI --- ion-cli/cli/cli.go | 75 ++++++++++++++++++--------------- ion-cli/config/config.go | 2 + ion-cli/contracts/flow_test.go | 18 ++++++-- ion-cli/contracts/validation.go | 40 +++++++++++++++++- ion-cli/rinkeby.json | 2 + test/PatriciaTrieTest.sol | 2 +- test/merkle.js | 2 +- 7 files changed, 100 insertions(+), 41 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 09d614f..628c2a7 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -40,13 +40,13 @@ func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Va } // Create an authorized transactor and corrsponding privateKey - authTo, keyTo := config.InitUser(setup.KeystoreTo, "password1") + authTo, keyTo := config.InitUser(setup.KeystoreTo, setup.PasswordTo) authTo.Value = big.NewInt(0) // in wei authTo.GasLimit = uint64(100000) // in units authTo.GasPrice = gasPrice // Create an authorized transactor and spend 1 unicorn - authFrom, _ := config.InitUser(setup.KeystoreFrom, "password1") + authFrom, _ := config.InitUser(setup.KeystoreFrom, setup.PasswordFrom) authFrom.Value = big.NewInt(0) // in wei authFrom.GasLimit = uint64(100000) // in units authFrom.GasPrice = gasPrice @@ -143,6 +143,46 @@ func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Va }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "submitBlockValidation", + Help: "use: submitBlockValidation [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.ShowPrompt(false) + defer c.ShowPrompt(true) // yes, revert after login. + + // Get the chainId + bytesChainId, err := utils.StringToBytes32(setup.ChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } + + // Get the block number + c.Print("Enter Block Number: ") + blockNum := c.ReadLine() + c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) + + signedBlock, unsignedBlock := calculateRlpEncoding(ethclientFrom, blockNum) + tx := contract.SubmitBlock( + ctx, + ethclientTo, + keyTo.PrivateKey, + Validation, + common.HexToAddress(setup.Validation), + bytesChainId, + unsignedBlock, + signedBlock, + ) + if err != nil { + c.Printf("Error: %s", err) + return + } + c.Printf("\nTransaction Result:\n%x\n", tx) + c.Println("===============================================================") + }, + }) + // shell.AddCmd(&ishell.Cmd{ // Name: "checkBlockValidation", // Help: "use: checkBlockValidation [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", @@ -180,37 +220,6 @@ func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Va // }, // }) - // shell.AddCmd(&ishell.Cmd{ - // Name: "submitBlockValidation", - // Help: "use: submitBlockValidation [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.ShowPrompt(false) - // defer c.ShowPrompt(true) // yes, revert after login. - - // // Get the chainId - // bytesChainId, err := utils.StringToBytes32(setup.ChainId) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - - // // Get the block number - // c.Print("Enter Block Number: ") - // blockNum := c.ReadLine() - // c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) - - // signedBlock, unsignedBlock := calculateRlpEncoding(clientFrom, blockNum) - // res, err := Validation.SubmitBlock(authTo, bytesChainId, unsignedBlock, signedBlock) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - // c.Printf("\nTransaction Hash:\n0x%x\n", res.Hash()) - // c.Println("===============================================================") - // }, - // }) - // shell.AddCmd(&ishell.Cmd{ // Name: "latestValidationBlock", // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 901d316..cb0481d 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -17,9 +17,11 @@ import ( type Setup struct { AddrTo string `json:"rpc-to"` AccountTo string `json:"account-to"` + PasswordTo string `json:"password-to"` KeystoreTo string `json:"keystore-to"` AddrFrom string `json:"rpc-from"` AccountFrom string `json:"account-from"` + PasswordFrom string `json:"password-from"` KeystoreFrom string `json:"keystore-from"` ChainId string `json:"validation-chainid"` Validation string `json:"validation-addr"` diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 634be1e..90687d4 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -126,19 +126,29 @@ func Test_VerifyTx(t *testing.T) { signedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) blockHeader.Extra = unsignedExtraData unsignedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) - txSubmitBlockValidation := TransactionContract( + txSubmitBlockValidation := SubmitBlock( ctx, blockchain, userKey, validationContractInstance.Contract, validationContractInstance.Address, - nil, - uint64(3000000), - "SubmitBlock", testChainID, unsignedBlockHeaderRLP, signedBlockHeaderRLP, ) + // txSubmitBlockValidation := TransactionContract( + // ctx, + // blockchain, + // userKey, + // validationContractInstance.Contract, + // validationContractInstance.Address, + // nil, + // uint64(3000000), + // "SubmitBlock", + // testChainID, + // unsignedBlockHeaderRLP, + // signedBlockHeaderRLP, + // ) blockchain.Commit() submitBlockValidationReceipt, err := bind.WaitMined(ctx, blockchain, txSubmitBlockValidation) diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index b151fe0..79207ef 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -10,13 +10,23 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -func RegisterChain(ctx context.Context, backend bind.ContractBackend, userKey *ecdsa.PrivateKey, contract *compiler.Contract, to common.Address, chainId common.Hash, ionAddr common.Address, validators []common.Address, registerHash common.Hash) (tx *types.Transaction) { +func RegisterChain( + ctx context.Context, + backend bind.ContractBackend, + userKey *ecdsa.PrivateKey, + contract *compiler.Contract, + toAddr common.Address, + chainId common.Hash, + ionAddr common.Address, + validators []common.Address, + registerHash common.Hash, +) (tx *types.Transaction) { tx = TransactionContract( ctx, backend, userKey, contract, - to, + toAddr, nil, uint64(3000000), "RegisterChain", @@ -28,3 +38,29 @@ func RegisterChain(ctx context.Context, backend bind.ContractBackend, userKey *e return } + +func SubmitBlock( + ctx context.Context, + backend bind.ContractBackend, + userKey *ecdsa.PrivateKey, + contract *compiler.Contract, + toAddr common.Address, + chainId common.Hash, + unsignedBlockHeaderRLP []byte, + signedBlockHeaderRLP []byte, +) (tx *types.Transaction) { + tx = TransactionContract( + ctx, + backend, + userKey, + contract, + toAddr, + nil, + uint64(3000000), + "SubmitBlock", + chainId, + unsignedBlockHeaderRLP, + signedBlockHeaderRLP, + ) + return +} diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index 9101a9c..0747546 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -1,12 +1,14 @@ { "rpc-to":"http://127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "password-to":"password1", "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613", "validation-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", "validation-chainid":"0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075", "rpc-from":"https://rinkeby.infura.io", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + "password-from":"password1", "trigger-addr":"0x61621bcf02914668f8404c1f860e92fc1893f74c", "keystore-from":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" } diff --git a/test/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol index bfa4319..4a98afb 100644 --- a/test/PatriciaTrieTest.sol +++ b/test/PatriciaTrieTest.sol @@ -45,7 +45,7 @@ contract PatriciaTrieTest { Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); } - function failVerifyNestedNodes() returns (bool) { + function testFailVerifyNestedNodes() returns (bool) { bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; bytes memory path = hex"62"; diff --git a/test/merkle.js b/test/merkle.js index adf913c..5b3ba7e 100644 --- a/test/merkle.js +++ b/test/merkle.js @@ -6,7 +6,7 @@ const Web3Utils = require('web3-utils'); const merkle = require('./helpers/merkle.js') contract('Merkle.js', () => { - it('test JS Merkle', () => { + it('Merkle Proof', () => { const testData = ["1","2","3","4","5","6","7"] From f3945981f2183266f9fff66979e6c9317359dcda Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 7 Aug 2018 13:34:19 +0100 Subject: [PATCH 119/203] Cleaned up unused code --- ion-cli/contracts/flow_test.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 90687d4..59455b4 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -136,19 +136,6 @@ func Test_VerifyTx(t *testing.T) { unsignedBlockHeaderRLP, signedBlockHeaderRLP, ) - // txSubmitBlockValidation := TransactionContract( - // ctx, - // blockchain, - // userKey, - // validationContractInstance.Contract, - // validationContractInstance.Address, - // nil, - // uint64(3000000), - // "SubmitBlock", - // testChainID, - // unsignedBlockHeaderRLP, - // signedBlockHeaderRLP, - // ) blockchain.Commit() submitBlockValidationReceipt, err := bind.WaitMined(ctx, blockchain, txSubmitBlockValidation) From 6a33316d2e40a85f340daaec996df2838f37689c Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 8 Aug 2018 10:33:01 +0100 Subject: [PATCH 120/203] CLI has all functionality for complete flow, just requires zombie script --- ion-cli/cli/cli.go | 262 ++++++++++++++++++-------------- ion-cli/cli/rpc_test.go | 1 - ion-cli/config/config.go | 1 + ion-cli/contracts/contract.go | 229 ---------------------------- ion-cli/contracts/flow_test.go | 7 +- ion-cli/contracts/function.go | 132 ++++++++++++++++ ion-cli/contracts/ion.go | 96 ++++++++++++ ion-cli/contracts/trigger.go | 33 ++++ ion-cli/contracts/validation.go | 106 +++++++++++++ ion-cli/main.go | 15 +- ion-cli/rinkeby.json | 1 + 11 files changed, 530 insertions(+), 353 deletions(-) create mode 100644 ion-cli/contracts/function.go create mode 100644 ion-cli/contracts/ion.go create mode 100644 ion-cli/contracts/trigger.go diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 628c2a7..aaec2cc 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -23,7 +23,14 @@ import ( ) // Launch - definition of commands and creates the iterface -func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Validation *compiler.Contract) { +func Launch( + setup config.Setup, + clientTo *rpc.Client, + clientFrom *rpc.Client, + Validation *compiler.Contract, + Trigger *compiler.Contract, + Function *compiler.Contract, +) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -46,7 +53,7 @@ func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Va authTo.GasPrice = gasPrice // Create an authorized transactor and spend 1 unicorn - authFrom, _ := config.InitUser(setup.KeystoreFrom, setup.PasswordFrom) + authFrom, keyFrom := config.InitUser(setup.KeystoreFrom, setup.PasswordFrom) authFrom.Value = big.NewInt(0) // in wei authFrom.GasLimit = uint64(100000) // in units authFrom.GasPrice = gasPrice @@ -134,10 +141,7 @@ func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Va validators, bytesGenesis, ) - if err != nil { - c.Printf("Error: %s", err) - return - } + c.Printf("\nTransaction Result:\n%x\n", tx) c.Println("===============================================================") }, @@ -174,130 +178,158 @@ func Launch(setup config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Va unsignedBlock, signedBlock, ) + + c.Printf("\nTransaction Result:\n%x\n", tx) + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "checkBlockValidation", + Help: "use: checkBlockValidation [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo) + c.ShowPrompt(false) + defer c.ShowPrompt(true) // yes, revert after login. + + // Get the chainId + bytesChainId, err := utils.StringToBytes32(setup.ChainId) if err != nil { c.Printf("Error: %s", err) return } - c.Printf("\nTransaction Result:\n%x\n", tx) + + // Get the blockHash + c.Print("Enter BlockHash: ") + blockHash := c.ReadLine() + bytesBlockHash, err := utils.StringToBytes32(blockHash) + if err != nil { + c.Printf("Error: %s", err) + return + } + + result := contract.ValidBlock( + ctx, + ethclientTo, + Validation, + common.HexToAddress(setup.AddrTo), + common.HexToAddress(setup.Validation), + bytesChainId, + bytesBlockHash, + ) + + c.Println("Checking for valid block:") + c.Printf("ChainId:\t%x\nBlockHash:\t%x\nValid:\t\t%v\n", bytesChainId, bytesBlockHash, result) + c.Println("===============================================================") }, }) - // shell.AddCmd(&ishell.Cmd{ - // Name: "checkBlockValidation", - // Help: "use: checkBlockValidation [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrTo) - // c.ShowPrompt(false) - // defer c.ShowPrompt(true) // yes, revert after login. - - // // Get the chainId - // bytesChainId, err := utils.StringToBytes32(setup.ChainId) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - - // // Get the blockHash - // c.Print("Enter BlockHash: ") - // blockHash := c.ReadLine() - // bytesBlockHash, err := utils.StringToBytes32(blockHash) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - - // result, err := Validation.MBlockhashes(&bind.CallOpts{}, bytesChainId, bytesBlockHash) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - // c.Println("Checking for valid block:") - // c.Printf("ChainId:\t%x\nBlockHash:\t%x\nValid:\t\t%v\n", bytesChainId, bytesBlockHash, result) - - // c.Println("===============================================================") - // }, - // }) - - // shell.AddCmd(&ishell.Cmd{ - // Name: "latestValidationBlock", - // Help: "use: latestValidationBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrTo) - // // Get the chainId - // bytesChainId, err := utils.StringToBytes32(setup.ChainId) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - - // result, err := Validation.MLatestblock(&bind.CallOpts{}, bytesChainId) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - // c.Printf("Latest Block Submitted:\nBlockHash:\t0x%x\nChainId:\t%s\n", result, setup.ChainId) - // c.Println("===============================================================") - // }, - // }) + shell.AddCmd(&ishell.Cmd{ + Name: "latestValidatedBlock", + Help: "use: latestValidatedBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo) + // Get the chainId + bytesChainId, err := utils.StringToBytes32(setup.ChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } + + result := contract.LatestValidBlock( + ctx, + ethclientTo, + Validation, + common.HexToAddress(setup.AddrTo), + common.HexToAddress(setup.Validation), + bytesChainId, + ) + + c.Println("Checking for latest valid block:") + c.Printf("\nBlockHash:\t0x%x\nChainId:\t%s\n", result, setup.ChainId) + c.Println("===============================================================") + }, + }) //--------------------------------------------------------------------------------------------- // Trigger Specific Commands //--------------------------------------------------------------------------------------------- - // shell.AddCmd(&ishell.Cmd{ - // Name: "triggerEvent", - // Help: "use: triggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrFrom) - // lastBlock := latestBlock(clientFrom) - - // result, err := Trigger.Fire(authFrom) - // if err != nil { - // c.Printf("Error: %s", err) - // return - // } - // c.Printf("Triggered Event:\nResult:\t%+v\n", result.Hash) - // block := lastBlock.Number - // blockNumber, _ := strconv.ParseUint(block.String(), 0, 64) - // // s := []uint32{} - // ch := make(chan *contract.TriggerTriggered) - // opts := &bind.WatchOpts{} - // opts.Start = &blockNumber - // _, err = Trigger.WatchTriggered(opts, ch) - // if err != nil { - // log.Fatalf("Failed WatchTriggered: %v", err) - // } - // var newEvent *contract.TriggerTriggered = <-ch - // fmt.Println(newEvent.Caller) - - // c.Println("===============================================================") - // }, - // }) - - // shell.AddCmd(&ishell.Cmd{ - // Name: "verifyAndExecute", - // Help: "use: verifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", - // Func: func(c *ishell.Context) { - // c.Println("===============================================================") - // c.Println("Connecting to: " + setup.AddrTo) - // if len(c.Args) == 0 { - // c.Println("Select a block") - // } else if len(c.Args) > 1 { - // c.Println("Too many arguments entered.") - // } else { - // c.Println("RLP encode block: " + c.Args[0]) - // PATH, TX_VALUE, TX_NODES, RECEIPT_VALUE, RECEIPT_NODES := utils.GenerateProof(context.Background(), clientFrom, c.args[0]) - // } - // c.Println("===============================================================") - // }, - // }) + shell.AddCmd(&ishell.Cmd{ + Name: "triggerEvent", + Help: "use: triggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrFrom) + + result := contract.Fire( + ctx, + ethclientFrom, + keyFrom.PrivateKey, + Trigger, + common.HexToAddress(setup.Trigger), + ) + + c.Printf("Triggered Event:\nResult:\t%+v\n", result) + c.Println("===============================================================") + }, + }) //--------------------------------------------------------------------------------------------- - // Ion Specific Commands + // Function Specific Commands //--------------------------------------------------------------------------------------------- + shell.AddCmd(&ishell.Cmd{ + Name: "verifyAndExecute", + Help: "use: verifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Func: func(c *ishell.Context) { + c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo) + if len(c.Args) == 0 { + c.Println("Enter transaction hash!") + } else if len(c.Args) > 1 { + c.Println("Too many arguments entered.") + } else { + c.Println("RLP encode block: " + c.Args[0]) + // Get the chainId + bytesChainId, err := utils.StringToBytes32(setup.ChainId) + if err != nil { + c.Printf("Error: %s", err) + return + } + + bytesBlockHash := common.HexToHash(c.Args[0]) + + // Generate the proof + txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( + context.Background(), + clientFrom, + bytesBlockHash, + ) + + // Execute + result := contract.VerifyExecute( + ctx, + ethclientTo, + keyTo.PrivateKey, + Function, + common.HexToAddress(setup.Function), + bytesChainId, + bytesBlockHash, + common.HexToAddress(setup.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, + txPath, // TEST_PATH, + txValue, // TEST_TX_VALUE, + txNodes, // TEST_TX_NODES, + receiptValue, // TEST_RECEIPT_VALUE, + receiptNodes, // TEST_RECEIPT_NODES, + common.HexToAddress(setup.AddrFrom), // TRIG_CALLED_BY, + ) + c.Printf("Verify and Executed Event:\nResult:\t%+v\n", result) + } + c.Println("===============================================================") + }, + }) // run shell shell.Run() diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index f8f599e..7b96728 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -33,7 +33,6 @@ func Test_EncodeSignedBlock(t *testing.T) { } func Test_EncodeUnsignedBlock(t *testing.T) { - // TEST_SIGNED := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" TestUnsigned := "f9021aa03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1da0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" ExpectedUnsignedBytes, _ := hex.DecodeString(TestUnsigned) diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index cb0481d..280b0ec 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -27,6 +27,7 @@ type Setup struct { Validation string `json:"validation-addr"` Ion string `json:"ion-addr"` Trigger string `json:"trigger-addr"` + Function string `json:"function-addr"` } // Takes path to a JSON and returns a struct of the contents diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index b2f13a5..73b3d4d 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -7,7 +7,6 @@ import ( "log" "math/big" "os" - "regexp" "strings" ethereum "github.com/ethereum/go-ethereum" @@ -25,11 +24,7 @@ type ContractInstance struct { Address common.Address } -// -------------------------------------------------------------------------------- -// -------------------------------------------------------------------------------- // GENERIC UTIL FUNCTIONS -// -------------------------------------------------------------------------------- -// -------------------------------------------------------------------------------- func getContractBytecodeAndABI(c *compiler.Contract) (string, string) { cABIBytes, err := json.Marshal(c.Info.AbiDefinition) @@ -190,96 +185,6 @@ func TransactionContract( return signedTx } -// -------------------------------------------------------------------------------- -// -------------------------------------------------------------------------------- -// ION SPECIFIC FUNCTIONS -// -------------------------------------------------------------------------------- -// -------------------------------------------------------------------------------- - -// CompileAndDeployIon specific compile and deploy ion contract -func CompileAndDeployIon( - ctx context.Context, - client bind.ContractBackend, - userKey *ecdsa.PrivateKey, - chainID interface{}, -) <-chan ContractInstance { - // --------------------------------------------- - // COMPILE ION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - ionContractPath := basePath + "Ion.sol" - - contracts, err := compiler.CompileSolidity("", ionContractPath) - if err != nil { - log.Fatal("ERROR failed to compile Ion.sol:", err) - } - - patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] - patriciaTrieBinStr, patriciaTrieABIStr := getContractBytecodeAndABI(patriciaTrieContract) - - ionContract := contracts[basePath+"Ion.sol:Ion"] - ionBinStr, ionABIStr := getContractBytecodeAndABI(ionContract) - - // --------------------------------------------- - // DEPLOY PATRICIA LIB ADDRESS - // --------------------------------------------- - patriciaTrieSignedTx := compileAndDeployContract( - ctx, - client, - userKey, - patriciaTrieBinStr, - patriciaTrieABIStr, - nil, - uint64(3000000), - ) - - resChan := make(chan ContractInstance) - - // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed - // Ion depends on PatriciaTrie library - go func() { - defer close(resChan) - deployBackend := client.(bind.DeployBackend) - - // wait for PatriciaTrie library to be deployed - patriciaTrieAddr, err := bind.WaitDeployed(ctx, deployBackend, patriciaTrieSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // DEPLOY ION CONTRACT WITH PATRICIA LIB ADDRESS - // --------------------------------------------- - // replace palceholder with Prticia Trie Lib address - var re = regexp.MustCompile(`__.*__`) - ionBinStrWithLibAddr := re.ReplaceAllString(ionBinStr, patriciaTrieAddr.Hex()[2:]) - ionSignedTx := compileAndDeployContract( - ctx, - client, - userKey, - ionBinStrWithLibAddr, - ionABIStr, - nil, - uint64(3000000), - chainID, - ) - - // only stop blocking the first result after the Ion contract as been deploy - // this guarantees that it works well with the blockchain simulator Commit() - resChan <- ContractInstance{patriciaTrieContract, patriciaTrieAddr} - - // wait for Ion to be deployed - ionAddr, err := bind.WaitDeployed(ctx, deployBackend, ionSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - resChan <- ContractInstance{ionContract, ionAddr} - }() - - return resChan -} - func CompileContract(contract string) (compiledContract *compiler.Contract) { // --------------------------------------------- // COMPILE VALIDATION AND DEPENDENCIES @@ -297,137 +202,3 @@ func CompileContract(contract string) (compiledContract *compiler.Contract) { return } - -// CompileAndDeployValidation method -func CompileAndDeployValidation( - ctx context.Context, - client bind.ContractBackend, - userKey *ecdsa.PrivateKey, - chainID interface{}, -) <-chan ContractInstance { - // --------------------------------------------- - // COMPILE VALIDATION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - validationContractPath := basePath + "Validation.sol" - - contracts, err := compiler.CompileSolidity("", validationContractPath) - if err != nil { - log.Fatal("ERROR failed to compile Ion.sol:", err) - } - - validationContract := contracts[basePath+"Validation.sol:Validation"] - validationBinStr, validationABIStr := getContractBytecodeAndABI(validationContract) - - // --------------------------------------------- - // DEPLOY VALIDATION CONTRACT - // --------------------------------------------- - validationSignedTx := compileAndDeployContract( - ctx, - client, - userKey, - validationBinStr, - validationABIStr, - nil, - uint64(3000000), - chainID, - ) - - resChan := make(chan ContractInstance) - - // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed - // Ion depends on PatriciaTrie library - go func() { - defer close(resChan) - deployBackend := client.(bind.DeployBackend) - - // wait for PatriciaTrie library to be deployed - validationAddr, err := bind.WaitDeployed(ctx, deployBackend, validationSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - resChan <- ContractInstance{validationContract, validationAddr} - }() - - return resChan -} - -// CompileAndDeployTriggerVerifierAndConsumerFunction method -func CompileAndDeployTriggerVerifierAndConsumerFunction( - ctx context.Context, - client bind.ContractBackend, - userKey *ecdsa.PrivateKey, - ionContractAddress common.Address, -) <-chan ContractInstance { - // --------------------------------------------- - // COMPILE VALIDATION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - triggerEventVerifierContractPath := basePath + "TriggerEventVerifier.sol" - consumerFunctionContractPath := basePath + "Function.sol" - - contracts, err := compiler.CompileSolidity("", consumerFunctionContractPath, triggerEventVerifierContractPath) - if err != nil { - log.Fatal("ERROR failed to compile Ion.sol:", err) - } - - triggerEventVerifierContract := contracts[triggerEventVerifierContractPath+":TriggerEventVerifier"] - triggerEventVerifierBinStr, triggerEventVerifierABIStr := getContractBytecodeAndABI(triggerEventVerifierContract) - consumerFunctionContract := contracts[consumerFunctionContractPath+":Function"] - consumerFunctionBinStr, consumerFunctionABIStr := getContractBytecodeAndABI(consumerFunctionContract) - - // --------------------------------------------- - // DEPLOY TRIGGER EVENT CONTRACT - // --------------------------------------------- - triggerEventSignedTx := compileAndDeployContract( - ctx, - client, - userKey, - triggerEventVerifierBinStr, - triggerEventVerifierABIStr, - nil, - uint64(3000000), - ) - - resChan := make(chan ContractInstance) - - // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed - // Ion depends on PatriciaTrie library - go func() { - defer close(resChan) - deployBackend := client.(bind.DeployBackend) - - // wait for trigger event contract to be deployed - triggerEventAddr, err := bind.WaitDeployed(ctx, deployBackend, triggerEventSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // DEPLOY CONSUMER FUNCTION CONTRACT - // --------------------------------------------- - consumerFunctionSignedTx := compileAndDeployContract( - ctx, - client, - userKey, - consumerFunctionBinStr, - consumerFunctionABIStr, - nil, - uint64(3000000), - ionContractAddress, - triggerEventAddr, - ) - - resChan <- ContractInstance{triggerEventVerifierContract, triggerEventAddr} - - // wait for consumer function contract to be deployed - consumerFunctionAddr, err := bind.WaitDeployed(ctx, deployBackend, consumerFunctionSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - resChan <- ContractInstance{consumerFunctionContract, consumerFunctionAddr} - }() - - return resChan -} diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 59455b4..f74c5b3 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -201,18 +201,15 @@ func Test_VerifyTx(t *testing.T) { receiptTriggerProofArr := utils.Proof(receiptTrie, txTriggerPath[:]) triggerCalledBy, _ := types.Sender(signer, txTrigger) - txVerifyAndExecuteFunction := TransactionContract( + txVerifyAndExecuteFunction := VerifyExecute( ctx, blockchain, userKey, consumerFunctionContractInstance.Contract, consumerFunctionContractInstance.Address, - nil, - uint64(3000000), - "verifyAndExecute", testChainID, blockHash, - txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, + *txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, txTriggerPath, // TEST_PATH, txTriggerRLP, // TEST_TX_VALUE, txTriggerProofArr, // TEST_TX_NODES, diff --git a/ion-cli/contracts/function.go b/ion-cli/contracts/function.go new file mode 100644 index 0000000..ffab442 --- /dev/null +++ b/ion-cli/contracts/function.go @@ -0,0 +1,132 @@ +package contract + +import ( + "context" + "crypto/ecdsa" + "log" + "os" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/compiler" + "github.com/ethereum/go-ethereum/core/types" +) + +// CompileAndDeployTriggerVerifierAndConsumerFunction method +func CompileAndDeployTriggerVerifierAndConsumerFunction( + ctx context.Context, + client bind.ContractBackend, + userKey *ecdsa.PrivateKey, + ionContractAddress common.Address, +) <-chan ContractInstance { + // --------------------------------------------- + // COMPILE VALIDATION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + triggerEventVerifierContractPath := basePath + "TriggerEventVerifier.sol" + consumerFunctionContractPath := basePath + "Function.sol" + + contracts, err := compiler.CompileSolidity("", consumerFunctionContractPath, triggerEventVerifierContractPath) + if err != nil { + log.Fatal("ERROR failed to compile Ion.sol:", err) + } + + triggerEventVerifierContract := contracts[triggerEventVerifierContractPath+":TriggerEventVerifier"] + triggerEventVerifierBinStr, triggerEventVerifierABIStr := getContractBytecodeAndABI(triggerEventVerifierContract) + consumerFunctionContract := contracts[consumerFunctionContractPath+":Function"] + consumerFunctionBinStr, consumerFunctionABIStr := getContractBytecodeAndABI(consumerFunctionContract) + + // --------------------------------------------- + // DEPLOY TRIGGER EVENT CONTRACT + // --------------------------------------------- + triggerEventSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + triggerEventVerifierBinStr, + triggerEventVerifierABIStr, + nil, + uint64(3000000), + ) + + resChan := make(chan ContractInstance) + + // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed + // Ion depends on PatriciaTrie library + go func() { + defer close(resChan) + deployBackend := client.(bind.DeployBackend) + + // wait for trigger event contract to be deployed + triggerEventAddr, err := bind.WaitDeployed(ctx, deployBackend, triggerEventSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // DEPLOY CONSUMER FUNCTION CONTRACT + // --------------------------------------------- + consumerFunctionSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + consumerFunctionBinStr, + consumerFunctionABIStr, + nil, + uint64(3000000), + ionContractAddress, + triggerEventAddr, + ) + + resChan <- ContractInstance{triggerEventVerifierContract, triggerEventAddr} + + // wait for consumer function contract to be deployed + consumerFunctionAddr, err := bind.WaitDeployed(ctx, deployBackend, consumerFunctionSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + resChan <- ContractInstance{consumerFunctionContract, consumerFunctionAddr} + }() + + return resChan +} + +func VerifyExecute( + ctx context.Context, + backend bind.ContractBackend, + userKey *ecdsa.PrivateKey, + contract *compiler.Contract, + toAddr common.Address, + chainId common.Hash, + blockHash common.Hash, + txTriggerTo common.Address, + txTriggerPath []byte, + txTriggerRLP []byte, + txTriggerProofArr []byte, + receiptTrigger []byte, + receiptTriggerProofArr []byte, + triggerCalledBy common.Address, + +) (tx *types.Transaction) { + tx = TransactionContract( + ctx, + backend, + userKey, + contract, + toAddr, + nil, + uint64(3000000), + "verifyAndExecute", + chainId, + blockHash, + txTriggerTo, // TRIG_DEPLOYED_RINKEBY_ADDR, + txTriggerPath, // TEST_PATH, + txTriggerRLP, // TEST_TX_VALUE, + txTriggerProofArr, // TEST_TX_NODES, + receiptTrigger, // TEST_RECEIPT_VALUE, + receiptTriggerProofArr, // TEST_RECEIPT_NODES, + triggerCalledBy, // TRIG_CALLED_BY, + ) + return +} diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go new file mode 100644 index 0000000..c93f9c3 --- /dev/null +++ b/ion-cli/contracts/ion.go @@ -0,0 +1,96 @@ +package contract + +import ( + "context" + "crypto/ecdsa" + "log" + "os" + "regexp" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common/compiler" +) + +// CompileAndDeployIon specific compile and deploy ion contract +func CompileAndDeployIon( + ctx context.Context, + client bind.ContractBackend, + userKey *ecdsa.PrivateKey, + chainID interface{}, +) <-chan ContractInstance { + // --------------------------------------------- + // COMPILE ION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + ionContractPath := basePath + "Ion.sol" + + contracts, err := compiler.CompileSolidity("", ionContractPath) + if err != nil { + log.Fatal("ERROR failed to compile Ion.sol:", err) + } + + patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] + patriciaTrieBinStr, patriciaTrieABIStr := getContractBytecodeAndABI(patriciaTrieContract) + + ionContract := contracts[basePath+"Ion.sol:Ion"] + ionBinStr, ionABIStr := getContractBytecodeAndABI(ionContract) + + // --------------------------------------------- + // DEPLOY PATRICIA LIB ADDRESS + // --------------------------------------------- + patriciaTrieSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + patriciaTrieBinStr, + patriciaTrieABIStr, + nil, + uint64(3000000), + ) + + resChan := make(chan ContractInstance) + + // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed + // Ion depends on PatriciaTrie library + go func() { + defer close(resChan) + deployBackend := client.(bind.DeployBackend) + + // wait for PatriciaTrie library to be deployed + patriciaTrieAddr, err := bind.WaitDeployed(ctx, deployBackend, patriciaTrieSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + // --------------------------------------------- + // DEPLOY ION CONTRACT WITH PATRICIA LIB ADDRESS + // --------------------------------------------- + // replace palceholder with Prticia Trie Lib address + var re = regexp.MustCompile(`__.*__`) + ionBinStrWithLibAddr := re.ReplaceAllString(ionBinStr, patriciaTrieAddr.Hex()[2:]) + ionSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + ionBinStrWithLibAddr, + ionABIStr, + nil, + uint64(3000000), + chainID, + ) + + // only stop blocking the first result after the Ion contract as been deploy + // this guarantees that it works well with the blockchain simulator Commit() + resChan <- ContractInstance{patriciaTrieContract, patriciaTrieAddr} + + // wait for Ion to be deployed + ionAddr, err := bind.WaitDeployed(ctx, deployBackend, ionSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + + resChan <- ContractInstance{ionContract, ionAddr} + }() + + return resChan +} diff --git a/ion-cli/contracts/trigger.go b/ion-cli/contracts/trigger.go new file mode 100644 index 0000000..b047b48 --- /dev/null +++ b/ion-cli/contracts/trigger.go @@ -0,0 +1,33 @@ +package contract + +import ( + "context" + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/compiler" + "github.com/ethereum/go-ethereum/core/types" +) + +// Registers chain with Validation contract specified +func Fire( + ctx context.Context, + backend bind.ContractBackend, + userKey *ecdsa.PrivateKey, + contract *compiler.Contract, + toAddr common.Address, +) (tx *types.Transaction) { + tx = TransactionContract( + ctx, + backend, + userKey, + contract, + toAddr, + nil, + uint64(3000000), + "fire", + ) + + return +} diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index 79207ef..0ee51f9 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -3,6 +3,8 @@ package contract import ( "context" "crypto/ecdsa" + "log" + "os" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -10,6 +12,61 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// CompileAndDeployValidation method +func CompileAndDeployValidation( + ctx context.Context, + client bind.ContractBackend, + userKey *ecdsa.PrivateKey, + chainID interface{}, +) <-chan ContractInstance { + // --------------------------------------------- + // COMPILE VALIDATION AND DEPENDENCIES + // --------------------------------------------- + basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" + validationContractPath := basePath + "Validation.sol" + + contracts, err := compiler.CompileSolidity("", validationContractPath) + if err != nil { + log.Fatal("ERROR failed to compile Ion.sol:", err) + } + + validationContract := contracts[basePath+"Validation.sol:Validation"] + validationBinStr, validationABIStr := getContractBytecodeAndABI(validationContract) + + // --------------------------------------------- + // DEPLOY VALIDATION CONTRACT + // --------------------------------------------- + validationSignedTx := compileAndDeployContract( + ctx, + client, + userKey, + validationBinStr, + validationABIStr, + nil, + uint64(3000000), + chainID, + ) + + resChan := make(chan ContractInstance) + + // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed + // Ion depends on PatriciaTrie library + go func() { + defer close(resChan) + deployBackend := client.(bind.DeployBackend) + + // wait for PatriciaTrie library to be deployed + validationAddr, err := bind.WaitDeployed(ctx, deployBackend, validationSignedTx) + if err != nil { + log.Fatal("ERROR while waiting for contract deployment") + } + resChan <- ContractInstance{validationContract, validationAddr} + }() + + return resChan +} + +// Registers chain with Validation contract specified func RegisterChain( ctx context.Context, backend bind.ContractBackend, @@ -39,6 +96,7 @@ func RegisterChain( return } +// Submits block to Validation contract specified func SubmitBlock( ctx context.Context, backend bind.ContractBackend, @@ -64,3 +122,51 @@ func SubmitBlock( ) return } + +// Queries validation contract to see is block is valid +func ValidBlock( + ctx context.Context, + backend bind.ContractBackend, + contract *compiler.Contract, + userAddr common.Address, + toAddr common.Address, + chainId common.Hash, + blockHash common.Hash, +) (isBlockValid bool) { + methodName := "m_blockhashes" + CallContract( + ctx, + backend, + contract, + userAddr, + toAddr, + methodName, + &isBlockValid, + chainId, + blockHash, + ) + return +} + +// Queries validation contract to see is block is valid +func LatestValidBlock( + ctx context.Context, + backend bind.ContractBackend, + contract *compiler.Contract, + userAddr common.Address, + toAddr common.Address, + chainId common.Hash, +) (isBlockValid bool) { + methodName := "m_latestblock" + CallContract( + ctx, + backend, + contract, + userAddr, + toAddr, + methodName, + &isBlockValid, + chainId, + ) + return +} diff --git a/ion-cli/main.go b/ion-cli/main.go index c17cd63..9325020 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -24,14 +24,23 @@ func main() { clientTo := utils.ClientRPC(setup.AddrTo) clientFrom := utils.ClientRPC(setup.AddrFrom) - // Ion := ionflow.CompileContract("Ion.sol") + // Compile contracts to use in sending transactions Validation := contract.CompileContract("Validation") - // Trigger := ionflow.CompileContract("Trigger.sol") + Function := contract.CompileContract("Function") + Trigger := contract.CompileContract("Trigger") printInfo(setup) // Launch the CLI - cli.Launch(setup, clientTo, clientFrom, Validation) + cli.Launch( + setup, + clientTo, + clientFrom, + Validation, + Trigger, + Function, + ) + } else { fmt.Print("Error: empty config!\n") os.Exit(3) diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index 0747546..c10275f 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -4,6 +4,7 @@ "password-to":"password1", "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "ion-addr":"0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613", + "function-addr":"0x49e71afdcaf62d7384f0b801c9e3c6e18d4a2597", "validation-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", "validation-chainid":"0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075", "rpc-from":"https://rinkeby.infura.io", From 06ace7cba69f5c7cc74e9facdff7cf9689852828 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 8 Aug 2018 10:59:21 +0100 Subject: [PATCH 121/203] trying to add solidity compiler to environment --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1c583ca..06ab07c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,9 @@ services: - docker before_install: + - sudo add-apt-repository ppa:ethereum/ethereum + - sudo apt-get update + - sudo apt-get install solc - docker build . -t node - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh From 0a7705adcd9844b62e98b67057cb0e944266dbf5 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Wed, 8 Aug 2018 11:06:01 +0100 Subject: [PATCH 122/203] need to add -y to sudo commands for travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 06ab07c..6bbdf7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,9 @@ services: - docker before_install: - - sudo add-apt-repository ppa:ethereum/ethereum + - sudo add-apt-repository ppa:ethereum/ethereum -y - sudo apt-get update - - sudo apt-get install solc + - sudo apt-get install solc -y - docker build . -t node - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh From f9615f938eae854d819186a8d5ed4c816ae635b1 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Wed, 8 Aug 2018 12:18:56 +0100 Subject: [PATCH 123/203] fixed diferent package name --- ion-cli/contracts/flow_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 46e6bfb..887cdbe 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -148,9 +148,9 @@ func Test_VerifyTx(t *testing.T) { // --------------------------------------------- blockHash := block.Hash() blockTransactions := block.Transactions() - txTrie := TxTrie(blockTransactions) - blockReceipts := GetBlockTxReceipts(client, block) - receiptTrie := ReceiptTrie(blockReceipts) + txTrie := utils.TxTrie(blockTransactions) + blockReceipts := utils.GetBlockTxReceipts(client, block) + receiptTrie := utils.ReceiptTrie(blockReceipts) txKey := []byte{0x01} txProofArr := utils.Proof(txTrie, txKey) @@ -204,9 +204,9 @@ func Test_VerifyTx(t *testing.T) { } txTriggerPath := []byte{txTriggerIdx} txTriggerRLP, _ := rlp.EncodeToBytes(txTrigger) - txTriggerProofArr := Proof(txTrie, txTriggerPath[:]) + txTriggerProofArr := utils.Proof(txTrie, txTriggerPath[:]) receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[txTriggerIdx]) - receiptTriggerProofArr := Proof(receiptTrie, txTriggerPath[:]) + receiptTriggerProofArr := utils.Proof(receiptTrie, txTriggerPath[:]) triggerCalledBy, _ := types.Sender(signer, txTrigger) txVerifyAndExecuteFunction := VerifyExecute( From 5e6921b2f5e189b61d4c47e34e75da76639fca27 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 9 Aug 2018 13:03:17 +0100 Subject: [PATCH 124/203] Walkthrough is complete need to review on github and improve docs --- IonCliScript.txt | 11 +- README.md | 191 ++++++++++++++++++++++++++----- contracts/Recover.sol | 129 --------------------- ion-cli/cli/cli.go | 174 ++++++++++++++-------------- ion-cli/contracts/contract.go | 6 +- ion-cli/contracts/flow_test.go | 27 +++-- ion-cli/contracts/function.go | 6 +- ion-cli/contracts/validation.go | 6 +- ion-cli/main.go | 22 ++-- ion-cli/rinkeby.json | 8 +- migrations/2_deploy_contracts.js | 5 +- test/PatriciaTrieTest.sol | 2 +- 12 files changed, 294 insertions(+), 293 deletions(-) delete mode 100644 contracts/Recover.sol diff --git a/IonCliScript.txt b/IonCliScript.txt index b0f2ca7..776b934 100644 --- a/IonCliScript.txt +++ b/IonCliScript.txt @@ -1,6 +1,7 @@ registerValidationChain: - chainId - 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 - validators - "["0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"]" - genesis - 0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177 - -0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91 \ No newline at end of file + chainId: + 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 + validators: + 0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91 + genesis: + 0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177 diff --git a/README.md b/README.md index 03803e4..b679250 100644 --- a/README.md +++ b/README.md @@ -100,46 +100,185 @@ Following this we can attach to the Ion Command Line Interface, ``` $ cd /path/to/ion/ion-cli $ make build +$ make test ``` -Assuming a successful build we must create a setup file which contains the connection of the separate blockchains, user accounts, account keystores, and the address of the deployed validation contract. Change the default values in the example setup.json then run the `ion-cli` poiinting to the modified setup file. +Assuming a successful build and passing of the tests a setup file which contains the connection of the separate blockchains, user accounts, account keystores, and the address of the deployed validation contract should be created. Change the default values in the example setup.json then run the `ion-cli` poiinting to the modified setup file. ``` -$ ./ion-cli -config [/path/to/setup.json] +$ ./ion-cli --config [/path/to/setup.json] =============================================================== Ion Command Line Interface RPC Client [to]: -Listening on: 127.0.0.1:8501 -User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d -Ion Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f + Listening on: http://127.0.0.1:8501 + User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d + RPC ChainId: 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 + Validation Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f + Ion Contract: 0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613 + Function Contract: 0x49e71afdcaf62d7384f0b801c9e3c6e18d4a2597 -RPC Client [from]: -Listening on: 127.0.0.1:8545 -User Account: 0x8671e5e08d74f338ee1c462340842346d797afd3 +RPC Client [from]: + Listening on: https://127.0.0.1:8545 + User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d + Trigger Contract: 0x61621bcf02914668f8404c1f860e92fc1893f74c =============================================================== >>> ``` running help displays the available commands. ``` >>> help - Commands: - clear clear the screen - exit exit the program - generateTxProof use: generateTxProof [Transaction Hash] [Block Number] - description: Returns the proof of a specific transaction held within a Patricia trie - getBlock use: getBlock [integer] - description: Returns block header specified - getValidationBlock use: latestValidationBlock - description: Returns hash of the last block submitted to the validation contract - getValidators use: getValidators - description: Returns the whitelist of validators from validator contract - help display help - latestBlock use: latestBlock - description: Returns number of latest block mined/sealed - latestValidationBlock use: latestValidationBlock - description: Returns hash of the last block submitted to the validation contract - submitValidationBlock use: submitValidationBlock [integer] - description: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract + checkBlockValidation use: checkBlockValidation + Enter Blockhash: [HASH] + description: Returns true for validated blocks + clear clear the screen + exit exit the program + getBlock use: getBlock [TO/FROM] [integer] + description: Returns block header specified from chain [TO/FROM] + help display help + latestBlock use: latestBlock [TO/FROM] + description: Returns number of latest block mined/sealed from chain [TO/FROM] + latestValidatedBlock use: latestValidatedBlock + description: Returns hash of the last block submitted to the validation contract + registerChainValidation use: registerChainValidation + Enter Validators: [ADDRESS ADDRESS] + Enter Genesis Hash: [HASH] + description: Register new chain with validation contract + submitBlockValidation use: submitBlockValidation + Enter Block Number: [INTEGER] + description: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract + triggerEvent use: triggerEvent + description: Returns hash of the last block submitted to the validation contract + verifyAndExecute use: verifyAndExecute [Transaction Hash] + description: Returns the proof of a specific transaction held within a Patricia trie +``` + +#### Ion CLI Walkthrough +A simple walkthrough of the Ion framework between a local testrpc and the Rinkeby test network is detailed. Users can trigger an event on Rinkeby with the account `0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d` and verify the transaction on the local testrpc where they deploy the event consuming contracts. + +A brief overview of the steps required are: +* Launch Ion CLI +* Register rinkeby with the validation contract +* Trigger event on rinkeby test network - this tutorial will use the transaction `0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098` - [check etherscan](https://rinkeby.etherscan.io/tx/0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098) +* Submit relevant rinkeby blocks to the validation contract +* Verify event happened on testrpc and execute function + +##### Step 1. Launch Ion CLI +Having followed the instructions to run and build the Ion CLI and testrpc, see [here](#### Runninig Ion CLI), launch the CLI with the setup file `rinkeby.json`. +``` +$ ./ion-cli --config rinkeby.json +=============================================================== +Ion Command Line Interface + +RPC Client [to]: + Listening on: http://127.0.0.1:8545 + User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d + RPC ChainId: 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 + Validation Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f + Ion Contract: 0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613 + Function Contract: 0x49e71afdcaf62d7384f0b801c9e3c6e18d4a2597 + +RPC Client [from]: + Listening on: https://rinkeby.infura.io + User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d + Trigger Contract: 0x61621bcf02914668f8404c1f860e92fc1893f74c +=============================================================== +>>> +``` + +##### Step 2. Register Chain +In order to validate blocks first the chain must be registered in the validation contract on the testrpc: +``` +>>> registerChainValidation +Connecting to: http://127.0.0.1:8545 +Enter Validators: 0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91 +Enter Genesis Hash: 0x100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c + +Returns: +Transaction: 0xcd5f4405260a6935b048e9136d211df99e594359abe04dcf975c730e5cf0d708 +=============================================================== +``` + +To see if it has successfully been registered we can check the the contract if this is a valid block: +``` +>>> checkBlockValidation +Connecting to: http://127.0.0.1:8545 +Enter BlockHash: 0x100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c +Checking for valid block: +ChainId: ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 +BlockHash: 100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c + +Returns: +Valid: true +=============================================================== +``` + +##### Step 3. Submit Block to Validation +As our event happened in block 2776659 this block must be submitted to the validation contract prior to verification of our transaction. +``` +>>> submitBlockValidation +Connecting to: http://127.0.0.1:8545 +Enter Block Number: 2776659 +RLP encode block: +Number: 2776659 +Signed Block Header Prefix: +f9025ca0100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ad9b6d8c20a0631e2513968cdf3667dffabf9d2f6c1bf22a5990861192e1d266a053413d0e5fd5854665fab663ad8ffb0f5d06bf1907a5a0a3e45300de1ce23fcda0997750d465d96422e7692e281d16db709e6ff9c11c1d8229410340cf1598a8b6b9010000000000c0000010000000000000000000000000000000008000000000000000000000040000000000002004000000000000000002000000000000000004000000010000000008000000002800000002000000000004000000000001000001400000000002000000040000000000080080000000000000000000001000008000000000002000000000000000000000000000000000000000000002000000000000000000010000000010004000000000000020000000000000000000000000000200010300000000000005000040000000000004000000000000000042006000000000200000008000000000000000800000020400000000001080020080000001832a5e53836b33668349d003845b6ab5b9b861d68301080d846765746886676f312e3130856c696e75780000000000000000000cd4835e13d2204ad1fbc94d18a1a0373e92ffc63a021f8212a72dd1cff2e2057bded7534ed90df2492e60c7050db528715e3bc7734bef0a4c97542886cbc57c01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000 + +Unsigned Block Header Prefix: +f9021aa0100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ad9b6d8c20a0631e2513968cdf3667dffabf9d2f6c1bf22a5990861192e1d266a053413d0e5fd5854665fab663ad8ffb0f5d06bf1907a5a0a3e45300de1ce23fcda0997750d465d96422e7692e281d16db709e6ff9c11c1d8229410340cf1598a8b6b9010000000000c0000010000000000000000000000000000000008000000000000000000000040000000000002004000000000000000002000000000000000004000000010000000008000000002800000002000000000004000000000001000001400000000002000000040000000000080080000000000000000000001000008000000000002000000000000000000000000000000000000000000002000000000000000000010000000010004000000000000020000000000000000000000000000200010300000000000005000040000000000004000000000000000042006000000000200000008000000000000000800000020400000000001080020080000001832a5e53836b33668349d003845b6ab5b9a0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000 + +Returns: +Transaction Hash: 0x965da7ac02d7ef58417e32b427b33ff2717d3cd6bb213fd05853a2c8d0fd092e +=============================================================== ``` +Again check that the block has successfully been validated: +``` +>>> checkBlockValidation +Connecting to: http://127.0.0.1:8545 +Enter BlockHash: 0x74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046 +Checking for valid block: +ChainId: ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 +BlockHash: 74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046 + +Returns: +Valid: true +=============================================================== +``` + +##### Step 4. Verify and Execute Event Consuming Contract +Now the block that contains our event has been successfully submitted to the validation contract we can execute the contract which consumes the event: +``` +>>> verifyAndExecute +Connecting to: http://127.0.0.1:8545 +Enter Transaction Hash: 0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098 +Enter Block Hash: 0x74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046 +Returns: +Transaction Hash: 0xc0bdb1b8dadd7bd0a68a9f773286236444a7c90fef9a2a7dacd9640f393df736 +=============================================================== +``` + +##### Step 5. Check Transaction Successfully Executed +Attach to the geth client of the RPC TO chain and run: +``` +> eth.getTransaction("0xc0bdb1b8dadd7bd0a68a9f773286236444a7c90fef9a2a7dacd9640f393df736") +{ + blockHash: "0x4cd5b0a89b96b3e8c5e9176ecc4bf23586958118d82360ba55e24d9170ad2032", + blockNumber: 438, + contractAddress: null, + cumulativeGasUsed: 104964, + from: "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", + gasUsed: 104964, + logs: [], + logsBloom: "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000", + status: "0x0", + to: "0x93981af8db02c7ef40d0ed61caef2726a79eb903", + transactionHash: "0xc0bdb1b8dadd7bd0a68a9f773286236444a7c90fef9a2a7dacd9640f393df736", + transactionIndex: 0 +} +``` +`status: "0x0"` shows the transaction executed successfully! \ No newline at end of file diff --git a/contracts/Recover.sol b/contracts/Recover.sol deleted file mode 100644 index df9ea37..0000000 --- a/contracts/Recover.sol +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.23; - -import "./libraries/ECVerify.sol"; - -contract Recover { - address Owner; - - event broadcastSig(address owner); - event broadcastHashData(bytes header, bytes parentHash, bytes rootHash); - /* event test(bytes start, bytes data); */ - event broadcastHash(bytes32 blockHash); - event test(bytes header); - - constructor () public { - Owner = msg.sender; - } - - /* - * @param data data that has been signed - * @param sig signature of data - */ - function VerifyHash(bytes32 data, bytes sig) public { - address sig_addr = ECVerify.ecrecovery(data, sig); - - emit broadcastSig(sig_addr); - } - - /* - * @param header header rlp encoded, with extraData signatures removed - * @param sig extraData signatures - */ - function VerifyBlock(bytes header, bytes sig) public { - bytes32 hashData = keccak256(header); - address sig_addr = ECVerify.ecrecovery(hashData, sig); - - bytes memory parentHash = new bytes(32); - bytes memory rootHash = new bytes(32); - - // get parentHash and rootHash - extractData(parentHash, header, 4, 32); - extractData(rootHash, header, 91, 32); - - emit broadcastHashData(header, parentHash, rootHash); - emit broadcastSig(sig_addr); - } - - /* - * @param header header rlp encoded, with extraData signatures removed - * @param prefixHeader the new prefix for the signed hash header - * @param prefixExtraData the new prefix for the extraData field - */ - function ExtractHash(bytes header, bytes prefixHeader, bytes prefixExtraData) public { - uint256 length = header.length; - bytes32 blockHash = keccak256(header); - - emit broadcastHash(blockHash); - - bytes memory headerStart = new bytes(length - 141); - bytes memory extraData = new bytes(31); - bytes memory extraDataSig = new bytes(65); - bytes memory headerEnd = new bytes(42); - - // Extract the start of the header and replace the length - extractData(headerStart, header, 0, headerStart.length); - assembly { - let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2) - } - - // Extract the real extra data and create the signed hash - extractData(extraData, header, length-140, extraData.length); - assembly { - let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1) - } - - // Extract the end of the header - extractData(headerEnd, header, length-42, headerEnd.length); - bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd); - - bytes32 hashData = keccak256(newHeader); - - // Extract the signature of the hash create above - extractData(extraDataSig, header, length-107, extraDataSig.length); - - address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig); - - emit broadcastSig(sig_addr); - - } - - function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) { - // Get the lengths sorted because they're needed later... - uint256 headerStartLength = headerStart.length; - uint256 extraDataLength = extraData.length; - uint256 extraDataStart = headerStartLength + 32; - uint256 headerEndLength = headerEnd.length; - uint256 headerEndStart = extraDataLength + headerStartLength + 32 + 2; - uint256 newLength = headerStartLength + extraDataLength + headerEndLength + 2; // extra two is for the prefix - bytes memory header = new bytes(newLength); - - - // Add in the first part of the header - assembly { - let ret := staticcall(3000, 4, add(headerStart, 32), headerStartLength, add(header, 32), headerStartLength) - } - assembly { - let ret := staticcall(3000, 4, add(extraData, 32), extraDataLength, add(header, extraDataStart), extraDataLength) - } - assembly { - let ret := staticcall(3000, 4, add(headerEnd, 32), headerEndLength, add(header, headerEndStart), headerEndLength) - } - - output = header; - } - - /* - * @param data memory allocation for the data you need to extract - * @param sig array from which the data should be extracted - * @param start index which the data starts within the byte array - * @param length total length of the data to be extracted - */ - function extractData(bytes data, bytes input, uint start, uint length) private pure { - for (uint i=0; i 1 { - c.Println("Only enter single argument") - } else { - getBlock(ethclientFrom, c.Args[0]) + if len(c.Args) != 2 { + c.Println("Error: Incorrect Arguments!") + } else if c.Args[0] == "TO" { + c.Println("Connecting to: " + setup.AddrTo) + getBlock(ethclientTo, c.Args[1]) + } else if c.Args[0] == "FROM" { + c.Println("Connecting to: " + setup.AddrFrom) + getBlock(ethclientFrom, c.Args[1]) } c.Println("===============================================================") }, @@ -98,19 +105,14 @@ func Launch( //--------------------------------------------------------------------------------------------- shell.AddCmd(&ishell.Cmd{ Name: "registerChainValidation", - Help: "use: registerChainValidation \n\t\t\t\tdescription: Register new chain with validation contract", + Help: "use: \tregisterChainValidation\n \t\t\t\t\tEnter Validators: [ADDRESS ADDRESS]\n \t\t\t\t\tEnter Genesis Hash: [HASH] \n\t\t\t\tdescription: Register new chain with validation contract", Func: func(c *ishell.Context) { - c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) c.ShowPrompt(false) - defer c.ShowPrompt(true) // yes, revert after login. + defer c.ShowPrompt(true) // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } + bytesChainId := common.HexToHash(setup.ChainId) // Get the validators array c.Print("Enter Validators: ") @@ -124,11 +126,7 @@ func Launch( // Get genesis hash c.Print("Enter Genesis Hash: ") genesis := c.ReadLine() - bytesGenesis, err := utils.StringToBytes32(genesis) - if err != nil { - c.Printf("Error: %s", err) - return - } + bytesGenesis := common.HexToHash(genesis) tx := contract.RegisterChain( ctx, @@ -142,16 +140,16 @@ func Launch( bytesGenesis, ) - c.Printf("\nTransaction Result:\n%x\n", tx) + c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ Name: "submitBlockValidation", - Help: "use: submitBlockValidation [integer] \n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", + Help: "use: \tsubmitBlockValidation\n \t\t\t\t\tEnter Block Number: [INTEGER]\n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { - c.Println("===============================================================") + c.Println("Connecting to: " + setup.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. @@ -179,16 +177,15 @@ func Launch( signedBlock, ) - c.Printf("\nTransaction Result:\n%x\n", tx) + c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ Name: "checkBlockValidation", - Help: "use: checkBlockValidation [blockHash]\n\t\t\t\tdescription: Returns true for validated blocks", + Help: "use: \tcheckBlockValidation\n \t\t\t\t\tEnter Blockhash: [HASH]\n\t\t\t\tdescription: Returns true for validated blocks", Func: func(c *ishell.Context) { - c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. @@ -221,23 +218,17 @@ func Launch( c.Println("Checking for valid block:") c.Printf("ChainId:\t%x\nBlockHash:\t%x\nValid:\t\t%v\n", bytesChainId, bytesBlockHash, result) - c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ Name: "latestValidatedBlock", - Help: "use: latestValidatedBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Help: "use: \tlatestValidatedBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { - c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrTo) // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } + bytesChainId := common.HexToHash(setup.ChainId) result := contract.LatestValidBlock( ctx, @@ -259,12 +250,11 @@ func Launch( //--------------------------------------------------------------------------------------------- shell.AddCmd(&ishell.Cmd{ Name: "triggerEvent", - Help: "use: triggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", + Help: "use: \ttriggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { - c.Println("===============================================================") c.Println("Connecting to: " + setup.AddrFrom) - result := contract.Fire( + tx := contract.Fire( ctx, ethclientFrom, keyFrom.PrivateKey, @@ -272,7 +262,7 @@ func Launch( common.HexToAddress(setup.Trigger), ) - c.Printf("Triggered Event:\nResult:\t%+v\n", result) + c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) c.Println("===============================================================") }, }) @@ -282,51 +272,53 @@ func Launch( //--------------------------------------------------------------------------------------------- shell.AddCmd(&ishell.Cmd{ Name: "verifyAndExecute", - Help: "use: verifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Help: "use: \tverifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", Func: func(c *ishell.Context) { - c.Println("===============================================================") - c.Println("Connecting to: " + setup.AddrTo) - if len(c.Args) == 0 { - c.Println("Enter transaction hash!") - } else if len(c.Args) > 1 { - c.Println("Too many arguments entered.") - } else { - c.Println("RLP encode block: " + c.Args[0]) - // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } - - bytesBlockHash := common.HexToHash(c.Args[0]) - - // Generate the proof - txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( - context.Background(), - clientFrom, - bytesBlockHash, - ) - - // Execute - result := contract.VerifyExecute( - ctx, - ethclientTo, - keyTo.PrivateKey, - Function, - common.HexToAddress(setup.Function), - bytesChainId, - bytesBlockHash, - common.HexToAddress(setup.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, - txPath, // TEST_PATH, - txValue, // TEST_TX_VALUE, - txNodes, // TEST_TX_NODES, - receiptValue, // TEST_RECEIPT_VALUE, - receiptNodes, // TEST_RECEIPT_NODES, - common.HexToAddress(setup.AddrFrom), // TRIG_CALLED_BY, - ) - c.Printf("Verify and Executed Event:\nResult:\t%+v\n", result) - } + c.Println("Connecting to: " + setup.AddrTo + " and " + setup.AddrFrom) + c.ShowPrompt(false) + defer c.ShowPrompt(true) // yes, revert after login. + + // Get the chainId + bytesChainId := common.HexToHash(setup.ChainId) + + // Get the transaction hash + c.Print("Enter Transaction Hash: ") + txHash := c.ReadLine() + bytesTxHash := common.HexToHash(txHash) + + // Get the blockHash + c.Print("Enter Block Hash: ") + blockHash := c.ReadLine() + bytesBlockHash := common.HexToHash(blockHash) + + // Generate the proof + txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( + ctx, + clientFrom, + bytesTxHash, + ) + + amount := big.NewInt(10000000) + + // Execute + tx := contract.VerifyExecute( + ctx, + ethclientTo, + keyTo.PrivateKey, + Function, + common.HexToAddress(setup.Function), + bytesChainId, + bytesBlockHash, + common.HexToAddress(setup.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, + txPath, // TEST_PATH, + txValue, // TEST_TX_VALUE, + txNodes, // TEST_TX_NODES, + receiptValue, // TEST_RECEIPT_VALUE, + receiptNodes, // TEST_RECEIPT_NODES, + common.HexToAddress(setup.AddrFrom), // TRIG_CALLED_BY, + amount, + ) + c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) c.Println("===============================================================") }, }) diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index 73b3d4d..f9d6c43 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -180,15 +180,12 @@ func TransactionContract( err = backend.SendTransaction(ctx, signedTx) if err != nil { - log.Fatal("ERROR sending contract deployment transaction") + log.Fatal("ERROR sending transaction", err) } return signedTx } func CompileContract(contract string) (compiledContract *compiler.Contract) { - // --------------------------------------------- - // COMPILE VALIDATION AND DEPENDENCIES - // --------------------------------------------- basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" contractPath := basePath + contract + ".sol" @@ -197,7 +194,6 @@ func CompileContract(contract string) (compiledContract *compiler.Contract) { log.Fatal("ERROR failed to compile contract:", err) } - // compiledContract = contracts[basePath+contract+".sol:"+contract] return diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index f74c5b3..bd1f55d 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -194,13 +194,15 @@ func Test_VerifyTx(t *testing.T) { // --------------------------------------------- // VERIFY FUNCTION EXECUITION // --------------------------------------------- - txTriggerPath := []byte{0x13} // SHOULD SOMEHOW BE DYNAMIC! - txTriggerRLP, _ := rlp.EncodeToBytes(txTrigger) - txTriggerProofArr := utils.Proof(txTrie, txTriggerPath[:]) - receiptTrigger, _ := rlp.EncodeToBytes(blockReceipts[0x13]) - receiptTriggerProofArr := utils.Proof(receiptTrie, txTriggerPath[:]) triggerCalledBy, _ := types.Sender(signer, txTrigger) + // Generate the proof + txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( + ctx, + clientRPC, + txHashWithEvent, + ) + txVerifyAndExecuteFunction := VerifyExecute( ctx, blockchain, @@ -209,13 +211,14 @@ func Test_VerifyTx(t *testing.T) { consumerFunctionContractInstance.Address, testChainID, blockHash, - *txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, - txTriggerPath, // TEST_PATH, - txTriggerRLP, // TEST_TX_VALUE, - txTriggerProofArr, // TEST_TX_NODES, - receiptTrigger, // TEST_RECEIPT_VALUE, - receiptTriggerProofArr, // TEST_RECEIPT_NODES, - triggerCalledBy, // TRIG_CALLED_BY, + *txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, + txPath, // TEST_PATH, + txValue, // TEST_TX_VALUE, + txNodes, // TEST_TX_NODES, + receiptValue, // TEST_RECEIPT_VALUE, + receiptNodes, // TEST_RECEIPT_NODES, + triggerCalledBy, // TRIG_CALLED_BY, + nil, ) blockchain.Commit() diff --git a/ion-cli/contracts/function.go b/ion-cli/contracts/function.go index ffab442..c0b42f0 100644 --- a/ion-cli/contracts/function.go +++ b/ion-cli/contracts/function.go @@ -4,6 +4,7 @@ import ( "context" "crypto/ecdsa" "log" + "math/big" "os" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -28,7 +29,7 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( contracts, err := compiler.CompileSolidity("", consumerFunctionContractPath, triggerEventVerifierContractPath) if err != nil { - log.Fatal("ERROR failed to compile Ion.sol:", err) + log.Fatal("ERROR failed to compile TriggerEventVerifier.sol:", err) } triggerEventVerifierContract := contracts[triggerEventVerifierContractPath+":TriggerEventVerifier"] @@ -107,6 +108,7 @@ func VerifyExecute( receiptTrigger []byte, receiptTriggerProofArr []byte, triggerCalledBy common.Address, + amount *big.Int, ) (tx *types.Transaction) { tx = TransactionContract( @@ -115,7 +117,7 @@ func VerifyExecute( userKey, contract, toAddr, - nil, + amount, uint64(3000000), "verifyAndExecute", chainId, diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index 0ee51f9..1c9df3a 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -27,7 +27,7 @@ func CompileAndDeployValidation( contracts, err := compiler.CompileSolidity("", validationContractPath) if err != nil { - log.Fatal("ERROR failed to compile Ion.sol:", err) + log.Fatal("ERROR failed to compile Validation.sol:", err) } validationContract := contracts[basePath+"Validation.sol:Validation"] @@ -156,7 +156,7 @@ func LatestValidBlock( userAddr common.Address, toAddr common.Address, chainId common.Hash, -) (isBlockValid bool) { +) (latestBlock common.Hash) { methodName := "m_latestblock" CallContract( ctx, @@ -165,7 +165,7 @@ func LatestValidBlock( userAddr, toAddr, methodName, - &isBlockValid, + &latestBlock, chainId, ) return diff --git a/ion-cli/main.go b/ion-cli/main.go index 9325020..9bd57d4 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -28,7 +28,6 @@ func main() { Validation := contract.CompileContract("Validation") Function := contract.CompileContract("Function") Trigger := contract.CompileContract("Trigger") - printInfo(setup) // Launch the CLI @@ -52,15 +51,16 @@ func printInfo(setup config.Setup) { // display welcome info. fmt.Println("===============================================================") fmt.Println("Ion Command Line Interface\n") - fmt.Println("RPC Client [to]:") - fmt.Println("Listening on:\t\t" + setup.AddrTo) - fmt.Println("User Account:\t\t" + setup.AccountTo) - fmt.Println("Validation Contract:\t" + setup.Validation) - fmt.Println("Validation ChainId:\t" + setup.ChainId) - fmt.Println("Ion Contract:\t\t" + setup.Ion) - fmt.Println("\nRPC Client [from]:") - fmt.Println("Listening on:\t\t" + setup.AddrFrom) - fmt.Println("User Account:\t\t" + setup.AccountFrom) - fmt.Println("Trigger Contract:\t" + setup.Trigger) + fmt.Println("RPC Client [TO]:") + fmt.Println("\tListening on:\t\t" + setup.AddrTo) + fmt.Println("\tUser Account:\t\t" + setup.AccountTo) + fmt.Println("\tRPC ChainId:\t\t" + setup.ChainId) + fmt.Println("\tValidation Contract:\t" + setup.Validation) + fmt.Println("\tIon Contract:\t\t" + setup.Ion) + fmt.Println("\tFunction Contract:\t" + setup.Function) + fmt.Println("\nRPC Client [FROM]:") + fmt.Println("\tListening on:\t\t" + setup.AddrFrom) + fmt.Println("\tUser Account:\t\t" + setup.AccountFrom) + fmt.Println("\tTrigger Contract:\t" + setup.Trigger) fmt.Println("===============================================================") } diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index c10275f..cb8b2f0 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -1,11 +1,11 @@ { - "rpc-to":"http://127.0.0.1:8545", + "rpc-to":"http://127.0.0.1:8501", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "password-to":"password1", "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "ion-addr":"0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613", - "function-addr":"0x49e71afdcaf62d7384f0b801c9e3c6e18d4a2597", - "validation-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", + "ion-addr":"0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", + "function-addr":"0x93981af8db02c7ef40d0ed61caef2726a79eb903", + "validation-addr":"0xd6894ba69834b5d0511c50971bc844dff04c2073", "validation-chainid":"0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075", "rpc-from":"https://rinkeby.infura.io", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 5a4e049..093ec06 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,5 +1,4 @@ const Ion = artifacts.require("Ion"); -const Recover = artifacts.require("Recover"); const Validation = artifacts.require("Validation"); const PatriciaTrie = artifacts.require("PatriciaTrie"); const EventFunction = artifacts.require("Function"); @@ -7,9 +6,7 @@ const EventVerifier = artifacts.require("EventVerifier"); module.exports = async (deployer) => { try { - deployer.deploy(Recover) - .then(() => Recover.deployed) - .then(() => deployer.deploy(Validation, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) + deployer.deploy(Validation, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") .then(() => Validation.deployed) .then(() => deployer.deploy(PatriciaTrie)) .then(() => PatriciaTrie.deployed) diff --git a/test/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol index 4a98afb..07c9682 100644 --- a/test/PatriciaTrieTest.sol +++ b/test/PatriciaTrieTest.sol @@ -45,7 +45,7 @@ contract PatriciaTrieTest { Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); } - function testFailVerifyNestedNodes() returns (bool) { + function FailVerifyNestedNodes() returns (bool) { bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; bytes memory path = hex"62"; From bb83ec1ceb59863fcae154fd0cf557439081968b Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 9 Aug 2018 15:11:02 +0100 Subject: [PATCH 125/203] Updated README --- README.md | 27 ++++++++++++++++++++------- test/ion.js | 8 ++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b679250..6271ea3 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,27 @@ # Ion Interoperability Protocol +The Ion Interoperability Protocol provides a framework to perform interoperability across multiple turing-complete blockchains. Using the generalised framework specific use cases, such as atomic swaps, can be developed. -The Ion Interoperability Protocol provides mechanisms to perform atomic swaps and currency transfers across multiple turing-complete blockchains. +In order to perform cross-chain interop the Ion framework verifies specific transactions executed on one blockchain A on another blockchain B. Being able to verify these transactions cross-chain requires submission of valid block headers, to the blockchain where a transaction is to be proven, and then performing a number of Patricia trie proofs of the transaction, receipts and logs. Smart contracts can then be built to execute only if the proof is verified, this is known as continuous execution. -## Ion State Verification Scheme +To facilitate this Ion has three main components: + * Ion Hub Contract + * Block Validation Scheme + * Ion Framework Contracts -## Block Validation Scheme -Block validation scheme is a set of smart contracts which ensures that block headers submitted to the contract are mined/sealed by an approved partie(s). The motivation behind this is to update the state of a blockchain onto another blockchain. To do this we first need to know which blocks are valid - dependent on the definition of a valid by the underlying consensus algorithm. As deterministic finality is a requirement we seek Clique PoA and Istanbul PBFT consensus is to be used on the chain from which the state is being taken. +The Ion hub contract is the core component of the framework, the contract persists key data of all valid blocks submitted to the validation contracts. To prove a transaction has occurred on an external blockchain the Ion framework contract require: -For a full description and roadmap of the project please refer to the Clearmatics [Ion-Stage-2 Wiki](https://github.com/clearmatics/ion/wiki/Ion-Stage-2---Proposal#validation). +* Block Header (RLP encoding of the following array of items): + * Previous block hash + * State root hash + * Tx root hash + * TxReceipt root hash +* Block Hash + +For each block submitted to the validation contracts this information is appended to the Ion hub contract, thus creating a generic interface for Ion framework contracts to receive valid block data. Ion provides a generalised interoperability framework and thus block validation is designed to be modular, in order to allow for interop between chains with any consensus mechanism. + +When external blockchains are registered with a specific validation contract, having its own consensus specific validation mechanism, the validation contract adds the chain to the Ion hub. Subsequently all blocks successfully submitted to the validation contract are added to the Ion hub. + +More details can be found in the [Ion Wiki](https://github.com/clearmatics/ion/wiki). ## Running the Project A Clique PoA chain is launched and then the block headers are taken and updated to the validation contract which is deployed on a ganache chain. However in the javascript tests the contract is deployed on the PoA chain itself for sake of simplicity, this has no bearing on the functionality of the project. @@ -19,7 +33,7 @@ Running the project requires initialisation of the following components: In order to use the smart contracts and run the tests it is necessary to first initialise the test networks. -***Note:*** that as the contract searches for specific parts of the block header that only exist in Clique and IBFT, Ganache or Ethash chains cannot be used for the _root_ blockchain from which headers are extracted. +**Note:** that as the contract searches for specific parts of the block header that only exist in Clique and IBFT, Ganache or Ethash chains cannot be used for the _root_ blockchain from which headers are extracted. ### Requirements * golang version: 1.9.x @@ -39,7 +53,6 @@ $ tree -L 1 Which hopefully returns this: ``` . -├── abi ├── CODE_OF_CONDUCT.md ├── contracts ├── CONTRIBUTING.md diff --git a/test/ion.js b/test/ion.js index feb70cc..71a1342 100644 --- a/test/ion.js +++ b/test/ion.js @@ -150,7 +150,7 @@ const TRIG_CALLED_BY = "0x279884e133f9346f2fad9cc158222068221b613e"; const GENESIS_HASH = TESTBLOCK.parentHash; -contract.only('Ion.js', (accounts) => { +contract('Ion.js', (accounts) => { it('Deploy Ion', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); let chainId = await ion.chainId(); @@ -279,7 +279,7 @@ contract.only('Ion.js', (accounts) => { const validation = await Validation.new(DEPLOYEDCHAINID); const verifier = await TriggerEventVerifier.new(); - const functionContract = await Function.new(ion.address, verifier.address); + const functionContract = await FunctionEvent.new(ion.address, verifier.address); }) it('Verify Function Execution', async () => { @@ -287,7 +287,7 @@ contract.only('Ion.js', (accounts) => { const validation = await Validation.new(DEPLOYEDCHAINID); const verifier = await TriggerEventVerifier.new(); - const functionContract = await Function.new(ion.address, verifier.address); + const functionContract = await FunctionEvent.new(ion.address, verifier.address); // Register chain and submit block to Ion await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); @@ -309,7 +309,7 @@ contract.only('Ion.js', (accounts) => { const validation = await Validation.new(DEPLOYEDCHAINID); const verifier = await TriggerEventVerifier.new(); - const functionContract = await Function.new(ion.address, verifier.address); + const functionContract = await FunctionEvent.new(ion.address, verifier.address); // Register chain and submit block to Ion await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); From d35cb9f3831c8163488682e93715513cbe6035e1 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 9 Aug 2018 16:14:55 +0100 Subject: [PATCH 126/203] Updated the architecture --- contracts/Ion.sol | 54 +++++++++++++++++++++++++--------------- contracts/Validation.sol | 8 ++++++ 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 1f98cc8..eda0373 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -6,19 +6,26 @@ import "./libraries/ECVerify.sol"; import "./libraries/RLP.sol"; import "./libraries/PatriciaTrie.sol"; import "./libraries/SolidityUtils.sol"; -import "./Validation.sol"; contract Ion { using RLP for RLP.RLPItem; using RLP for RLP.Iterator; using RLP for bytes; - // bytes32 public blockHash; bytes32 public chainId; bytes32[] public registeredChains; - uint256 public blockHeight; + + /* + * @description persists the last submitted block of a chain being validated + */ + struct BlockHeader { + bytes32 txRootHash; + bytes32 receiptRootHash; + } mapping (bytes32 => bool) public chains; + mapping (bytes32 => bool) public m_blockhashes; + mapping (bytes32 => BlockHeader) public m_blockheaders; mapping (bytes32 => address) public m_validation; @@ -68,8 +75,7 @@ contract Ion { * Modifier that checks if the provided block hash has been verified by the validation contract */ modifier onlyExistingBlocks(bytes32 _id, bytes32 _hash) { - Validation validation = Validation(m_validation[_id]); - require(validation.m_blockhashes(_id, _hash), "Block does not exist for chain"); + require(m_blockhashes[_hash], "Block does not exist for chain"); _; } @@ -134,11 +140,7 @@ contract Ion { public returns (bool) { - // Connect to validation contract - Validation validation = Validation(m_validation[_id]); - bytes32 txRootHash = validation.getTxRootHash(_id, _blockHash); - //assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, txRootHash) ); - verifyProof(_value, _parentNodes, _path, txRootHash); + verifyProof(_value, _parentNodes, _path, m_blockheaders[_blockHash].txRootHash); emit VerifiedProof(_id, _blockHash, uint(ProofType.TX)); return true; @@ -173,10 +175,7 @@ contract Ion { public returns (bool) { - Validation validation = Validation(m_validation[_id]); - bytes32 receiptRootHash = validation.getReceiptRootHash(_id, _blockHash); - // assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, receiptRootHash) ); - verifyProof(_value, _parentNodes, _path, receiptRootHash); + verifyProof(_value, _parentNodes, _path, m_blockheaders[_blockHash].receiptRootHash); emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); return true; @@ -217,17 +216,32 @@ contract Ion { public returns (bool) { - Validation validation = Validation(m_validation[_id]); - bytes32 txRootHash = validation.getTxRootHash(_id, _blockHash); - bytes32 receiptRootHash = validation.getReceiptRootHash(_id, _blockHash); - - assert( txRootHash == getRootNodeHash(_txNodes) ); - assert( receiptRootHash == getRootNodeHash(_receiptNodes) ); + assert( m_blockheaders[_blockHash].txRootHash == getRootNodeHash(_txNodes) ); + assert( m_blockheaders[_blockHash].receiptRootHash == getRootNodeHash(_receiptNodes) ); emit VerifiedProof(_id, _blockHash, uint(ProofType.ROOTS)); return true; } + /* + * @description when a block is submitted the root hash must be added to a mapping of chains to hashes + * @param _hash root hash of the block being added + */ + function addBlockHash(bytes32 _hash) public { + m_blockhashes[_hash] = true; + } + +/* + * @description when a block is submitted the header must be added to a mapping of chains to blockheaders + * @param _hash root hash of the block being added + * @param _txRootHash transaction root hash of the block being added + * @param _receiptRootHash receipt root hash of the block being added + */ + function addBlockHeader(bytes32 _hash, bytes32 _txRootHash, bytes32 _receiptRootHash) public { + m_blockheaders[_hash].txRootHash = _txRootHash; + m_blockheaders[_hash].receiptRootHash = _receiptRootHash; + } + /* ======================================================================================================================== diff --git a/contracts/Validation.sol b/contracts/Validation.sol index fc330f1..69c004c 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -12,6 +12,7 @@ contract Validation { using RLP for RLP.Iterator; using RLP for bytes; + address registeredIon; bytes32 public chainId; /* @@ -61,6 +62,7 @@ contract Validation { Ion ion = Ion(_ion); require(ion.addChain(_id), "Chain not added to Ion successfully!"); + registeredIon = _ion; m_blockheaders[_id][_genesisHash].blockHeight = 0; m_blockheaders[_id][_genesisHash].latestHash = _genesisHash; @@ -133,6 +135,12 @@ contract Validation { m_blockheaders[_id][_hash].prevBlockHash = _parentHash; m_blockheaders[_id][_hash].txRootHash = _txRootHash; m_blockheaders[_id][_hash].receiptRootHash = _receiptRootHash; + + // Add block to Ion + Ion ion = Ion(registeredIon); + ion.addBlockHeader(_hash, _txRootHash, _receiptRootHash); + ion.addBlockHash(_hash); + } /* From 9907e395dc891a18242d9b110130f97a86d17b46 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 9 Aug 2018 16:26:06 +0100 Subject: [PATCH 127/203] Added copyright notices --- contracts/EventVerifier.sol | 2 ++ contracts/Function.sol | 2 ++ contracts/IonCompatible.sol | 2 ++ contracts/Migrations.sol | 1 - contracts/Trigger.sol | 2 ++ contracts/TriggerEventVerifier.sol | 2 ++ ion-cli/cli/cli.go | 1 - ion-cli/cli/cli_test.go | 1 - ion-cli/cli/rpc.go | 1 - ion-cli/cli/rpc_test.go | 1 - ion-cli/contracts/contract.go | 1 + ion-cli/contracts/contract_test.go | 1 + ion-cli/contracts/flow_test.go | 1 + ion-cli/contracts/function.go | 1 + ion-cli/contracts/ion.go | 1 + ion-cli/contracts/raw_example_test.go | 1 + ion-cli/contracts/trigger.go | 1 + ion-cli/contracts/validation.go | 1 + ion-cli/setup.json | 10 ---------- ion-cli/utils/client.go | 1 + ion-cli/utils/client_test.go | 1 + ion-cli/utils/proof.go | 1 + ion-cli/utils/proof_test.go | 1 - ion-cli/utils/trie.go | 1 + 24 files changed, 22 insertions(+), 16 deletions(-) delete mode 100644 ion-cli/setup.json diff --git a/contracts/EventVerifier.sol b/contracts/EventVerifier.sol index 242aab5..038731c 100644 --- a/contracts/EventVerifier.sol +++ b/contracts/EventVerifier.sol @@ -1,3 +1,5 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; import "./libraries/RLP.sol"; diff --git a/contracts/Function.sol b/contracts/Function.sol index b9467f3..7259d7f 100644 --- a/contracts/Function.sol +++ b/contracts/Function.sol @@ -1,3 +1,5 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; import "./Ion.sol"; diff --git a/contracts/IonCompatible.sol b/contracts/IonCompatible.sol index b93bbdb..8144614 100644 --- a/contracts/IonCompatible.sol +++ b/contracts/IonCompatible.sol @@ -1,3 +1,5 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.0; import "./Ion.sol"; diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index 9de91ab..3a3cc99 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,6 +1,5 @@ // Copyright (c) 2016-2017 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ - pragma solidity ^0.4.23; contract Migrations { diff --git a/contracts/Trigger.sol b/contracts/Trigger.sol index 66958e3..dd06a4c 100644 --- a/contracts/Trigger.sol +++ b/contracts/Trigger.sol @@ -1,3 +1,5 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; /* diff --git a/contracts/TriggerEventVerifier.sol b/contracts/TriggerEventVerifier.sol index 0a8763e..6d348ec 100644 --- a/contracts/TriggerEventVerifier.sol +++ b/contracts/TriggerEventVerifier.sol @@ -1,3 +1,5 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; import "./libraries/RLP.sol"; diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 7e09508..19aacfa 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -1,5 +1,4 @@ // Copyright (c) 2018 Clearmatics Technologies Ltd - package cli import ( diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go index 69d8e5b..468d4e2 100644 --- a/ion-cli/cli/cli_test.go +++ b/ion-cli/cli/cli_test.go @@ -1,5 +1,4 @@ // Copyright (c) 2018 Clearmatics Technologies Ltd - package cli_test import ( diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index e59a408..7abffa1 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -1,5 +1,4 @@ // Copyright (c) 2018 Clearmatics Technologies Ltd - package cli import ( diff --git a/ion-cli/cli/rpc_test.go b/ion-cli/cli/rpc_test.go index 7b96728..83902e8 100644 --- a/ion-cli/cli/rpc_test.go +++ b/ion-cli/cli/rpc_test.go @@ -1,5 +1,4 @@ // Copyright (c) 2018 Clearmatics Technologies Ltd - package cli import ( diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index f9d6c43..10fa329 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/contracts/contract_test.go b/ion-cli/contracts/contract_test.go index 3155322..f04d74c 100644 --- a/ion-cli/contracts/contract_test.go +++ b/ion-cli/contracts/contract_test.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 40b0851..2ed1eec 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/contracts/function.go b/ion-cli/contracts/function.go index c0b42f0..084a0b0 100644 --- a/ion-cli/contracts/function.go +++ b/ion-cli/contracts/function.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go index c93f9c3..be180e9 100644 --- a/ion-cli/contracts/ion.go +++ b/ion-cli/contracts/ion.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/contracts/raw_example_test.go b/ion-cli/contracts/raw_example_test.go index c4d5a93..0706eed 100644 --- a/ion-cli/contracts/raw_example_test.go +++ b/ion-cli/contracts/raw_example_test.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/contracts/trigger.go b/ion-cli/contracts/trigger.go index b047b48..f960001 100644 --- a/ion-cli/contracts/trigger.go +++ b/ion-cli/contracts/trigger.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index 1c9df3a..0996bbd 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package contract import ( diff --git a/ion-cli/setup.json b/ion-cli/setup.json deleted file mode 100644 index 8a80e72..0000000 --- a/ion-cli/setup.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "rpc-to":"http://127.0.0.1:8545", - "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-from":"http://127.0.0.1:8501", - "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-from":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f" -} diff --git a/ion-cli/utils/client.go b/ion-cli/utils/client.go index 31112a4..35062cc 100644 --- a/ion-cli/utils/client.go +++ b/ion-cli/utils/client.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package utils import ( diff --git a/ion-cli/utils/client_test.go b/ion-cli/utils/client_test.go index 884d8d6..3990c99 100644 --- a/ion-cli/utils/client_test.go +++ b/ion-cli/utils/client_test.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package utils_test import ( diff --git a/ion-cli/utils/proof.go b/ion-cli/utils/proof.go index 9fb3f3b..e8f6748 100644 --- a/ion-cli/utils/proof.go +++ b/ion-cli/utils/proof.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package utils import ( diff --git a/ion-cli/utils/proof_test.go b/ion-cli/utils/proof_test.go index 23ecac0..e7b613b 100644 --- a/ion-cli/utils/proof_test.go +++ b/ion-cli/utils/proof_test.go @@ -1,5 +1,4 @@ // Copyright (c) 2018 Clearmatics Technologies Ltd - package utils_test import ( diff --git a/ion-cli/utils/trie.go b/ion-cli/utils/trie.go index 607fbde..6ee67cc 100644 --- a/ion-cli/utils/trie.go +++ b/ion-cli/utils/trie.go @@ -1,3 +1,4 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd package utils import ( From 4c14f4f4906d48cc8a68d71ee9a8d8fa10968a99 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 9 Aug 2018 17:30:13 +0100 Subject: [PATCH 128/203] test --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6271ea3..7f5c825 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# Ion Interoperability Protocol -The Ion Interoperability Protocol provides a framework to perform interoperability across multiple turing-complete blockchains. Using the generalised framework specific use cases, such as atomic swaps, can be developed. +# Ion Interoperability Framework +The Ion Interoperability Framework provides a interface to perform interoperability across multiple turing-complete blockchains. Using the generalised framework specific use cases, such as atomic swaps, can be developed. In order to perform cross-chain interop the Ion framework verifies specific transactions executed on one blockchain A on another blockchain B. Being able to verify these transactions cross-chain requires submission of valid block headers, to the blockchain where a transaction is to be proven, and then performing a number of Patricia trie proofs of the transaction, receipts and logs. Smart contracts can then be built to execute only if the proof is verified, this is known as continuous execution. To facilitate this Ion has three main components: * Ion Hub Contract - * Block Validation Scheme + * Modular Validation Scheme * Ion Framework Contracts The Ion hub contract is the core component of the framework, the contract persists key data of all valid blocks submitted to the validation contracts. To prove a transaction has occurred on an external blockchain the Ion framework contract require: From 144553ebd3e01a1d6fae747c0c5f336a6d509705 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 13 Aug 2018 17:14:01 +0100 Subject: [PATCH 129/203] made some small changes to verifyExecution to work as expected --- README.md | 78 +++++++++++++++++++-------- contracts/Function.sol | 3 +- contracts/Ion.sol | 4 -- contracts/libraries/SolidityUtils.sol | 16 ++++++ ion-cli/cli/cli.go | 24 +++++---- ion-cli/contracts/contract.go | 2 +- ion-cli/contracts/flow_test.go | 2 +- ion-cli/main.go | 8 +++ ion-cli/rinkeby.json | 2 +- migrations/2_deploy_contracts.js | 2 +- 10 files changed, 99 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 7f5c825..64bab2e 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ A brief overview of the steps required are: * Verify event happened on testrpc and execute function ##### Step 1. Launch Ion CLI -Having followed the instructions to run and build the Ion CLI and testrpc, see [here](#### Runninig Ion CLI), launch the CLI with the setup file `rinkeby.json`. +Having followed the instructions to run and build the Ion CLI and testrpc, see [here](https://github.com/clearmatics/ion/tree/ion-stage-2#running-ion-cli), launch the CLI with the setup file `rinkeby.json`. ``` $ ./ion-cli --config rinkeby.json =============================================================== @@ -267,31 +267,65 @@ Enter Transaction Hash: 0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299ae Enter Block Hash: 0x74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046 Returns: -Transaction Hash: 0xc0bdb1b8dadd7bd0a68a9f773286236444a7c90fef9a2a7dacd9640f393df736 +Transaction Hash: 0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb =============================================================== ``` ##### Step 5. Check Transaction Successfully Executed Attach to the geth client of the RPC TO chain and run: ``` -> eth.getTransaction("0xc0bdb1b8dadd7bd0a68a9f773286236444a7c90fef9a2a7dacd9640f393df736") -{ - blockHash: "0x4cd5b0a89b96b3e8c5e9176ecc4bf23586958118d82360ba55e24d9170ad2032", - blockNumber: 438, - contractAddress: null, - cumulativeGasUsed: 104964, - from: "0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - gasUsed: 104964, - logs: [], - logsBloom: "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000", - status: "0x0", - to: "0x93981af8db02c7ef40d0ed61caef2726a79eb903", - transactionHash: "0xc0bdb1b8dadd7bd0a68a9f773286236444a7c90fef9a2a7dacd9640f393df736", - transactionIndex: 0 -} +> eth.getTransactionReceipt("0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15") +{ + blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", + blockNumber: 11, + contractAddress: null, + cumulativeGasUsed: 352099, + gasUsed: 352099, + logs: [{ + address: "0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", + blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", + blockNumber: 11, + data: "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac807574d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b0460000000000000000000000000000000000000000000000000000000000000002", + logIndex: 0, + topics: ["0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046"], + transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", + transactionIndex: 0, + type: "mined" + }, { + address: "0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", + blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", + blockNumber: 11, + data: "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac807574d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b0460000000000000000000000000000000000000000000000000000000000000000", + logIndex: 1, + topics: ["0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046"], + transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", + transactionIndex: 0, + type: "mined" + }, { + address: "0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", + blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", + blockNumber: 11, + data: "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac807574d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b0460000000000000000000000000000000000000000000000000000000000000001", + logIndex: 2, + topics: ["0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046"], + transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", + transactionIndex: 0, + type: "mined" + }, { + address: "0x93981af8db02c7ef40d0ed61caef2726a79eb903", + blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", + blockNumber: 11, + data: "0x00", + logIndex: 3, + topics: ["0x68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e"], + transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", + transactionIndex: 0, + type: "mined" + }], + logsBloom: "0x00000000000000000000000000000000000000000001000000080000000000000000000800000000000000000000000000000000000000010000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000100080000000000000000000000040000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000", + status: "0x1", + transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", + transactionIndex: 0 +} ``` -`status: "0x0"` shows the transaction executed successfully! \ No newline at end of file +`status: "0x1"` shows the transaction executed successfully! \ No newline at end of file diff --git a/contracts/Function.sol b/contracts/Function.sol index 7259d7f..5743802 100644 --- a/contracts/Function.sol +++ b/contracts/Function.sol @@ -1,8 +1,7 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd + // Copyright (c) 2016-2018 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; -import "./Ion.sol"; import "./IonCompatible.sol"; contract TriggerEventVerifier { diff --git a/contracts/Ion.sol b/contracts/Ion.sol index eda0373..5ff9c1a 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -26,7 +26,6 @@ contract Ion { mapping (bytes32 => bool) public chains; mapping (bytes32 => bool) public m_blockhashes; mapping (bytes32 => BlockHeader) public m_blockheaders; - mapping (bytes32 => address) public m_validation; @@ -105,9 +104,6 @@ contract Ion { chains[_id] = true; registeredChains.push(_id); - // Create mapping of registered _id to the validation address - m_validation[_id] = msg.sender; - return true; } diff --git a/contracts/libraries/SolidityUtils.sol b/contracts/libraries/SolidityUtils.sol index 0707c19..939b0d6 100644 --- a/contracts/libraries/SolidityUtils.sol +++ b/contracts/libraries/SolidityUtils.sol @@ -17,6 +17,22 @@ library SolUtils { } } + + /* + * @description copies 20 bytes from input into the output + * @param output memory allocation for the data you need to extract + * @param input array from which the data should be extracted + * @param buf index which the data starts within the byte array needs to have 32 bytes appended + */ + function BytesToBytes20(bytes b, uint256 buf) internal pure returns (bytes20) { + bytes20 out; + + for (uint i = 0; i < 20; i++) { + out |= bytes20(b[buf + i] & 0xFF) >> (i * 8); + } + return out; + } + /* * @description copies output.length bytes from the input into the output * @param output memory allocation for the data you need to extract diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 19aacfa..fb760df 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -117,6 +117,7 @@ func Launch( c.Print("Enter Validators: ") validatorString := c.ReadLine() valArray := strings.Fields(validatorString) + // valArray := strings.Fields("0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91") var validators []common.Address for _, val := range valArray { validators = append(validators, common.HexToAddress(val)) @@ -126,6 +127,7 @@ func Launch( c.Print("Enter Genesis Hash: ") genesis := c.ReadLine() bytesGenesis := common.HexToHash(genesis) + // bytesGenesis := common.HexToHash("0x100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c") tx := contract.RegisterChain( ctx, @@ -162,6 +164,7 @@ func Launch( // Get the block number c.Print("Enter Block Number: ") blockNum := c.ReadLine() + // blockNum := "2776659" c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) signedBlock, unsignedBlock := calculateRlpEncoding(ethclientFrom, blockNum) @@ -284,11 +287,13 @@ func Launch( c.Print("Enter Transaction Hash: ") txHash := c.ReadLine() bytesTxHash := common.HexToHash(txHash) + // bytesTxHash := common.HexToHash("0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098") // Get the blockHash c.Print("Enter Block Hash: ") blockHash := c.ReadLine() bytesBlockHash := common.HexToHash(blockHash) + // bytesBlockHash := common.HexToHash("0x74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046") // Generate the proof txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( @@ -297,26 +302,25 @@ func Launch( bytesTxHash, ) - amount := big.NewInt(10000000) - // Execute tx := contract.VerifyExecute( ctx, ethclientTo, - keyTo.PrivateKey, + keyFrom.PrivateKey, Function, common.HexToAddress(setup.Function), bytesChainId, bytesBlockHash, common.HexToAddress(setup.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, - txPath, // TEST_PATH, - txValue, // TEST_TX_VALUE, - txNodes, // TEST_TX_NODES, - receiptValue, // TEST_RECEIPT_VALUE, - receiptNodes, // TEST_RECEIPT_NODES, - common.HexToAddress(setup.AddrFrom), // TRIG_CALLED_BY, - amount, + txPath, // TEST_PATH, + txValue, // TEST_TX_VALUE, + txNodes, // TEST_TX_NODES, + receiptValue, // TEST_RECEIPT_VALUE, + receiptNodes, // TEST_RECEIPT_NODES, + common.HexToAddress(setup.AccountFrom), // TRIG_CALLED_BY, + nil, ) + c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) c.Println("===============================================================") }, diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index 10fa329..7e317fa 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -181,7 +181,7 @@ func TransactionContract( err = backend.SendTransaction(ctx, signedTx) if err != nil { - log.Fatal("ERROR sending transaction", err) + log.Fatal("ERROR sending transaction: ", err) } return signedTx } diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 2ed1eec..869e494 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -78,7 +78,7 @@ func Test_VerifyTx(t *testing.T) { alloc[userAddr] = core.GenesisAccount{Balance: userIntialBalance} blockchain := backends.NewSimulatedBackend(alloc) - // ----txTrigger----------------------------------------- + // --------------------------------------------- // COMPILE AND DEPLOY ION // --------------------------------------------- contractChan := CompileAndDeployIon(ctx, blockchain, userKey, deployedChainID) diff --git a/ion-cli/main.go b/ion-cli/main.go index 9bd57d4..4ece45e 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -3,8 +3,10 @@ package main import ( + "encoding/json" "flag" "fmt" + "log" "os" "github.com/clearmatics/ion/ion-cli/cli" @@ -27,6 +29,12 @@ func main() { // Compile contracts to use in sending transactions Validation := contract.CompileContract("Validation") Function := contract.CompileContract("Function") + functionAbiStr, err := json.Marshal(Function.Info.AbiDefinition) + if err != nil { + log.Fatal("ERROR marshalling abi to string", err) + } + + fmt.Printf("Function: %s\n", functionAbiStr) Trigger := contract.CompileContract("Trigger") printInfo(setup) diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index cb8b2f0..9bf0119 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -1,5 +1,5 @@ { - "rpc-to":"http://127.0.0.1:8501", + "rpc-to":"http://127.0.0.1:8545", "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "password-to":"password1", "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 093ec06..7ff1c25 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -2,7 +2,7 @@ const Ion = artifacts.require("Ion"); const Validation = artifacts.require("Validation"); const PatriciaTrie = artifacts.require("PatriciaTrie"); const EventFunction = artifacts.require("Function"); -const EventVerifier = artifacts.require("EventVerifier"); +const EventVerifier = artifacts.require("TriggerEventVerifier"); module.exports = async (deployer) => { try { From f70cdb8730a9bb71ee1624c60660ff40dd30f876 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 14 Aug 2018 09:30:32 +0100 Subject: [PATCH 130/203] Cleaned some bytes manip stuff into the general library --- contracts/TriggerEventVerifier.sol | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/contracts/TriggerEventVerifier.sol b/contracts/TriggerEventVerifier.sol index 6d348ec..347383f 100644 --- a/contracts/TriggerEventVerifier.sol +++ b/contracts/TriggerEventVerifier.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.23; import "./libraries/RLP.sol"; +import "./libraries/SolidityUtils.sol"; import "./EventVerifier.sol"; /* @@ -39,7 +40,8 @@ contract TriggerEventVerifier is EventVerifier { parameter in the event from our function call. This acts as our conditional check that the event called is what the user expects. */ - bytes20 b20_address = bytesToBytes20(data, data.length - 20); + // bytes20 b20_address = bytesToBytes20(data, data.length - 20); + bytes20 b20_address = SolUtils.BytesToBytes20(data, data.length - 20); assert( b20_address == _expectedAddress ); /* @@ -49,12 +51,4 @@ contract TriggerEventVerifier is EventVerifier { return true; } - function bytesToBytes20(bytes b, uint _offset) private pure returns (bytes20) { - bytes20 out; - - for (uint i = 0; i < 20; i++) { - out |= bytes20(b[_offset + i] & 0xFF) >> (i * 8); - } - return out; - } } From fd20f39a9a7176ff085acaf3ae37837d19414933 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 14 Aug 2018 14:04:15 +0100 Subject: [PATCH 131/203] Made small change to registration of validation, removing the ion address and placing it into the constructor --- contracts/EventVerifier.sol | 11 ++------ contracts/TriggerEventVerifier.sol | 1 - contracts/Validation.sol | 26 +++--------------- ion-cli/cli/cli.go | 1 - ion-cli/contracts/contract_test.go | 8 +++--- ion-cli/contracts/flow_test.go | 8 +++--- ion-cli/contracts/validation.go | 28 +++++++++---------- ion-cli/rinkeby.json | 4 +-- migrations/2_deploy_contracts.js | 8 +++--- test/ion.js | 42 ++++++++++++++--------------- test/validation.js | 43 +++++++++++++++--------------- 11 files changed, 77 insertions(+), 103 deletions(-) diff --git a/contracts/EventVerifier.sol b/contracts/EventVerifier.sol index 038731c..9bf271b 100644 --- a/contracts/EventVerifier.sol +++ b/contracts/EventVerifier.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.23; import "./libraries/RLP.sol"; +import "./libraries/SolidityUtils.sol"; /* EventVerifier @@ -49,7 +50,7 @@ contract EventVerifier { bytes32 containedEventSignature = RLP.toBytes32(topics[0]); if (containedEventSignature == _eventSignature) { // If event signature is found, check the contract address it was emitted from - bytes20 b20_emissionSource = bytesToBytes20(RLP.toData(log[0]), 0); + bytes20 b20_emissionSource = SolUtils.BytesToBytes20(RLP.toData(log[0]), 0); assert( b20_emissionSource == _contractEmittedAddress); return log; } @@ -57,12 +58,4 @@ contract EventVerifier { assert( false ); } - function bytesToBytes20(bytes b, uint _offset) private pure returns (bytes20) { - bytes20 out; - - for (uint i = 0; i < 20; i++) { - out |= bytes20(b[_offset + i] & 0xFF) >> (i * 8); - } - return out; - } } diff --git a/contracts/TriggerEventVerifier.sol b/contracts/TriggerEventVerifier.sol index 347383f..abd72da 100644 --- a/contracts/TriggerEventVerifier.sol +++ b/contracts/TriggerEventVerifier.sol @@ -40,7 +40,6 @@ contract TriggerEventVerifier is EventVerifier { parameter in the event from our function call. This acts as our conditional check that the event called is what the user expects. */ - // bytes20 b20_address = bytesToBytes20(data, data.length - 20); bytes20 b20_address = SolUtils.BytesToBytes20(data, data.length - 20); assert( b20_address == _expectedAddress ); diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 69c004c..8b294b3 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -38,8 +38,9 @@ contract Validation { /* * @param _id genesis block of the blockchain where the contract is deployed */ - constructor (bytes32 _id) public { + constructor (bytes32 _id, address _ion) public { chainId = _id; + registeredIon = _ion; } @@ -50,7 +51,7 @@ contract Validation { * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. */ - function RegisterChain(bytes32 _id, address _ion, address[] _validators, bytes32 _genesisHash) public { + function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { require( _id != chainId, "Cannot add this chain id to chain register" ); require(!chains[_id], "Chain already exists" ); chains[_id] = true; @@ -60,9 +61,8 @@ contract Validation { m_validators[_id][_validators[i]] = true; } - Ion ion = Ion(_ion); + Ion ion = Ion(registeredIon); require(ion.addChain(_id), "Chain not added to Ion successfully!"); - registeredIon = _ion; m_blockheaders[_id][_genesisHash].blockHeight = 0; m_blockheaders[_id][_genesisHash].latestHash = _genesisHash; @@ -161,24 +161,6 @@ contract Validation { m_latestblock[_id] = _hash; } - /* - * @description returns the transaction root hash of a specific block - * @param _id unique identifier of the chain from which the block hails - * @param _hash root hash of the block being queried - */ - function getTxRootHash(bytes32 _id, bytes32 _hash) public returns(bytes32) { - return(m_blockheaders[_id][_hash].txRootHash); - } - - /* - * @description returns the receipt root hash of a specific block - * @param _id unique identifier of the chain from which the block hails - * @param _hash root hash of the block being queried - */ - function getReceiptRootHash(bytes32 _id, bytes32 _hash) public returns(bytes32) { - return(m_blockheaders[_id][_hash].receiptRootHash); - } - /* * onlyRegisteredChains * param: _id (bytes32) Unique id of chain supplied to function diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index fb760df..991b180 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -136,7 +136,6 @@ func Launch( Validation, common.HexToAddress(setup.Validation), bytesChainId, - common.HexToAddress(setup.Ion), validators, bytesGenesis, ) diff --git a/ion-cli/contracts/contract_test.go b/ion-cli/contracts/contract_test.go index f04d74c..f15ed10 100644 --- a/ion-cli/contracts/contract_test.go +++ b/ion-cli/contracts/contract_test.go @@ -91,13 +91,14 @@ func Test_RegisterChain(t *testing.T) { ionContractInstance := <-contractChan // deploy validation contract - contractChan = CompileAndDeployValidation(ctx, blockchain, userAKey, chainID) + var ionContractAddr [20]byte + copy(ionContractAddr[:], ionContractInstance.Address.Bytes()) + contractChan = CompileAndDeployValidation(ctx, blockchain, userAKey, chainID, ionContractAddr) blockchain.Commit() validationContractInstance := <-contractChan var chainIDA [32]byte - var ionAddress, validationAddress [20]byte - copy(ionAddress[:], ionContractInstance.Address.Bytes()) + var validationAddress [20]byte copy(validationAddress[:], validationContractInstance.Address.Bytes()) copy(chainIDA[:], crypto.Keccak256Hash([]byte("TESTCHAINID")).Bytes()) deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") @@ -108,7 +109,6 @@ func Test_RegisterChain(t *testing.T) { validationContractInstance.Contract, validationContractInstance.Address, chainIDA, - ionAddress, testValidators, deployedChainID, ) diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go index 869e494..c334936 100644 --- a/ion-cli/contracts/flow_test.go +++ b/ion-cli/contracts/flow_test.go @@ -90,15 +90,16 @@ func Test_VerifyTx(t *testing.T) { // --------------------------------------------- // COMPILE AND DEPLOY VALIDATION // --------------------------------------------- - contractChan = CompileAndDeployValidation(ctx, blockchain, userKey, deployedChainID) + var ionContractAddr [20]byte + copy(ionContractAddr[:], ionContractInstance.Address.Bytes()) + contractChan = CompileAndDeployValidation(ctx, blockchain, userKey, deployedChainID, ionContractAddr) blockchain.Commit() validationContractInstance := <-contractChan // --------------------------------------------- // REGISTER CHAIN ON VALIDATION // --------------------------------------------- - var ionContractAddr [20]byte - copy(ionContractAddr[:], ionContractInstance.Address.Bytes()) + var genesisHash [32]byte copy(genesisHash[:], block.ParentHash().Bytes()) txRegisterChainValidation := RegisterChain( @@ -108,7 +109,6 @@ func Test_VerifyTx(t *testing.T) { validationContractInstance.Contract, validationContractInstance.Address, testChainID, - ionContractAddr, testValidators, genesisHash, ) diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index 0996bbd..ec55e79 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -19,6 +19,7 @@ func CompileAndDeployValidation( client bind.ContractBackend, userKey *ecdsa.PrivateKey, chainID interface{}, + ionContractAddress common.Address, ) <-chan ContractInstance { // --------------------------------------------- // COMPILE VALIDATION AND DEPENDENCIES @@ -46,6 +47,7 @@ func CompileAndDeployValidation( nil, uint64(3000000), chainID, + ionContractAddress, ) resChan := make(chan ContractInstance) @@ -67,15 +69,14 @@ func CompileAndDeployValidation( return resChan } -// Registers chain with Validation contract specified +// RegisterChain with Validation contract specified func RegisterChain( ctx context.Context, backend bind.ContractBackend, userKey *ecdsa.PrivateKey, contract *compiler.Contract, toAddr common.Address, - chainId common.Hash, - ionAddr common.Address, + chainID common.Hash, validators []common.Address, registerHash common.Hash, ) (tx *types.Transaction) { @@ -88,8 +89,7 @@ func RegisterChain( nil, uint64(3000000), "RegisterChain", - chainId, - ionAddr, + chainID, validators, registerHash, ) @@ -97,14 +97,14 @@ func RegisterChain( return } -// Submits block to Validation contract specified +// SubmitBlock Submits block to Validation contract specified func SubmitBlock( ctx context.Context, backend bind.ContractBackend, userKey *ecdsa.PrivateKey, contract *compiler.Contract, toAddr common.Address, - chainId common.Hash, + chainID common.Hash, unsignedBlockHeaderRLP []byte, signedBlockHeaderRLP []byte, ) (tx *types.Transaction) { @@ -117,21 +117,21 @@ func SubmitBlock( nil, uint64(3000000), "SubmitBlock", - chainId, + chainID, unsignedBlockHeaderRLP, signedBlockHeaderRLP, ) return } -// Queries validation contract to see is block is valid +// ValidBlock Queries validation contract to see is block is valid func ValidBlock( ctx context.Context, backend bind.ContractBackend, contract *compiler.Contract, userAddr common.Address, toAddr common.Address, - chainId common.Hash, + chainID common.Hash, blockHash common.Hash, ) (isBlockValid bool) { methodName := "m_blockhashes" @@ -143,20 +143,20 @@ func ValidBlock( toAddr, methodName, &isBlockValid, - chainId, + chainID, blockHash, ) return } -// Queries validation contract to see is block is valid +// LatestValidBlock Queries validation contract to see is block is valid func LatestValidBlock( ctx context.Context, backend bind.ContractBackend, contract *compiler.Contract, userAddr common.Address, toAddr common.Address, - chainId common.Hash, + chainID common.Hash, ) (latestBlock common.Hash) { methodName := "m_latestblock" CallContract( @@ -167,7 +167,7 @@ func LatestValidBlock( toAddr, methodName, &latestBlock, - chainId, + chainID, ) return } diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json index 9bf0119..bce18c8 100644 --- a/ion-cli/rinkeby.json +++ b/ion-cli/rinkeby.json @@ -3,9 +3,9 @@ "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "password-to":"password1", "keystore-to":"./keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "ion-addr":"0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", + "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", "function-addr":"0x93981af8db02c7ef40d0ed61caef2726a79eb903", - "validation-addr":"0xd6894ba69834b5d0511c50971bc844dff04c2073", + "validation-addr":"0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", "validation-chainid":"0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075", "rpc-from":"https://rinkeby.infura.io", "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 7ff1c25..3733c76 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -5,14 +5,14 @@ const EventFunction = artifacts.require("Function"); const EventVerifier = artifacts.require("TriggerEventVerifier"); module.exports = async (deployer) => { - try { - deployer.deploy(Validation, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") - .then(() => Validation.deployed) - .then(() => deployer.deploy(PatriciaTrie)) + try { + deployer.deploy(PatriciaTrie) .then(() => PatriciaTrie.deployed) .then(() => deployer.link(PatriciaTrie, Ion)) .then(() => deployer.deploy(Ion, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) .then(() => Ion.deployed) + .then(() => deployer.deploy(Validation, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177", Ion.address)) + .then(() => Validation.deployed) .then(() => deployer.deploy(EventVerifier)) .then(() => EventVerifier.deployed) .then(() => deployer.deploy(EventFunction, Ion.address, EventVerifier.address)) diff --git a/test/ion.js b/test/ion.js index 71a1342..351bf12 100644 --- a/test/ion.js +++ b/test/ion.js @@ -160,26 +160,26 @@ contract('Ion.js', (accounts) => { it('Register Chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); let chain = await ion.chains(TESTCHAINID); assert.equal(chain, true); // Fail adding id of this chain - await validation.RegisterChain(DEPLOYEDCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already registered - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; }) it('Check Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); const val = await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -190,9 +190,9 @@ contract('Ion.js', (accounts) => { it('Fail Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -208,9 +208,9 @@ contract('Ion.js', (accounts) => { it('Check Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -222,9 +222,9 @@ contract('Ion.js', (accounts) => { it('Fail Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -240,9 +240,9 @@ contract('Ion.js', (accounts) => { it('Check Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -254,9 +254,9 @@ contract('Ion.js', (accounts) => { it('Fail Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -276,7 +276,7 @@ contract('Ion.js', (accounts) => { it('Deploy Function Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); const verifier = await TriggerEventVerifier.new(); const functionContract = await FunctionEvent.new(ion.address, verifier.address); @@ -284,13 +284,13 @@ contract('Ion.js', (accounts) => { it('Verify Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); const verifier = await TriggerEventVerifier.new(); const functionContract = await FunctionEvent.new(ion.address, verifier.address); // Register chain and submit block to Ion - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); @@ -306,13 +306,13 @@ contract('Ion.js', (accounts) => { it('Fail Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); const verifier = await TriggerEventVerifier.new(); const functionContract = await FunctionEvent.new(ion.address, verifier.address); // Register chain and submit block to Ion - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); diff --git a/test/validation.js b/test/validation.js index 9268a40..c5be0a1 100644 --- a/test/validation.js +++ b/test/validation.js @@ -54,7 +54,8 @@ contract('Validation.js', (accounts) => { const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); it('Deploy Contract', async () => { - const validation = await Validation.new(DEPLOYEDCHAINID); + const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); let chainId = await validation.chainId(); assert.equal(chainId, DEPLOYEDCHAINID); @@ -62,28 +63,28 @@ contract('Validation.js', (accounts) => { it('Register Chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); // Successfully add id of another chain - let tx = await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + let tx = await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); let chain = await validation.chains(TESTCHAINID); assert.equal(chain, true); // Fail adding id of this chain - await validation.RegisterChain(DEPLOYEDCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already initialised - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH).should.be.rejected; + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; }) it('Register Chain - Check Validators', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); let validators = await validation.m_validators.call(TESTCHAINID, VALIDATORS[0]); assert.equal(validators, true); @@ -92,10 +93,10 @@ contract('Validation.js', (accounts) => { it('Register Chain - Check Genesis Hash', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); let header = await validation.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); let blockHeight = header[0]; @@ -106,9 +107,9 @@ contract('Validation.js', (accounts) => { it('Authentic Submission Happy Path - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -183,9 +184,9 @@ contract('Validation.js', (accounts) => { // Here the block header is signed off chain but by a whitelisted validator it('Authentic Submission Off-Chain Signature - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -294,9 +295,9 @@ contract('Validation.js', (accounts) => { // Here the block header is signed off chain but by a whitelisted validator who alters the block it('Inauthentic Block Submission - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -416,9 +417,9 @@ contract('Validation.js', (accounts) => { // Here the block header is signed off chain but by a a non-whitelisted validator it('Fail Submit Block unkown validator - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -513,9 +514,9 @@ contract('Validation.js', (accounts) => { it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -576,9 +577,9 @@ contract('Validation.js', (accounts) => { it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - await validation.RegisterChain(TESTCHAINID, ion.address, VALIDATORS, GENESIS_HASH); + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); From 52633972d2cba6873baf575987e72b47571bb1aa Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 14 Aug 2018 15:17:02 +0100 Subject: [PATCH 132/203] Updated some documentation in the Validation contract --- contracts/Validation.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 8b294b3..a132da7 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -37,6 +37,7 @@ contract Validation { /* * @param _id genesis block of the blockchain where the contract is deployed + * @param _ion address of the Ion hub contract with which this validation contract is connected */ constructor (bytes32 _id, address _ion) public { chainId = _id; @@ -46,7 +47,9 @@ contract Validation { /* * RegisterChain - * param: chainId (bytes32) Unique id of another chain to interoperate with + * param: _id (bytes32) Unique id of another chain to interoperate with + * param: _validators (address[]) Array containing the validators at the genesis block + * param: _genesisHash (bytes32) Hash of the genesis block for the chain being registered with Ion * * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. From 0746646b5c93b279c955d7ca54414c796663e50f Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 14 Aug 2018 17:24:47 +0100 Subject: [PATCH 133/203] Added check for extra data field --- contracts/Validation.sol | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contracts/Validation.sol b/contracts/Validation.sol index a132da7..6ecdbfd 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -34,6 +34,7 @@ contract Validation { event broadcastSignature(address signer); event broadcastHash(bytes32 blockHash); + event broadcastBytes(bytes blockHash); /* * @param _id genesis block of the blockchain where the contract is deployed @@ -91,7 +92,12 @@ contract Validation { for (uint256 i=0; i Date: Thu, 16 Aug 2018 09:41:30 +0100 Subject: [PATCH 134/203] Added new test for the validator proposals --- contracts/Validation.sol | 27 +++- contracts/libraries/SolidityUtils.sol | 22 +++- test/clique.js | 130 +++++++++++++++++++ test/helpers/encoder.js | 122 +++++++++--------- test/helpers/utils.js | 1 - test/validation.js | 172 +++----------------------- 6 files changed, 242 insertions(+), 232 deletions(-) create mode 100644 test/clique.js diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 6ecdbfd..7434d04 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -30,11 +30,13 @@ contract Validation { mapping (bytes32 => bytes32) public m_latestblock; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; + mapping (bytes32 => uint256) public m_threshold; mapping (bytes32 => mapping (address => bool)) public m_validators; + mapping (bytes32 => mapping (address => uint256)) public m_proposals; + event broadcastSignature(address signer); event broadcastHash(bytes32 blockHash); - event broadcastBytes(bytes blockHash); /* * @param _id genesis block of the blockchain where the contract is deployed @@ -60,10 +62,11 @@ contract Validation { require(!chains[_id], "Chain already exists" ); chains[_id] = true; - // Append validators + // Append validators and vote threshold for (uint256 i = 0; i < _validators.length; i++) { m_validators[_id][_validators[i]] = true; } + m_threshold[_id] = (_validators.length/2) + 1; Ion ion = Ion(registeredIon); require(ion.addChain(_id), "Chain not added to Ion successfully!"); @@ -97,8 +100,7 @@ contract Validation { SolUtils.BytesToBytes(extraData, signedHeader[i].toBytes(), 2); SolUtils.BytesToBytes(extraDataSigned, header[i].toBytes(), 1); require(keccak256(extraDataSigned)==keccak256(extraData), "Header data doesn't match!"); - // continue; - } else{ + } else { require(keccak256(header[i].toBytes())==keccak256(signedHeader[i].toBytes()), "Header data doesn't match!"); } } @@ -113,7 +115,8 @@ contract Validation { recoverSignature(_id, signedHeader[12].toBytes(), _rlpBlockHeader); - // Append the new block to the struct + // Append the new block to the struct + addProposal(_id, SolUtils.BytesToAddress(header[2].toBytes(), 1)); addBlockHeaderToChain(_id, _blockHash, _parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint()); addBlockHashToChain(_id, _blockHash); updateBlockHash(_id, _blockHash); @@ -132,6 +135,20 @@ contract Validation { emit broadcastSignature(sigAddr); } + function addProposal(bytes32 _id, address _vote) { + if (_vote!=(0x0)) { + m_proposals[_id][_vote]++; + // Add validator if does not exist else remove + if (m_proposals[_id][_vote]>=m_threshold[_id] && !m_validators[_id][_vote]) { + m_validators[_id][_vote] = true; + m_proposals[_id][_vote] = 0; + } else if (m_proposals[_id][_vote]>=m_threshold[_id] && m_validators[_id][_vote]) { + m_validators[_id][_vote] = false; + m_proposals[_id][_vote] = 0; + } + } + } + /* * @description when a block is submitted the root hash must be added to a mapping of chains to hashes * @param _id unique identifier of the chain from which the block hails diff --git a/contracts/libraries/SolidityUtils.sol b/contracts/libraries/SolidityUtils.sol index 939b0d6..9aa2483 100644 --- a/contracts/libraries/SolidityUtils.sol +++ b/contracts/libraries/SolidityUtils.sol @@ -17,22 +17,34 @@ library SolUtils { } } - /* * @description copies 20 bytes from input into the output * @param output memory allocation for the data you need to extract * @param input array from which the data should be extracted * @param buf index which the data starts within the byte array needs to have 32 bytes appended */ - function BytesToBytes20(bytes b, uint256 buf) internal pure returns (bytes20) { - bytes20 out; + function BytesToBytes20(bytes input, uint256 buf) internal pure returns (bytes20) { + bytes20 output; for (uint i = 0; i < 20; i++) { - out |= bytes20(b[buf + i] & 0xFF) >> (i * 8); + output |= bytes20(input[buf + i] & 0xFF) >> (i * 8); } - return out; + return output; } +/* + * @description copies 20 bytes from input into the output returning an address + * @param output memory allocation for the data you need to extract + * @param input array from which the data should be extracted + * @param buf index which the data starts within the byte array needs to have 32 bytes appended + */ + function BytesToAddress(bytes input, uint256 buf) internal pure returns (address output) { + buf = buf + 20; + assembly { + output := mload(add(input, buf)) + } + } + /* * @description copies output.length bytes from the input into the output * @param output memory allocation for the data you need to extract diff --git a/test/clique.js b/test/clique.js new file mode 100644 index 0000000..e1bc70a --- /dev/null +++ b/test/clique.js @@ -0,0 +1,130 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const eth_util = require('ethereumjs-util'); +const utils = require('./helpers/utils.js'); +const encoder = require('./helpers/encoder.js'); +const Web3 = require('web3'); + +const Validation = artifacts.require("Validation"); +const Ion = artifacts.require("Ion"); + +const web3 = new Web3(); +const rinkeby = new Web3(); + +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); +rinkeby.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); + +// Takes a header and private key returning the signed data +// Needs extraData just to be sure of the final byte +signHeader = (headerHash, privateKey, extraData) => { + const sig = eth_util.ecsign(headerHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = eth_util.pubToAddress(pubKey); + + const newSigBytes = Buffer.concat([sig.r, sig.s]); + let newSig; + + const bytes = utils.hexToBytes(extraData) + const finalByte = bytes.splice(bytes.length-1) + if (finalByte.toString('hex')=="0") { + newSig = newSigBytes.toString('hex') + '00'; + } + if (finalByte.toString('hex')=="1") { + newSig = newSigBytes.toString('hex') + '01'; + } + + return newSig; +} + +const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" +const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" +const VALIDATORS_START = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; +const VALIDATORS_FINISH = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; +const GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; + +contract('Clique.js', (accounts) => { + const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); + + const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); + + // This test checks that new validators get added into the validator list as blocks are submitted to the contract. + // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 + // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. + it('Add Validators Through Block Submission', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + + await validation.RegisterChain(TESTCHAINID, VALIDATORS_START, GENESIS_HASH); + + let voteThreshold = await validation.m_threshold(TESTCHAINID); + assert.equal(voteThreshold, 2); + + let voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Fetch block 873982 from rinkeby + let block = rinkeby.eth.getBlock(873982); + let rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + let validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873982 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873983 from rinkeby + block = rinkeby.eth.getBlock(873983); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873983 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Check proposal is added + voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 1); + + + // Fetch block 873984 from rinkeby + block = rinkeby.eth.getBlock(873984); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873984 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873985 from rinkeby + block = rinkeby.eth.getBlock(873985); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873985 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873986 from rinkeby + block = rinkeby.eth.getBlock(873986); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873986 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Check proposal is added + voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Check all new validators are added + let validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[0]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[2]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[3]); + assert.equal(validators, true); + }) + +}); diff --git a/test/helpers/encoder.js b/test/helpers/encoder.js index 229584c..56abddb 100644 --- a/test/helpers/encoder.js +++ b/test/helpers/encoder.js @@ -1,78 +1,68 @@ // Copyright (c) 2016-2018 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ -const Web3 = require('web3'); const Web3Utils = require('web3-utils'); -const Web3Abi = require('web3-eth-abi'); const rlp = require('rlp'); +const utils = require('./utils.js'); -const web3 = new Web3(); +const encoder = {}; -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); - -function hexToBytes(hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; -} - -function bytesToHex(bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(""); -} +encoder.encodeBlockHeader = (block) => { + const signedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + block.extraData, + block.mixHash, + block.nonce + ]; + // Remove last 65 Bytes of extraData + const extraBytes = utils.hexToBytes(block.extraData); + const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); + const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); + const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); -const block = web3.eth.getBlock(7); -// console.log("\n\n\n\nBlock = " + JSON.stringify(block)) -// Decompose the values in the block to hash -const parentHash = block.parentHash; -const sha3Uncles = block.sha3Uncles; -const coinbase = block.miner; -const root = block.stateRoot; -const txHash = block.transactionsRoot; -const receiptHash = block.receiptsRoot; -const logsBloom = block.logsBloom; -const difficulty = Web3Utils.toBN(block.difficulty); -const number = Web3Utils.toBN(block.number); -const gasLimit = block.gasLimit; -const gasUsed = block.gasUsed; -const timestamp = Web3Utils.toBN(block.timestamp); -const extraData = block.extraData; -const mixHash = block.mixHash; -const nonce = block.nonce; + const unsignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + extraDataShort, // extraData minus the signature + block.mixHash, + block.nonce + ]; -// Remove last 65 Bytes of extraData -const extraBytes = hexToBytes(extraData); -const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); -const extraDataSignature = '0x' + bytesToHex(extraBytes.splice(extraBytes.length-65)); -const extraDataShort = '0x' + bytesToHex(extraBytesShort); + const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); + const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); -const header = [ - parentHash, - sha3Uncles, - coinbase, - root, - txHash, - receiptHash, - logsBloom, - difficulty, - number, - gasLimit, - gasUsed, - timestamp, - extraData, - mixHash, - nonce -]; - -const encodedHeader = rlp.encode(header); - -const headerHash = Web3Utils.sha3(encodedHeader); + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + + return { + unsigned: encodedUnsignedHeader, + signed: encodedSignedHeader, + extraDataSignature: extraDataSignature, + extraDataShort: extraDataShort, + extraBytesShort: extraBytesShort + }; +} -// console.log("\n\n\nRLP-encoded header: " +bytesToHex(encodedHeader)); -// console.log("\n\n\nHashed header: " +headerHash) -// console.log("\n\n\nExpected hash: " +block.hash) -// console.log("\n\n\n" + ((rlp.encode(parentHash)))) \ No newline at end of file +module.exports = encoder; \ No newline at end of file diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 5f742bd..74065a7 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -64,5 +64,4 @@ utils.txGas = txReceipt => txReceipt.receipt.gasUsed * gasPrice utils.txLoggedArgs = txReceipt => txReceipt.logs[0].args utils.txContractId = txReceipt => txLoggedArgs(txReceipt).contractId -// bufToStr, joinHex, newSecretHashPair, oneFinney, random32, randomArr, randomHex, sha256, sleep, txGas, txLoggedArgs} module.exports = utils; \ No newline at end of file diff --git a/test/validation.js b/test/validation.js index c5be0a1..d1787c8 100644 --- a/test/validation.js +++ b/test/validation.js @@ -3,10 +3,9 @@ const eth_util = require('ethereumjs-util'); const utils = require('./helpers/utils.js'); +const encoder = require('./helpers/encoder.js'); const Web3 = require('web3'); const Web3Utils = require('web3-utils'); -const Web3Abi = require('web3-eth-abi'); -const Web3Accounts = require('web3-eth-accounts'); const rlp = require('rlp'); const Validation = artifacts.require("Validation"); @@ -48,7 +47,7 @@ const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; -contract('Validation.js', (accounts) => { +contract.only('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); @@ -102,8 +101,7 @@ contract('Validation.js', (accounts) => { let blockHeight = header[0]; assert.equal(0, blockHeight); -; -}) + }) it('Authentic Submission Happy Path - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); @@ -114,57 +112,13 @@ contract('Validation.js', (accounts) => { // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); - const signedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; - - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); assert.equal(block.hash, signedHeaderHash); - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); - // Submit block should succeed - const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); + // const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); + const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; assert.equal(signedHeaderHash, recoveredBlockHash); console.log("\tGas used to submit block = " + validationReceipt.receipt.gasUsed.toString() + " gas"); @@ -191,58 +145,12 @@ contract('Validation.js', (accounts) => { // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); - const signedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; - - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); - assert.equal(block.hash, signedHeaderHash); - - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); // Encode and sign the new header - const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); - const newSignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); + const encodedExtraData = '0x' + rlp.encode(rlpHeaders.extraDataShort).toString('hex'); + const newSignedHeaderHash = eth_util.sha3(rlpHeaders.unsigned); const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') @@ -250,9 +158,10 @@ contract('Validation.js', (accounts) => { // Append signature to the end of extraData const sigBytes = utils.hexToBytes(signature.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); + // const extraBytesShort = utils.hexToBytes(rlpHeaders.extraDataShort); + const newExtraDataBytes = rlpHeaders.extraBytesShort.concat(sigBytes); const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); - assert.equal(extraDataSignature, '0x'+signature.toString('hex')) + assert.equal(rlpHeaders.extraDataSignature, '0x'+signature.toString('hex')) const newSignedHeader = [ block.parentHash, @@ -276,7 +185,7 @@ contract('Validation.js', (accounts) => { const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); // Submit block should succeed - const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader); + const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, offchainSignedHeader); const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; assert.equal(signedHeaderHash, recoveredBlockHash); @@ -521,57 +430,10 @@ contract('Validation.js', (accounts) => { // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); - const signedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; - - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); - assert.equal(block.hash, signedHeaderHash); - - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + const rlpHeaders = encoder.encodeBlockHeader(block); // Submit block should succeed - await validation.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", encodedUnsignedHeader, encodedSignedHeader).should.be.rejected; + await validation.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", rlpHeaders.unsigned, rlpHeaders.signed).should.be.rejected; }) From 1905547d93a4504ebbd94c18306fc02a4c847d13 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 10:23:32 +0100 Subject: [PATCH 135/203] removed .only that was stopping most tests from running --- test/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/validation.js b/test/validation.js index d1787c8..bc276a3 100644 --- a/test/validation.js +++ b/test/validation.js @@ -47,7 +47,7 @@ const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; -contract.only('Validation.js', (accounts) => { +contract('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); From 1153092bb92dc092262605f99f290646d9ba674f Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 10:45:39 +0100 Subject: [PATCH 136/203] Added go dep to the travis file to ensure correct geth is being used --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6bbdf7a..ebb8db0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,8 @@ matrix: - npm run depclique - npm run test - cd ./ion-cli - - go get -t ./... + - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh + - dep ensure - make build - make test From 77d1c0b8161b48f0a9a1d90f336726fb75c3851f Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 11:01:27 +0100 Subject: [PATCH 137/203] Fixing traviss yaml --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ebb8db0..2aa8c6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,14 +17,15 @@ matrix: dist: trusty go: 1.9.x script: - - npm install - - npm run depclique - - npm run test - cd ./ion-cli + - go get github.com/ethereum/go-ethereum - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - dep ensure - make build - make test + - cd .. + - npm install + - npm run test notifications: slack: From 9dc2a75d9096fd03cadb01395da7bfb7e6bc7583 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 11:33:01 +0100 Subject: [PATCH 138/203] Attempted fix of the include failues for go-ethereum and trying to run tests in parallel --- .travis.yml | 34 ++++++++++++++------- ion-cli/Gopkg.lock | 76 +++++++++++++++++++++------------------------- ion-cli/Gopkg.toml | 8 ++--- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2aa8c6d..11b7aa7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,29 +3,41 @@ language: go services: - docker -before_install: - - sudo add-apt-repository ppa:ethereum/ethereum -y - - sudo apt-get update - - sudo apt-get install solc -y - - docker build . -t node - - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash - - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh - matrix: include: - os: linux dist: trusty + + - name: "Javascript Contract Tests" + script: + - npm install + - npm run test + + before_install: + - docker build . -t node + - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash + - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh + + - name: "Golang Ion-CLI Tests" go: 1.9.x script: - cd ./ion-cli - go get github.com/ethereum/go-ethereum + - cp -r "${GOPATH}/src/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1" "vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/" - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - dep ensure - make build - make test - - cd .. - - npm install - - npm run test + + before_install: + - sudo add-apt-repository ppa:ethereum/ethereum -y + - sudo apt-get update + - sudo apt-get install solc -y + - docker build . -t node + - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash + - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh + + notifications: slack: diff --git a/ion-cli/Gopkg.lock b/ion-cli/Gopkg.lock index 773aa19..3b3c507 100644 --- a/ion-cli/Gopkg.lock +++ b/ion-cli/Gopkg.lock @@ -14,16 +14,14 @@ revision = "155bce2042db95a783081fab225e74dd879055b0" [[projects]] - branch = "master" name = "github.com/aristanetworks/goarista" packages = ["monotime"] - revision = "3e95f038af02770089c3988f48f9e1a6b6fe2ac5" + revision = "ea17b1a17847fb6e4c0a91de0b674704693469b0" [[projects]] - branch = "master" name = "github.com/btcsuite/btcd" packages = ["btcec"] - revision = "9a2f9524024889e129a5422aca2cff73cb3eabf6" + revision = "2e60448ffcc6bf78332d1fe590260095f554dd78" [[projects]] name = "github.com/davecgh/go-spew" @@ -33,9 +31,14 @@ [[projects]] branch = "master" + name = "github.com/deckarep/golang-set" + packages = ["."] + revision = "504e848d77ea4752b3057b8fb46da0e7f746ccf3" + +[[projects]] name = "github.com/edsrzf/mmap-go" packages = ["."] - revision = "0bce6a6887123b67a60366d2c9fe2dfb74289d2e" + revision = "935e0e8a636ca4ba70b713f3e38a19e1b77739e8" [[projects]] name = "github.com/ethereum/go-ethereum" @@ -48,6 +51,7 @@ "accounts/keystore", "common", "common/bitutil", + "common/compiler", "common/hexutil", "common/math", "common/mclock", @@ -64,7 +68,6 @@ "crypto/bn256", "crypto/bn256/cloudflare", "crypto/bn256/google", - "crypto/randentropy", "crypto/secp256k1", "crypto/sha3", "eth/filters", @@ -79,8 +82,8 @@ "rpc", "trie" ] - revision = "37685930d953bcbe023f9bc65b135a8d8b8f1488" - version = "v1.8.12" + revision = "225171a4bfcc16bd12a1906b1e0d43d0b18c353b" + version = "v1.8.13" [[projects]] name = "github.com/fatih/color" @@ -97,8 +100,8 @@ [[projects]] name = "github.com/go-stack/stack" packages = ["."] - revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" - version = "v1.7.0" + revision = "54be5f394ed2c3e19dac9134a40a95ba5a017f7b" + version = "v1.5.4" [[projects]] branch = "master" @@ -107,13 +110,12 @@ revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" [[projects]] - branch = "master" name = "github.com/hashicorp/golang-lru" packages = [ ".", "simplelru" ] - revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3" + revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6" [[projects]] name = "github.com/mattn/go-colorable" @@ -127,17 +129,10 @@ revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" version = "v0.0.3" -[[projects]] - name = "github.com/maxrobot/go-ethereum" - packages = ["crypto"] - revision = "dea1ce052a10cd7d401a5c04f83f371a06fe293c" - version = "v1.8.11" - [[projects]] name = "github.com/pborman/uuid" packages = ["."] - revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53" - version = "v1.1" + revision = "1b00554d822231195d1babd97ff4a781231955c9" [[projects]] name = "github.com/pmezard/go-difflib" @@ -148,14 +143,19 @@ [[projects]] name = "github.com/rjeczalik/notify" packages = ["."] - revision = "52ae50d8490436622a8941bd70c3dbe0acdd4bbf" - version = "v0.9.0" + revision = "c31e5f2cb22b3e4ef3f882f413847669bf2652b9" [[projects]] name = "github.com/rs/cors" packages = ["."] - revision = "3fb1b69b103a84de38a19c3c6ec073dd6caa4d3f" - version = "v1.5.0" + revision = "a62a804a8a009876ca59105f7899938a1349f4b3" + version = "v1.0" + +[[projects]] + name = "github.com/rs/xhandler" + packages = ["."] + revision = "d9d9599b6aaf6a058cb7b1f48291ded2cbd13390" + version = "v1.0" [[projects]] name = "github.com/stretchr/testify" @@ -164,7 +164,6 @@ version = "v1.2.2" [[projects]] - branch = "master" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -183,42 +182,35 @@ revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445" [[projects]] - branch = "master" name = "golang.org/x/crypto" packages = [ "pbkdf2", "ripemd160", "scrypt" ] - revision = "c126467f60eb25f8f27e5a981f32a87e3965053f" + revision = "6a293f2d4b14b8e6d3f0539e383f6d0d30fce3fd" [[projects]] - branch = "master" name = "golang.org/x/net" - packages = ["websocket"] - revision = "c4299a1a0d8524c11563db160fbf9bddbceadb21" + packages = [ + "context", + "websocket" + ] + revision = "a6577fac2d73be281a500b310739095313165611" [[projects]] branch = "master" name = "golang.org/x/sys" packages = ["unix"] - revision = "bd9dbc187b6e1dacfdd2722a87e83093c2d7bd6e" + revision = "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded" [[projects]] - branch = "master" name = "golang.org/x/tools" packages = [ "go/ast/astutil", - "imports", - "internal/fastwalk" + "imports" ] - revision = "8cc4e8a6f4841aa92a8683fca47bc5d64b58875b" - -[[projects]] - name = "gopkg.in/fatih/set.v0" - packages = ["."] - revision = "57907de300222151a123d29255ed17f5ed43fad3" - version = "v0.1.0" + revision = "be0fcc31ae2332374e800dfff29b721c585b35df" [[projects]] branch = "v2" @@ -235,6 +227,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "805e01dd280107fbb7b37497eab1b47175b241c1a5b253db91a375d83d208ae5" + inputs-digest = "61e6c38a8fde2002db259f4cefff56c1602f61842d325ec011613477dd20a819" solver-name = "gps-cdcl" solver-version = 1 diff --git a/ion-cli/Gopkg.toml b/ion-cli/Gopkg.toml index d511c01..abffbd1 100644 --- a/ion-cli/Gopkg.toml +++ b/ion-cli/Gopkg.toml @@ -1,6 +1,6 @@ # Gopkg.toml example # -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html # for detailed Gopkg.toml documentation. # # required = ["github.com/user/thing/cmd/thing"] @@ -31,11 +31,7 @@ [[constraint]] name = "github.com/ethereum/go-ethereum" - version = "1.8.12" - -[[constraint]] - name = "github.com/maxrobot/go-ethereum" - version = "1.8.11" + version = "1.8.13" [[constraint]] name = "github.com/stretchr/testify" From a3837b3d963fdd8b8e7c3d8050f1a318e1607f60 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 11:39:32 +0100 Subject: [PATCH 139/203] Dependency check was in wrong order fixed --- .travis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 11b7aa7..fe6db3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,3 @@ -language: go - services: - docker @@ -23,9 +21,9 @@ matrix: script: - cd ./ion-cli - go get github.com/ethereum/go-ethereum - - cp -r "${GOPATH}/src/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1" "vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/" - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - dep ensure + - cp -r "${GOPATH}/src/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1" "vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/" - make build - make test @@ -33,9 +31,6 @@ matrix: - sudo add-apt-repository ppa:ethereum/ethereum -y - sudo apt-get update - sudo apt-get install solc -y - - docker build . -t node - - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash - - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh From 8c21ddcbb05d3a24d519479472199534f1eccb24 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 11:45:21 +0100 Subject: [PATCH 140/203] test --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe6db3d..53acabf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ -services: - - docker - matrix: include: - os: linux dist: trusty - name: "Javascript Contract Tests" + services: + - docker + script: - npm install - npm run test @@ -20,8 +20,8 @@ matrix: go: 1.9.x script: - cd ./ion-cli - - go get github.com/ethereum/go-ethereum - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh + - go get github.com/ethereum/go-ethereum - dep ensure - cp -r "${GOPATH}/src/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1" "vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/" - make build From 9175811cd77497b49be943b8c4a49775f0eea137 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 13:37:44 +0100 Subject: [PATCH 141/203] Testing parallel testinf --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 53acabf..fec4084 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ +os: linux +dist: trusty + matrix: include: - - os: linux - dist: trusty - - name: "Javascript Contract Tests" services: - docker @@ -20,8 +20,8 @@ matrix: go: 1.9.x script: - cd ./ion-cli - - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - go get github.com/ethereum/go-ethereum + - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - dep ensure - cp -r "${GOPATH}/src/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1" "vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/" - make build From f0c7217dac2998f73d3157bb66a9fba0e9d410c1 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 16 Aug 2018 13:43:31 +0100 Subject: [PATCH 142/203] try try again --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index fec4084..b0bd376 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ matrix: - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh - name: "Golang Ion-CLI Tests" + language: go go: 1.9.x script: - cd ./ion-cli From bb41570577fe47affb042d3484cec066e087c1ed Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Mon, 20 Aug 2018 13:36:52 +0100 Subject: [PATCH 143/203] Cleanup --- contracts/Ion.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 5ff9c1a..5144e12 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -16,16 +16,16 @@ contract Ion { bytes32[] public registeredChains; /* - * @description persists the last submitted block of a chain being validated + * @description BlockHeader struct containing trie root hashes for tx verifications */ - struct BlockHeader { - bytes32 txRootHash; - bytes32 receiptRootHash; - } + struct BlockHeader { + bytes32 txRootHash; + bytes32 receiptRootHash; + } mapping (bytes32 => bool) public chains; mapping (bytes32 => bool) public m_blockhashes; - mapping (bytes32 => BlockHeader) public m_blockheaders; + mapping (bytes32 => BlockHeader) public m_blockheaders; @@ -41,12 +41,12 @@ contract Ion { chainId = _id; } - enum ProofType { TX, RECEIPT, ROOTS } event VerifiedProof(bytes32 chainId, bytes32 blockHash, uint proofType); event broadcastSignature(address signer); - event broadcastHash(bytes32 blockHash); + event broadcastHash(bytes32 blockHash); + /* ======================================================================================================================== From 4a434f62c392d93663c1e20fa17b1ac139d1cddb Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 24 Aug 2018 11:47:00 +0100 Subject: [PATCH 144/203] Extracting the validators from the extra data field of block 0 --- contracts/Ion.sol | 5 +- ion-cli/main.go | 8 -- test/helpers/encoder.js | 23 +++++ test/validation.js | 200 ++-------------------------------------- 4 files changed, 31 insertions(+), 205 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 5ff9c1a..cbd73bc 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -88,10 +88,7 @@ contract Ion { /* * addChain - * param: chainId Unique id of another chain to interoperate with - * param: validationAddr Address of the validation contract required to make modular validation - * param: _validators List of validators on the block chain - * param: _genesisHash Genesis blockhash of the interop block chain + * param: id Unique id of another chain to interoperate with * * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. diff --git a/ion-cli/main.go b/ion-cli/main.go index 4ece45e..9bd57d4 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -3,10 +3,8 @@ package main import ( - "encoding/json" "flag" "fmt" - "log" "os" "github.com/clearmatics/ion/ion-cli/cli" @@ -29,12 +27,6 @@ func main() { // Compile contracts to use in sending transactions Validation := contract.CompileContract("Validation") Function := contract.CompileContract("Function") - functionAbiStr, err := json.Marshal(Function.Info.AbiDefinition) - if err != nil { - log.Fatal("ERROR marshalling abi to string", err) - } - - fmt.Printf("Function: %s\n", functionAbiStr) Trigger := contract.CompileContract("Trigger") printInfo(setup) diff --git a/test/helpers/encoder.js b/test/helpers/encoder.js index 56abddb..c95d031 100644 --- a/test/helpers/encoder.js +++ b/test/helpers/encoder.js @@ -7,6 +7,7 @@ const utils = require('./utils.js'); const encoder = {}; +// encoder.encodeBlockHeader = (block) => { const signedHeader = [ block.parentHash, @@ -65,4 +66,26 @@ encoder.encodeBlockHeader = (block) => { }; } +// Takes the extraData field from a clique genesis block and finds the validators +encoder.extractValidators = (extraData) => { + genesisExtraData = utils.hexToBytes(extraData) + + // Remove dressin, 32 bytes pre validators, 65 bytes post validators, and extra byte for 0x + extraDataValidators = genesisExtraData.splice(33, genesisExtraData.length-32-65-1) + + // Check that the validators length is factor of 20 + assert.equal(extraDataValidators.length%20, 0); + numValidators = extraDataValidators.length / 20; + + let validators = []; + + // Append each new validator to the array + for (i = 0; i < numValidators; ++i) { + validator = extraDataValidators.splice(0, 20); + validators.push('0x' + utils.bytesToHex(validator)); + } + + return validators; +} + module.exports = encoder; \ No newline at end of file diff --git a/test/validation.js b/test/validation.js index bc276a3..753ae6b 100644 --- a/test/validation.js +++ b/test/validation.js @@ -43,15 +43,17 @@ signHeader = (headerHash, privateKey, extraData) => { const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" -const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; -const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; - contract('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); + // Fetch genesis from testrpc + const genesisBlock = web3.eth.getBlock(0); + const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + const GENESIS_HASH = genesisBlock.hash; + it('Deploy Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); @@ -106,7 +108,7 @@ contract('Validation.js', (accounts) => { it('Authentic Submission Happy Path - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc @@ -117,7 +119,6 @@ contract('Validation.js', (accounts) => { assert.equal(block.hash, signedHeaderHash); // Submit block should succeed - // const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; assert.equal(signedHeaderHash, recoveredBlockHash); @@ -135,194 +136,6 @@ contract('Validation.js', (accounts) => { assert.equal(parentHash, block.parentHash); }) - // Here the block header is signed off chain but by a whitelisted validator - it('Authentic Submission Off-Chain Signature - SubmitBlock()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - const rlpHeaders = encoder.encodeBlockHeader(block); - const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); - - // Encode and sign the new header - const encodedExtraData = '0x' + rlp.encode(rlpHeaders.extraDataShort).toString('hex'); - const newSignedHeaderHash = eth_util.sha3(rlpHeaders.unsigned); - - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - - let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); - - // Append signature to the end of extraData - const sigBytes = utils.hexToBytes(signature.toString('hex')); - // const extraBytesShort = utils.hexToBytes(rlpHeaders.extraDataShort); - const newExtraDataBytes = rlpHeaders.extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); - assert.equal(rlpHeaders.extraDataSignature, '0x'+signature.toString('hex')) - - const newSignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - newExtraData, // Off-chain signed block - block.mixHash, - block.nonce - ]; - - // Encode the offchain signed header - const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); - - // Submit block should succeed - const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, offchainSignedHeader); - const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; - assert.equal(signedHeaderHash, recoveredBlockHash); - - let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); - assert.equal(blockHash, true); - - let header = await validation.m_blockheaders(TESTCHAINID, block.hash); - - // Separate fetched header info - parentHash = header[2]; - - // Assert that block was persisted correctly - assert.equal(parentHash, block.parentHash); - }) - - // Here the block header is signed off chain but by a whitelisted validator who alters the block - it('Inauthentic Block Submission - SubmitBlock()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - // Alter txHash - const newTxHash = Web3Utils.sha3("Test Data"); - const signedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - newTxHash, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - newTxHash, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; - - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); - - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); - - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - - const sig = eth_util.ecsign(unsignedHeaderHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = eth_util.ecrecover(unsignedHeaderHash, sig.v, sig.r, sig.s); - const addrBuf = eth_util.pubToAddress(pubKey); - assert.equal(VALIDATORS[0], '0x'+addrBuf.toString('hex')); - - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig; - - // Need to understand why but signature requires different v than in others to recover correctly - if (sig.v=="27") { - newSig = newSigBytes.toString('hex') + '00'; - } - if (sig.v=="28") { - newSig = newSigBytes.toString('hex') + '01'; - } - - // let signature = await signHeader(unsignedHeaderHash, privateKey, block.extraData); - - // Append signature to the end of extraData - const sigBytes = utils.hexToBytes(newSig.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); - - const newSignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - newTxHash, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - newExtraData, // Off-chain signed block - block.mixHash, - block.nonce - ]; - - // Encode the offchain signed header - const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); - const offchainHeaderHash = Web3Utils.sha3(offchainSignedHeader); - - // Submit block should succeed - const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader); - const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; - // console.log(validationReceipt.logs[1].args['signer']); - assert.equal(offchainHeaderHash, recoveredBlockHash); - - let blockHash = await validation.m_blockhashes(TESTCHAINID, offchainHeaderHash); - assert.equal(blockHash, true); - - }) - // Here the block header is signed off chain but by a a non-whitelisted validator it('Fail Submit Block unkown validator - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); @@ -448,6 +261,7 @@ contract('Validation.js', (accounts) => { const signedHeader = [ block.parentHash, +// web3.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); block.sha3Uncles, block.miner, block.stateRoot, From 49b9c074ec93f33d221180e6f586f2462d5fbacd Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 24 Aug 2018 11:59:00 +0100 Subject: [PATCH 145/203] Altered the README to be generic now it no longer matter what the sealer is on the Clique test chain --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 64bab2e..d56e6d5 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,7 @@ Which hopefully returns this: ### Testing Contracts In order to test the Solidity contracts using the Javascript tests a testrpc must be run. As the validation contract relies upon receiving signatures in the `extraData` field of the block header it is not sufficient to run an instance of ganache-cli, rather a Clique PoA chain must be initialised. -To use the tests please follow the instructions on how to run a single validator Clique chain given [here](https://github.com/maxrobot/network-geth). Additionally you must ensure that the account sealing blocks is identical to that defined in the `validation.js` test itself `0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d`. - -Having launched a single-validator clique chain with the sealer `0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d`, run the tests as follows. +Having launched a Clique PoA chain, hosted on `127.0.0.1:8501`, run the tests as follows: ``` $ npm install $ npm run test From c4b414d7cd4fe93d4cfa8c9351f2b932f179cee5 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Mon, 24 Sep 2018 14:22:21 +0100 Subject: [PATCH 146/203] added small reminder --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d56e6d5..2fefab0 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Which hopefully returns this: ### Testing Contracts In order to test the Solidity contracts using the Javascript tests a testrpc must be run. As the validation contract relies upon receiving signatures in the `extraData` field of the block header it is not sufficient to run an instance of ganache-cli, rather a Clique PoA chain must be initialised. -Having launched a Clique PoA chain, hosted on `127.0.0.1:8501`, run the tests as follows: +Having launched a Clique PoA chain, hosted on `127.0.0.1:8501` (the first account on the `eth.accounts` array should be unlocked in the node), run the tests as follows: ``` $ npm install $ npm run test @@ -326,4 +326,4 @@ Attach to the geth client of the RPC TO chain and run: transactionIndex: 0 } ``` -`status: "0x1"` shows the transaction executed successfully! \ No newline at end of file +`status: "0x1"` shows the transaction executed successfully! From 8b23452bc0ff97433931277aa4de1710dbf1a919 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 24 Sep 2018 14:51:46 +0100 Subject: [PATCH 147/203] Added a few additional tests to clique --- contracts/Ion.sol | 22 +--- contracts/Validation.sol | 78 +++++++++--- test/clique.js | 107 +++++++++++++++- test/helpers/encoder.js | 39 ++++++ test/ion.js | 1 - test/validation.js | 268 +++++++++++---------------------------- 6 files changed, 290 insertions(+), 225 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 5ff9c1a..dc902ac 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -88,10 +88,7 @@ contract Ion { /* * addChain - * param: chainId Unique id of another chain to interoperate with - * param: validationAddr Address of the validation contract required to make modular validation - * param: _validators List of validators on the block chain - * param: _genesisHash Genesis blockhash of the interop block chain + * param: id Unique id of another chain to interoperate with * * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. @@ -155,7 +152,7 @@ contract Ion { * blockHash: (bytes32) hash of the block verifying proof against * proofType: (uint) enum of proof type * - * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution + * All data associated with the proof must be constructed and paddChainrovided to this function. Modifiers restrict execution * of this function to only allow if the chain the proof is for is registered to this contract and if the block that * the proof is for has been submitted. */ @@ -220,20 +217,13 @@ contract Ion { } /* - * @description when a block is submitted the root hash must be added to a mapping of chains to hashes - * @param _hash root hash of the block being added - */ - function addBlockHash(bytes32 _hash) public { - m_blockhashes[_hash] = true; - } - -/* - * @description when a block is submitted the header must be added to a mapping of chains to blockheaders + * @description when a block is submitted the header must be added to a mapping of blockhashes and chains to blockheaders * @param _hash root hash of the block being added * @param _txRootHash transaction root hash of the block being added * @param _receiptRootHash receipt root hash of the block being added */ - function addBlockHeader(bytes32 _hash, bytes32 _txRootHash, bytes32 _receiptRootHash) public { + function addBlock(bytes32 _hash, bytes32 _txRootHash, bytes32 _receiptRootHash) public { + m_blockhashes[_hash] = true; m_blockheaders[_hash].txRootHash = _txRootHash; m_blockheaders[_hash].receiptRootHash = _receiptRootHash; } @@ -252,7 +242,7 @@ contract Ion { * @param _rlpNodes RLP encoded trie * @returns root hash */ - function getRootNodeHash(bytes _rlpNodes) private view returns (bytes32) { + function getRootNodeHash(bytes _rlpNodes) private returns (bytes32) { RLP.RLPItem memory nodes = RLP.toRLPItem(_rlpNodes); RLP.RLPItem[] memory nodeList = RLP.toList(nodes); diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 7434d04..b07b2c5 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -37,6 +37,7 @@ contract Validation { event broadcastSignature(address signer); event broadcastHash(bytes32 blockHash); + event test(bytes unsigned, bytes signed); /* * @param _id genesis block of the blockchain where the contract is deployed @@ -78,8 +79,56 @@ contract Validation { } + /* + * SubmitBlocks + * param: _id (bytes32) Unique id of chain submitting block from + * param: _rlpBlockHeader (bytes) Concatenation of multiple RLP-encoded byte arrays of block headers from other chain without the signature in extraData + * param: _rlpSignedBlockHeader (bytes) Concatenation of multiple RLP-encoded byte arrays of block headers from other chain with the signature in extraData + * param: _unsignedIndices (uint256[]) Array containing the indices at which each individual block begins at in the unsigned header concatenation + * param: _signedIndices (uint256[]) Array containing the indices at which each individual block begins at in the signed header concatenation + * + * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered + * and if valid the block is persisted as BlockHeader structs defined above. + */ + function SubmitBlocks( + bytes32 _id, + bytes _rlpUnsignedBlockHeaders, + bytes _rlpSignedBlockHeaders, + uint256[] _unsignedIndices, + uint256[] _signedIndices + ) public { + // Loop over each header contained in the bytes arrays and submit to block accordingly + for (uint i=0; i<_signedIndices.length; ++i ) { + uint256 signedSize; + uint256 unsignedSize; + + // Find the length in bytes of each encoded header + if (i==0) { + signedSize = _signedIndices[0]; + unsignedSize = _unsignedIndices[0]; + } else { + signedSize = _signedIndices[i] - _signedIndices[i-1]; + unsignedSize = _unsignedIndices[i] - _unsignedIndices[i-1]; + } + + bytes memory signedHeader = new bytes(signedSize); + bytes memory unsignedHeader = new bytes(unsignedSize); + + if (i==0) { + SolUtils.BytesToBytes(signedHeader, _rlpSignedBlockHeaders, 0); + SolUtils.BytesToBytes(unsignedHeader, _rlpUnsignedBlockHeaders, 0); + } else { + SolUtils.BytesToBytes(signedHeader, _rlpSignedBlockHeaders, _signedIndices[i-1]); + SolUtils.BytesToBytes(unsignedHeader, _rlpUnsignedBlockHeaders, _unsignedIndices[i-1]); + } + + // Submit block to the validation + SubmitBlock(_id, unsignedHeader, signedHeader); + } + } + /* - * ValidateBlock + * SubmitBlock * param: _id (bytes32) Unique id of chain submitting block from * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain without the signature in extraData * param: _rlpSignedBlockHeader (bytes) RLP-encoded byte array of the block header from other chain with the signature in extraData @@ -117,8 +166,7 @@ contract Validation { // Append the new block to the struct addProposal(_id, SolUtils.BytesToAddress(header[2].toBytes(), 1)); - addBlockHeaderToChain(_id, _blockHash, _parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint()); - addBlockHashToChain(_id, _blockHash); + addBlockToChain(_id, _blockHash, _parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint()); updateBlockHash(_id, _blockHash); } @@ -135,7 +183,7 @@ contract Validation { emit broadcastSignature(sigAddr); } - function addProposal(bytes32 _id, address _vote) { + function addProposal(bytes32 _id, address _vote) internal { if (_vote!=(0x0)) { m_proposals[_id][_vote]++; // Add validator if does not exist else remove @@ -154,7 +202,15 @@ contract Validation { * @param _id unique identifier of the chain from which the block hails * @param _hash root hash of the block being added */ - function addBlockHeaderToChain(bytes32 _id, bytes32 _hash, bytes32 _parentHash, bytes32 _txRootHash, bytes32 _receiptRootHash, uint256 _height) internal { + function addBlockToChain( + bytes32 _id, + bytes32 _hash, + bytes32 _parentHash, + bytes32 _txRootHash, + bytes32 _receiptRootHash, + uint256 _height + ) internal { + m_blockhashes[_id][_hash] = true; // Append the new block to the struct m_blockheaders[_id][_hash].blockHeight = _height; m_blockheaders[_id][_hash].latestHash = _hash; @@ -164,18 +220,8 @@ contract Validation { // Add block to Ion Ion ion = Ion(registeredIon); - ion.addBlockHeader(_hash, _txRootHash, _receiptRootHash); - ion.addBlockHash(_hash); - - } + ion.addBlock(_hash, _txRootHash, _receiptRootHash); - /* - * @description when a block is submitted the root hash must be added to a mapping of chains to hashes - * @param _id unique identifier of the chain from which the block hails - * @param _hash root hash of the block being added - */ - function addBlockHashToChain(bytes32 _id, bytes32 _hash) internal { - m_blockhashes[_id][_hash] = true; } /* diff --git a/test/clique.js b/test/clique.js index e1bc70a..675598a 100644 --- a/test/clique.js +++ b/test/clique.js @@ -47,6 +47,10 @@ const VALIDATORS_START = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc5 const VALIDATORS_FINISH = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; const GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; +require('chai') + .use(require('chai-as-promised')) + .should(); + contract('Clique.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); @@ -55,7 +59,7 @@ contract('Clique.js', (accounts) => { // This test checks that new validators get added into the validator list as blocks are submitted to the contract. // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. - it('Add Validators Through Block Submission', async () => { + it('Add Validators Through Individual Block Submission', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); @@ -127,4 +131,105 @@ contract('Clique.js', (accounts) => { assert.equal(validators, true); }) + // This test checks that new validators get added into the validator list as blocks are submitted to the contract. + // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 + // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. + it('Add Validators Through Simultaneous Block Submission', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + + // Generate the arrays which will store the block header and indices + let signedHeaders = []; + let signedHeaderIndices = []; + let unsignedHeaders = []; + let unsignedHeaderIndices = []; + + await validation.RegisterChain(TESTCHAINID, VALIDATORS_START, GENESIS_HASH); + + let voteThreshold = await validation.m_threshold(TESTCHAINID); + assert.equal(voteThreshold, 2); + + let voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Fetch block 873982 from rinkeby + let block = rinkeby.eth.getBlock(873982); + let rlpHeaders = encoder.encodeBlockHeader(block); + encoder.appendBlockHeaders( + signedHeaders, + signedHeaderIndices, + unsignedHeaders, + unsignedHeaderIndices, + rlpHeaders, + ); + + // Fetch block 873983 from rinkeby + block = rinkeby.eth.getBlock(873983); + rlpHeaders = encoder.encodeBlockHeader(block); + encoder.appendBlockHeaders( + signedHeaders, + signedHeaderIndices, + unsignedHeaders, + unsignedHeaderIndices, + rlpHeaders, + ); + + // Fetch block 873984 from rinkeby + block = rinkeby.eth.getBlock(873984); + rlpHeaders = encoder.encodeBlockHeader(block); + encoder.appendBlockHeaders( + signedHeaders, + signedHeaderIndices, + unsignedHeaders, + unsignedHeaderIndices, + rlpHeaders, + ); + + // Fetch block 873985 from rinkeby + block = rinkeby.eth.getBlock(873985); + rlpHeaders = encoder.encodeBlockHeader(block); + encoder.appendBlockHeaders( + signedHeaders, + signedHeaderIndices, + unsignedHeaders, + unsignedHeaderIndices, + rlpHeaders, + ); + + // Fetch block 873986 from rinkeby + block = rinkeby.eth.getBlock(873986); + rlpHeaders = encoder.encodeBlockHeader(block); + encoder.appendBlockHeaders( + signedHeaders, + signedHeaderIndices, + unsignedHeaders, + unsignedHeaderIndices, + rlpHeaders, + ); + + // Submit block should succeed + let joinedSignedBlocks = utils.joinHex(signedHeaders); + let joinedUnsignedBlocks = utils.joinHex(unsignedHeaders); + + // Submit multiple blocks at the same time + const validationReceipt = await validation.SubmitBlocks( + TESTCHAINID, + joinedUnsignedBlocks, + joinedSignedBlocks, + unsignedHeaderIndices, + signedHeaderIndices, + ); + console.log("\tGas used to simultaneously submit blocks (873982-873986) = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Check all new validators are added + let validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[0]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[2]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[3]); + assert.equal(validators, true); + }) + }); diff --git a/test/helpers/encoder.js b/test/helpers/encoder.js index 56abddb..930169d 100644 --- a/test/helpers/encoder.js +++ b/test/helpers/encoder.js @@ -7,6 +7,7 @@ const utils = require('./utils.js'); const encoder = {}; +// Encodes the block headers from clique returning the signed and unsigned instances encoder.encodeBlockHeader = (block) => { const signedHeader = [ block.parentHash, @@ -65,4 +66,42 @@ encoder.encodeBlockHeader = (block) => { }; } +// Takes the extraData field from a clique genesis block and finds the validators +encoder.extractValidators = (extraData) => { + genesisExtraData = utils.hexToBytes(extraData) + + // Remove dressin, 32 bytes pre validators, 65 bytes post validators, and extra byte for 0x + extraDataValidators = genesisExtraData.splice(33, genesisExtraData.length-32-65-1) + + // Check that the validators length is factor of 20 + assert.equal(extraDataValidators.length%20, 0); + numValidators = extraDataValidators.length / 20; + + let validators = []; + + // Append each new validator to the array + for (i = 0; i < numValidators; ++i) { + validator = extraDataValidators.splice(0, 20); + validators.push('0x' + utils.bytesToHex(validator)); + } + + return validators; +} + +encoder.appendBlockHeaders = (signedHeaders, signedHeaderIndices, unsignedHeaders, unsignedHeaderIndices, rlpHeaders) => { + // Start creating the long list of block headers + signedHeaders.push(rlpHeaders.signed); + unsignedHeaders.push(rlpHeaders.unsigned); + + // Need to append the cumulative length + if (signedHeaderIndices.length==0) { + signedHeaderIndices.push(utils.hexToBytes(rlpHeaders.signed).splice(1).length); + unsignedHeaderIndices.push(utils.hexToBytes(rlpHeaders.unsigned).splice(1).length); + } else { + signedHeaderIndices.push(utils.hexToBytes(rlpHeaders.signed).splice(1).length + signedHeaderIndices[signedHeaderIndices.length - 1]); + unsignedHeaderIndices.push(utils.hexToBytes(rlpHeaders.unsigned).splice(1).length + unsignedHeaderIndices[unsignedHeaderIndices.length - 1]); + } + +} + module.exports = encoder; \ No newline at end of file diff --git a/test/ion.js b/test/ion.js index 351bf12..de2e384 100644 --- a/test/ion.js +++ b/test/ion.js @@ -301,7 +301,6 @@ contract('Ion.js', (accounts) => { console.log("\tGas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); - }) it('Fail Function Execution', async () => { diff --git a/test/validation.js b/test/validation.js index bc276a3..e816203 100644 --- a/test/validation.js +++ b/test/validation.js @@ -15,6 +15,10 @@ const web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); +require('chai') + .use(require('chai-as-promised')) + .should(); + // Takes a header and private key returning the signed data // Needs extraData just to be sure of the final byte signHeader = (headerHash, privateKey, extraData) => { @@ -43,15 +47,17 @@ signHeader = (headerHash, privateKey, extraData) => { const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" -const VALIDATORS = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d"]; -const GENESIS_HASH = "0xaf0d377824ecc16cfdd5946ad0cd0da904cbcfff8c6cd31628c9c9e5bed2c95b"; - contract('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); + // Fetch genesis from testrpc + const genesisBlock = web3.eth.getBlock(0); + const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + const GENESIS_HASH = genesisBlock.hash; + it('Deploy Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); @@ -102,11 +108,11 @@ contract('Validation.js', (accounts) => { assert.equal(0, blockHeight); }) - + it('Authentic Submission Happy Path - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc @@ -117,7 +123,6 @@ contract('Validation.js', (accounts) => { assert.equal(block.hash, signedHeaderHash); // Submit block should succeed - // const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader); const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; assert.equal(signedHeaderHash, recoveredBlockHash); @@ -135,74 +140,8 @@ contract('Validation.js', (accounts) => { assert.equal(parentHash, block.parentHash); }) - // Here the block header is signed off chain but by a whitelisted validator - it('Authentic Submission Off-Chain Signature - SubmitBlock()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - const rlpHeaders = encoder.encodeBlockHeader(block); - const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); - - // Encode and sign the new header - const encodedExtraData = '0x' + rlp.encode(rlpHeaders.extraDataShort).toString('hex'); - const newSignedHeaderHash = eth_util.sha3(rlpHeaders.unsigned); - - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - - let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); - - // Append signature to the end of extraData - const sigBytes = utils.hexToBytes(signature.toString('hex')); - // const extraBytesShort = utils.hexToBytes(rlpHeaders.extraDataShort); - const newExtraDataBytes = rlpHeaders.extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); - assert.equal(rlpHeaders.extraDataSignature, '0x'+signature.toString('hex')) - - const newSignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - newExtraData, // Off-chain signed block - block.mixHash, - block.nonce - ]; - - // Encode the offchain signed header - const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); - - // Submit block should succeed - const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, offchainSignedHeader); - const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; - assert.equal(signedHeaderHash, recoveredBlockHash); - - let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); - assert.equal(blockHash, true); - - let header = await validation.m_blockheaders(TESTCHAINID, block.hash); - - // Separate fetched header info - parentHash = header[2]; - - // Assert that block was persisted correctly - assert.equal(parentHash, block.parentHash); - }) - - // Here the block header is signed off chain but by a whitelisted validator who alters the block - it('Inauthentic Block Submission - SubmitBlock()', async () => { + // Here the block header is signed off chain but by a a non-whitelisted validator + it('Fail Submit Block unkown validator - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); @@ -211,14 +150,13 @@ contract('Validation.js', (accounts) => { // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); - // Alter txHash - const newTxHash = Web3Utils.sha3("Test Data"); + // Alter txHashin the unsigned header concatenation const signedHeader = [ block.parentHash, block.sha3Uncles, block.miner, block.stateRoot, - newTxHash, + block.transactionsRoot, block.receiptsRoot, block.logsBloom, Web3Utils.toBN(block.difficulty), @@ -242,7 +180,7 @@ contract('Validation.js', (accounts) => { block.sha3Uncles, block.miner, block.stateRoot, - newTxHash, + block.transactionsRoot, block.receiptsRoot, block.logsBloom, Web3Utils.toBN(block.difficulty), @@ -259,34 +197,18 @@ contract('Validation.js', (accounts) => { const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); - - const privateKey = Buffer.from('e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b', 'hex') - - const sig = eth_util.ecsign(unsignedHeaderHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = eth_util.ecrecover(unsignedHeaderHash, sig.v, sig.r, sig.s); - const addrBuf = eth_util.pubToAddress(pubKey); - assert.equal(VALIDATORS[0], '0x'+addrBuf.toString('hex')); + const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig; + // Encode and sign the new header + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); + const newSignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); - // Need to understand why but signature requires different v than in others to recover correctly - if (sig.v=="27") { - newSig = newSigBytes.toString('hex') + '00'; - } - if (sig.v=="28") { - newSig = newSigBytes.toString('hex') + '01'; - } + const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') - // let signature = await signHeader(unsignedHeaderHash, privateKey, block.extraData); + let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); // Append signature to the end of extraData - const sigBytes = utils.hexToBytes(newSig.toString('hex')); + const sigBytes = utils.hexToBytes(signature.toString('hex')); const newExtraDataBytes = extraBytesShort.concat(sigBytes); const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); @@ -295,7 +217,7 @@ contract('Validation.js', (accounts) => { block.sha3Uncles, block.miner, block.stateRoot, - newTxHash, + block.transactionsRoot, block.receiptsRoot, block.logsBloom, Web3Utils.toBN(block.difficulty), @@ -312,113 +234,77 @@ contract('Validation.js', (accounts) => { const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); const offchainHeaderHash = Web3Utils.sha3(offchainSignedHeader); - // Submit block should succeed - const validationReceipt = await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader); - const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; - // console.log(validationReceipt.logs[1].args['signer']); - assert.equal(offchainHeaderHash, recoveredBlockHash); - - let blockHash = await validation.m_blockhashes(TESTCHAINID, offchainHeaderHash); - assert.equal(blockHash, true); + await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader).should.be.rejected; }) - // Here the block header is signed off chain but by a a non-whitelisted validator - it('Fail Submit Block unkown validator - SubmitBlock()', async () => { + it('Submission of two sequential blocks - SubmitBlocks()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - + await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); + // Generate the arrays which will store the block header and indices + let signedHeaders = []; + let signedHeaderIndices = []; + let unsignedHeaders = []; + let unsignedHeaderIndices = []; - // Alter txHash - const signedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; + // Fetch block 1 from testrpc + let block = web3.eth.getBlock(1); - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); + let rlpHeaders = encoder.encodeBlockHeader(block); + let signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); + // Start creating the long list of block headers + signedHeaders.push(rlpHeaders.signed); + signedHeaderIndices.push(utils.hexToBytes(rlpHeaders.signed).splice(1).length); + unsignedHeaders.push(rlpHeaders.unsigned); + unsignedHeaderIndices.push(utils.hexToBytes(rlpHeaders.unsigned).splice(1).length); - // Encode and sign the new header - const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); - const newSignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); + // Fetch block 1 from testrpc + block = web3.eth.getBlock(2); - const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') + rlpHeaders = encoder.encodeBlockHeader(block); + signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + signedHeaders.push(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); - let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); + // Start creating the long list of block headers + signedHeaders.push(rlpHeaders.signed); + signedHeaderIndices.push(utils.hexToBytes(rlpHeaders.signed).splice(1).length + signedHeaderIndices[signedHeaderIndices.length - 1]); + unsignedHeaders.push(rlpHeaders.unsigned); + unsignedHeaderIndices.push(utils.hexToBytes(rlpHeaders.unsigned).splice(1).length + unsignedHeaderIndices[unsignedHeaderIndices.length - 1]); - // Append signature to the end of extraData - const sigBytes = utils.hexToBytes(signature.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); + // Submit block should succeed + let joinedSignedBlocks = utils.joinHex(signedHeaders); + let joinedUnsignedBlocks = utils.joinHex(unsignedHeaders); + + + // Submit two blocks at the same time + const validationReceipt = await validation.SubmitBlocks( + TESTCHAINID, + joinedUnsignedBlocks, + joinedSignedBlocks, + unsignedHeaderIndices, + signedHeaderIndices, + ); + + const recoveredBlockHash = await validationReceipt.logs[2].args['blockHash']; + assert.equal(signedHeaderHash, recoveredBlockHash); + console.log("\tGas used to submit block = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - const newSignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - newExtraData, // Off-chain signed block - block.mixHash, - block.nonce - ]; + let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); + assert.equal(blockHash, true); - // Encode the offchain signed header - const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); - const offchainHeaderHash = Web3Utils.sha3(offchainSignedHeader); + let header = await validation.m_blockheaders(TESTCHAINID, block.hash); - await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader).should.be.rejected; + // Separate fetched header info + parentHash = header[2]; + // Assert that block was persisted correctly + assert.equal(parentHash, block.parentHash); }) it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { From d2d97d2b0046d97c155297c06a123e56f6ca58f5 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 24 Sep 2018 15:08:12 +0100 Subject: [PATCH 148/203] Added the rehashing of blocks in Ion block store --- contracts/Ion.sol | 9 ++++++++- contracts/Validation.sol | 7 ++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index dc902ac..25de9be 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -222,7 +222,14 @@ contract Ion { * @param _txRootHash transaction root hash of the block being added * @param _receiptRootHash receipt root hash of the block being added */ - function addBlock(bytes32 _hash, bytes32 _txRootHash, bytes32 _receiptRootHash) public { + function addBlock(bytes32 _id, bytes32 _hash, bytes32 _txRootHash, bytes32 _receiptRootHash, bytes _rlpBlockHeader) + onlyRegisteredChains(_id) + { + RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); + + bytes32 hashedHeader = keccak256(_rlpBlockHeader); + require( hashedHeader == _hash ); + m_blockhashes[_hash] = true; m_blockheaders[_hash].txRootHash = _txRootHash; m_blockheaders[_hash].receiptRootHash = _receiptRootHash; diff --git a/contracts/Validation.sol b/contracts/Validation.sol index b07b2c5..8064c7e 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -166,7 +166,7 @@ contract Validation { // Append the new block to the struct addProposal(_id, SolUtils.BytesToAddress(header[2].toBytes(), 1)); - addBlockToChain(_id, _blockHash, _parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint()); + addBlockToChain(_id, _blockHash, _parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint(), _rlpSignedBlockHeader); updateBlockHash(_id, _blockHash); } @@ -208,7 +208,8 @@ contract Validation { bytes32 _parentHash, bytes32 _txRootHash, bytes32 _receiptRootHash, - uint256 _height + uint256 _height, + bytes _rlpBlock ) internal { m_blockhashes[_id][_hash] = true; // Append the new block to the struct @@ -220,7 +221,7 @@ contract Validation { // Add block to Ion Ion ion = Ion(registeredIon); - ion.addBlock(_hash, _txRootHash, _receiptRootHash); + ion.addBlock(_id, _hash, _txRootHash, _receiptRootHash, _rlpBlock); } From ae9dbe33faabf003ac8c0a845f7a2d59b1313c24 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 25 Sep 2018 11:28:00 +0100 Subject: [PATCH 149/203] Implemented a small change to Ion restricting the calling of functions to registered validation modules --- contracts/Ion.sol | 31 ++++++++++++++++++++++++------- test/ion.js | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 50aa7b9..97ccd53 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -23,7 +23,8 @@ contract Ion { bytes32 receiptRootHash; } - mapping (bytes32 => bool) public chains; + mapping (bytes32 => bool) public m_chains; + mapping (address => bool) public m_validation_modules; mapping (bytes32 => bool) public m_blockhashes; mapping (bytes32 => BlockHeader) public m_blockheaders; @@ -62,7 +63,18 @@ contract Ion { * Modifier that checks if the provided chain id has been registered to this contract */ modifier onlyRegisteredChains(bytes32 _id) { - require(chains[_id], "Chain is not registered"); + require(m_chains[_id], "Chain is not registered"); + _; + } + + /* + * onlyRegisteredValidation + * param: _addr (address) Address of the Validation module being registered + * + * Modifier that checks if the provided chain id has been registered to this contract + */ + modifier onlyRegisteredValidation(address _addr) { + require(m_validation_modules[_addr], "Validation module is not registered"); _; } @@ -89,16 +101,18 @@ contract Ion { /* * addChain * param: id Unique id of another chain to interoperate with + * param: addr Address of the validation module used for this new chain * * Supplied with an id of another chain, checks if this id already exists in the known set of ids - * and adds it to the list of known chains. + * and adds it to the list of known m_chains. * *Should be called by the validation registerChain() function */ function addChain(bytes32 _id) public returns (bool) { require( _id != chainId, "Cannot add this chain id to chain register" ); - require(!chains[_id], "Chain already exists" ); - chains[_id] = true; + require(!m_chains[_id], "Chain already exists" ); + m_chains[_id] = true; + m_validation_modules[msg.sender] = true; registeredChains.push(_id); return true; @@ -217,18 +231,21 @@ contract Ion { } /* - * @description when a block is submitted the header must be added to a mapping of blockhashes and chains to blockheaders + * @description when a block is submitted the header must be added to a mapping of blockhashes and m_chains to blockheaders * @param _hash root hash of the block being added * @param _txRootHash transaction root hash of the block being added * @param _receiptRootHash receipt root hash of the block being added */ function addBlock(bytes32 _id, bytes32 _hash, bytes32 _txRootHash, bytes32 _receiptRootHash, bytes _rlpBlockHeader) + onlyRegisteredValidation(msg.sender) onlyRegisteredChains(_id) { + require(!m_blockhashes[_hash]); + RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); bytes32 hashedHeader = keccak256(_rlpBlockHeader); - require( hashedHeader == _hash ); + require(hashedHeader==_hash); m_blockhashes[_hash] = true; m_blockheaders[_hash].txRootHash = _txRootHash; diff --git a/test/ion.js b/test/ion.js index de2e384..0fea494 100644 --- a/test/ion.js +++ b/test/ion.js @@ -164,7 +164,7 @@ contract('Ion.js', (accounts) => { // Successfully add id of another chain await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - let chain = await ion.chains(TESTCHAINID); + let chain = await ion.m_chains(TESTCHAINID); assert.equal(chain, true); From 4bc8af3a5d485536616387522e7d258467b52ebb Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Mon, 1 Oct 2018 14:30:59 +0100 Subject: [PATCH 150/203] Cleaned up code and removed unused/redundant code. Removed chain ID from validation, should derive from single source to prevent mismatches. Updated tests and bundled clique test into validation as the validation is clique specific anyway. --- contracts/Ion.sol | 41 +++-- contracts/Validation.sol | 119 ++++---------- contracts/libraries/PatriciaTrie.sol | 2 +- migrations/2_deploy_contracts.js | 2 +- test/clique.js | 235 --------------------------- test/ion.js | 21 ++- test/merkle.js | 92 ----------- test/validation.js | 176 +++++++++++--------- 8 files changed, 161 insertions(+), 527 deletions(-) delete mode 100644 test/clique.js delete mode 100644 test/merkle.js diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 97ccd53..3daca9d 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -12,24 +12,23 @@ contract Ion { using RLP for RLP.Iterator; using RLP for bytes; - bytes32 public chainId; - bytes32[] public registeredChains; - /* * @description BlockHeader struct containing trie root hashes for tx verifications */ struct BlockHeader { - bytes32 txRootHash; - bytes32 receiptRootHash; + bytes32 txRootHash; + bytes32 receiptRootHash; } + bytes32 public chainId; + bytes32[] public registeredChains; + mapping (bytes32 => bool) public m_chains; mapping (address => bool) public m_validation_modules; mapping (bytes32 => bool) public m_blockhashes; mapping (bytes32 => BlockHeader) public m_blockheaders; - /* * Constructor * param: id (bytes32) Unique id to identify this chain that the contract is being deployed to. @@ -45,8 +44,8 @@ contract Ion { enum ProofType { TX, RECEIPT, ROOTS } event VerifiedProof(bytes32 chainId, bytes32 blockHash, uint proofType); - event broadcastSignature(address signer); - event broadcastHash(bytes32 blockHash); + event BroadcastSignature(address signer); + event BroadcastHash(bytes32 blockHash); /* ======================================================================================================================== @@ -177,10 +176,10 @@ contract Ion { bytes _parentNodes, bytes _path ) - onlyRegisteredChains(_id) - onlyExistingBlocks(_id, _blockHash) - public - returns (bool) + onlyRegisteredChains(_id) + onlyExistingBlocks(_id, _blockHash) + public + returns (bool) { verifyProof(_value, _parentNodes, _path, m_blockheaders[_blockHash].receiptRootHash); @@ -188,14 +187,6 @@ contract Ion { return true; } - /* - * Verify proof assertion to avoid stack to deep error (it doesn't show during compile time but it breaks - * blockchain simulator) - */ - function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _hash) { - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, _hash) ); - } - /* * CheckRootsProof * param: _id (bytes32) Unique id of chain submitting block from @@ -230,6 +221,14 @@ contract Ion { return true; } + /* + * Verify proof assertion to avoid stack to deep error (it doesn't show during compile time but it breaks + * blockchain simulator) + */ + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _hash) { + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, _hash) ); + } + /* * @description when a block is submitted the header must be added to a mapping of blockhashes and m_chains to blockheaders * @param _hash root hash of the block being added @@ -245,7 +244,7 @@ contract Ion { RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); bytes32 hashedHeader = keccak256(_rlpBlockHeader); - require(hashedHeader==_hash); + require(hashedHeader == _hash, "Hashed header does not match submitted block hash!"); m_blockhashes[_hash] = true; m_blockheaders[_hash].txRootHash = _txRootHash; diff --git a/contracts/Validation.sol b/contracts/Validation.sol index 8064c7e..460dac9 100644 --- a/contracts/Validation.sol +++ b/contracts/Validation.sol @@ -12,15 +12,14 @@ contract Validation { using RLP for RLP.Iterator; using RLP for bytes; - address registeredIon; - bytes32 public chainId; + Ion ion; /* * @description persists the last submitted block of a chain being validated */ struct BlockHeader { - uint256 blockHeight; - bytes32 latestHash; + uint256 blockNumber; + bytes32 blockHash; bytes32 prevBlockHash; bytes32 txRootHash; bytes32 receiptRootHash; @@ -34,18 +33,12 @@ contract Validation { mapping (bytes32 => mapping (address => bool)) public m_validators; mapping (bytes32 => mapping (address => uint256)) public m_proposals; - - event broadcastSignature(address signer); - event broadcastHash(bytes32 blockHash); - event test(bytes unsigned, bytes signed); - /* * @param _id genesis block of the blockchain where the contract is deployed * @param _ion address of the Ion hub contract with which this validation contract is connected */ - constructor (bytes32 _id, address _ion) public { - chainId = _id; - registeredIon = _ion; + constructor (address _ionAddr) public { + ion = Ion(_ionAddr); } @@ -59,7 +52,7 @@ contract Validation { * and adds it to the list of known chains. */ function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { - require( _id != chainId, "Cannot add this chain id to chain register" ); + require( _id != ion.chainId(), "Cannot add this chain id to chain register" ); require(!chains[_id], "Chain already exists" ); chains[_id] = true; @@ -69,62 +62,12 @@ contract Validation { } m_threshold[_id] = (_validators.length/2) + 1; - Ion ion = Ion(registeredIon); require(ion.addChain(_id), "Chain not added to Ion successfully!"); - m_blockheaders[_id][_genesisHash].blockHeight = 0; - m_blockheaders[_id][_genesisHash].latestHash = _genesisHash; + m_blockheaders[_id][_genesisHash].blockNumber = 0; + m_blockheaders[_id][_genesisHash].blockHash = _genesisHash; m_blockhashes[_id][_genesisHash] = true; m_latestblock[_id] = _genesisHash; - - } - - /* - * SubmitBlocks - * param: _id (bytes32) Unique id of chain submitting block from - * param: _rlpBlockHeader (bytes) Concatenation of multiple RLP-encoded byte arrays of block headers from other chain without the signature in extraData - * param: _rlpSignedBlockHeader (bytes) Concatenation of multiple RLP-encoded byte arrays of block headers from other chain with the signature in extraData - * param: _unsignedIndices (uint256[]) Array containing the indices at which each individual block begins at in the unsigned header concatenation - * param: _signedIndices (uint256[]) Array containing the indices at which each individual block begins at in the signed header concatenation - * - * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered - * and if valid the block is persisted as BlockHeader structs defined above. - */ - function SubmitBlocks( - bytes32 _id, - bytes _rlpUnsignedBlockHeaders, - bytes _rlpSignedBlockHeaders, - uint256[] _unsignedIndices, - uint256[] _signedIndices - ) public { - // Loop over each header contained in the bytes arrays and submit to block accordingly - for (uint i=0; i<_signedIndices.length; ++i ) { - uint256 signedSize; - uint256 unsignedSize; - - // Find the length in bytes of each encoded header - if (i==0) { - signedSize = _signedIndices[0]; - unsignedSize = _unsignedIndices[0]; - } else { - signedSize = _signedIndices[i] - _signedIndices[i-1]; - unsignedSize = _unsignedIndices[i] - _unsignedIndices[i-1]; - } - - bytes memory signedHeader = new bytes(signedSize); - bytes memory unsignedHeader = new bytes(unsignedSize); - - if (i==0) { - SolUtils.BytesToBytes(signedHeader, _rlpSignedBlockHeaders, 0); - SolUtils.BytesToBytes(unsignedHeader, _rlpUnsignedBlockHeaders, 0); - } else { - SolUtils.BytesToBytes(signedHeader, _rlpSignedBlockHeaders, _signedIndices[i-1]); - SolUtils.BytesToBytes(unsignedHeader, _rlpUnsignedBlockHeaders, _unsignedIndices[i-1]); - } - - // Submit block to the validation - SubmitBlock(_id, unsignedHeader, signedHeader); - } } /* @@ -139,6 +82,7 @@ contract Validation { function SubmitBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) onlyRegisteredChains(_id) public { RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); + require( header.length == signedHeader.length, "Header properties length mismatch" ); // Check header and signedHeader contain the same data for (uint256 i=0; i { .then(() => deployer.link(PatriciaTrie, Ion)) .then(() => deployer.deploy(Ion, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) .then(() => Ion.deployed) - .then(() => deployer.deploy(Validation, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177", Ion.address)) + .then(() => deployer.deploy(Validation, Ion.address)) .then(() => Validation.deployed) .then(() => deployer.deploy(EventVerifier)) .then(() => EventVerifier.deployed) diff --git a/test/clique.js b/test/clique.js deleted file mode 100644 index 675598a..0000000 --- a/test/clique.js +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const eth_util = require('ethereumjs-util'); -const utils = require('./helpers/utils.js'); -const encoder = require('./helpers/encoder.js'); -const Web3 = require('web3'); - -const Validation = artifacts.require("Validation"); -const Ion = artifacts.require("Ion"); - -const web3 = new Web3(); -const rinkeby = new Web3(); - -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); -rinkeby.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); - -// Takes a header and private key returning the signed data -// Needs extraData just to be sure of the final byte -signHeader = (headerHash, privateKey, extraData) => { - const sig = eth_util.ecsign(headerHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); - const addrBuf = eth_util.pubToAddress(pubKey); - - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig; - - const bytes = utils.hexToBytes(extraData) - const finalByte = bytes.splice(bytes.length-1) - if (finalByte.toString('hex')=="0") { - newSig = newSigBytes.toString('hex') + '00'; - } - if (finalByte.toString('hex')=="1") { - newSig = newSigBytes.toString('hex') + '01'; - } - - return newSig; -} - -const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" -const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" -const VALIDATORS_START = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; -const VALIDATORS_FINISH = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; -const GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; - -require('chai') - .use(require('chai-as-promised')) - .should(); - -contract('Clique.js', (accounts) => { - const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); - - const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); - - // This test checks that new validators get added into the validator list as blocks are submitted to the contract. - // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 - // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. - it('Add Validators Through Individual Block Submission', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS_START, GENESIS_HASH); - - let voteThreshold = await validation.m_threshold(TESTCHAINID); - assert.equal(voteThreshold, 2); - - let voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(voteProposal, 0); - - // Fetch block 873982 from rinkeby - let block = rinkeby.eth.getBlock(873982); - let rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - let validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873982 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Fetch block 873983 from rinkeby - block = rinkeby.eth.getBlock(873983); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873983 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Check proposal is added - voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(voteProposal, 1); - - - // Fetch block 873984 from rinkeby - block = rinkeby.eth.getBlock(873984); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873984 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Fetch block 873985 from rinkeby - block = rinkeby.eth.getBlock(873985); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873985 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Fetch block 873986 from rinkeby - block = rinkeby.eth.getBlock(873986); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873986 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Check proposal is added - voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(voteProposal, 0); - - // Check all new validators are added - let validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[0]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[2]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[3]); - assert.equal(validators, true); - }) - - // This test checks that new validators get added into the validator list as blocks are submitted to the contract. - // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 - // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. - it('Add Validators Through Simultaneous Block Submission', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - - // Generate the arrays which will store the block header and indices - let signedHeaders = []; - let signedHeaderIndices = []; - let unsignedHeaders = []; - let unsignedHeaderIndices = []; - - await validation.RegisterChain(TESTCHAINID, VALIDATORS_START, GENESIS_HASH); - - let voteThreshold = await validation.m_threshold(TESTCHAINID); - assert.equal(voteThreshold, 2); - - let voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(voteProposal, 0); - - // Fetch block 873982 from rinkeby - let block = rinkeby.eth.getBlock(873982); - let rlpHeaders = encoder.encodeBlockHeader(block); - encoder.appendBlockHeaders( - signedHeaders, - signedHeaderIndices, - unsignedHeaders, - unsignedHeaderIndices, - rlpHeaders, - ); - - // Fetch block 873983 from rinkeby - block = rinkeby.eth.getBlock(873983); - rlpHeaders = encoder.encodeBlockHeader(block); - encoder.appendBlockHeaders( - signedHeaders, - signedHeaderIndices, - unsignedHeaders, - unsignedHeaderIndices, - rlpHeaders, - ); - - // Fetch block 873984 from rinkeby - block = rinkeby.eth.getBlock(873984); - rlpHeaders = encoder.encodeBlockHeader(block); - encoder.appendBlockHeaders( - signedHeaders, - signedHeaderIndices, - unsignedHeaders, - unsignedHeaderIndices, - rlpHeaders, - ); - - // Fetch block 873985 from rinkeby - block = rinkeby.eth.getBlock(873985); - rlpHeaders = encoder.encodeBlockHeader(block); - encoder.appendBlockHeaders( - signedHeaders, - signedHeaderIndices, - unsignedHeaders, - unsignedHeaderIndices, - rlpHeaders, - ); - - // Fetch block 873986 from rinkeby - block = rinkeby.eth.getBlock(873986); - rlpHeaders = encoder.encodeBlockHeader(block); - encoder.appendBlockHeaders( - signedHeaders, - signedHeaderIndices, - unsignedHeaders, - unsignedHeaderIndices, - rlpHeaders, - ); - - // Submit block should succeed - let joinedSignedBlocks = utils.joinHex(signedHeaders); - let joinedUnsignedBlocks = utils.joinHex(unsignedHeaders); - - // Submit multiple blocks at the same time - const validationReceipt = await validation.SubmitBlocks( - TESTCHAINID, - joinedUnsignedBlocks, - joinedSignedBlocks, - unsignedHeaderIndices, - signedHeaderIndices, - ); - console.log("\tGas used to simultaneously submit blocks (873982-873986) = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Check all new validators are added - let validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[0]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[2]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[3]); - assert.equal(validators, true); - }) - -}); diff --git a/test/ion.js b/test/ion.js index 0fea494..42152a1 100644 --- a/test/ion.js +++ b/test/ion.js @@ -4,7 +4,6 @@ const Web3Utils = require('web3-utils'); const utils = require('./helpers/utils.js'); const BN = require('bignumber.js') -const merkle = require('./helpers/merkle.js') const encoder = require('./helpers/encoder.js') const rlp = require('rlp'); const async = require('async') @@ -160,7 +159,7 @@ contract('Ion.js', (accounts) => { it('Register Chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); // Successfully add id of another chain await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -177,7 +176,7 @@ contract('Ion.js', (accounts) => { it('Check Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -190,7 +189,7 @@ contract('Ion.js', (accounts) => { it('Fail Tx Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -208,7 +207,7 @@ contract('Ion.js', (accounts) => { it('Check Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -222,7 +221,7 @@ contract('Ion.js', (accounts) => { it('Fail Receipt Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -240,7 +239,7 @@ contract('Ion.js', (accounts) => { it('Check Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -254,7 +253,7 @@ contract('Ion.js', (accounts) => { it('Fail Roots Proof', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -276,7 +275,7 @@ contract('Ion.js', (accounts) => { it('Deploy Function Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); const verifier = await TriggerEventVerifier.new(); const functionContract = await FunctionEvent.new(ion.address, verifier.address); @@ -284,7 +283,7 @@ contract('Ion.js', (accounts) => { it('Verify Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); const verifier = await TriggerEventVerifier.new(); const functionContract = await FunctionEvent.new(ion.address, verifier.address); @@ -305,7 +304,7 @@ contract('Ion.js', (accounts) => { it('Fail Function Execution', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); const verifier = await TriggerEventVerifier.new(); const functionContract = await FunctionEvent.new(ion.address, verifier.address); diff --git a/test/merkle.js b/test/merkle.js deleted file mode 100644 index 5b3ba7e..0000000 --- a/test/merkle.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3Utils = require('web3-utils'); -// const BN = require('bignumber.js') -const merkle = require('./helpers/merkle.js') - -contract('Merkle.js', () => { - it('Merkle Proof', () => { - - const testData = ["1","2","3","4","5","6","7"] - - const tree = merkle.createMerkle(testData) - - const expectedTree = [ - [ - [ - '8568612641526826488487436752726739043287191320122540356069953783894380777505', - '8763638472773768691201326883407021568462294246273894496415427229083082408032', - '19224855404247632006917173431419498680506051063941070371722880450128577361118', - '61795459977501490647348212754130855970016313872340374962921336716751708851142', - '64645341593328157176709656265449880868558868673380425455960412802858937540801', - '74330811247603495249613868516695563873247293176611122272199330092769797099053', - '78469846343542442363028680824980501212021332975324075417961003849793346933925', - '75317570447191171753008806478868650352148013528306361601609880810432714200529' - ], - [ - '6560824545851281876686151142367952893930617484325436481370811303698242675212', - '14094329272021934754728783365468382816047630355461653340632553426278198853241', - '25919299780512511508061958642305261009583198324725036212440752482930702519878', - '11791415309425995046749154607832041856871129882141188736462372751874115368248' - ], - [ - '22114525030336665972036957912787127870644756898138077124815002206627656645846', - '74561778027252859083209130121920474961655350982938755244738788717578708084930' - ], - [ - '5587813875922595628752214729735723034111050560116231646359963981668986135460' - ] - ], - '5587813875922595628752214729735723034111050560116231646359963981668986135460' - ] - - const treeStr = [tree[0].map(i => i.map(j => j.toString(10))),tree[1].toString(10)] - assert.deepEqual(treeStr,expectedTree) - - const expectedPaths = [ - [ - '19224855404247632006917173431419498680506051063941070371722880450128577361118', - '6560824545851281876686151142367952893930617484325436481370811303698242675212', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ], - [ - '104265592756520220608901552731040627315465509694716502611474276812410996610513', - '25919299780512511508061958642305261009583198324725036212440752482930702519878', - '22114525030336665972036957912787127870644756898138077124815002206627656645846' - ], - [ - '90743482286830539503240959006302832933333810038750515972785732718729991261126', - '6560824545851281876686151142367952893930617484325436481370811303698242675212', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ], - [ - '8568612641526826488487436752726739043287191320122540356069953783894380777505', - '43042351581350983610621529617640359779365126521871794350496949428256481263225', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ], - [ - '103278833556932544105506614768867540836564789343021263282063726094748079509037', - '40739437618755043902641900860004018820188626048551329746326768753852397778232', - '22114525030336665972036957912787127870644756898138077124815002206627656645846' - ], - [ - '64645341593328157176709656265449880868558868673380425455960412802858937540801', - '40739437618755043902641900860004018820188626048551329746326768753852397778232', - '22114525030336665972036957912787127870644756898138077124815002206627656645846' - ], - [ - '37711660782102817547094073135578998531779790412684035506279823231061364818016', - '43042351581350983610621529617640359779365126521871794350496949428256481263225', - '103509800336581907939101876374092451924972847149348896254603184719556990494914' - ] - ] - - const path = testData.map(value => merkle.pathMerkle(value,tree[0])) - assert.deepEqual(path.map(i => i.map(j => j.toString(10))),expectedPaths, 'paths badly created') - - const proof = testData.reduce((prev,leaf,idx) => (merkle.proofMerkle(leaf,path[idx],tree[1]) && prev), true) - const negProof = testData.reduce((prev,leaf,idx) => !(merkle.proofMerkle('10',path[idx],tree[1]) && prev),true) - assert(proof && negProof,'proof failed') - }) -}) diff --git a/test/validation.js b/test/validation.js index 98c49d7..c233a43 100644 --- a/test/validation.js +++ b/test/validation.js @@ -12,8 +12,10 @@ const Validation = artifacts.require("Validation"); const Ion = artifacts.require("Ion"); const web3 = new Web3(); +const rinkeby = new Web3(); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); +rinkeby.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); require('chai') .use(require('chai-as-promised')) @@ -48,6 +50,12 @@ signHeader = (headerHash, privateKey, extraData) => { const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" +const VALIDATORS_START = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; +const VALIDATORS_FINISH = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; +const GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; +const ADD_VALIDATORS_GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; + + contract('Validation.js', (accounts) => { const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); @@ -60,15 +68,15 @@ contract('Validation.js', (accounts) => { it('Deploy Contract', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - let chainId = await validation.chainId(); + const validation = await Validation.new(ion.address); + let chainId = await ion.chainId(); assert.equal(chainId, DEPLOYEDCHAINID); }) it('Register Chain', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); // Successfully add id of another chain let tx = await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -86,7 +94,7 @@ contract('Validation.js', (accounts) => { it('Register Chain - Check Validators', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); // Successfully add id of another chain await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -98,7 +106,7 @@ contract('Validation.js', (accounts) => { it('Register Chain - Check Genesis Hash', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); // Successfully add id of another chain await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -111,7 +119,7 @@ contract('Validation.js', (accounts) => { it('Authentic Submission Happy Path - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -124,7 +132,7 @@ contract('Validation.js', (accounts) => { // Submit block should succeed const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - const recoveredBlockHash = await validationReceipt.logs[0].args['blockHash']; + const recoveredBlockHash = await validation.getLatestBlockHash.call(TESTCHAINID); assert.equal(signedHeaderHash, recoveredBlockHash); console.log("\tGas used to submit block = " + validationReceipt.receipt.gasUsed.toString() + " gas"); @@ -143,7 +151,7 @@ contract('Validation.js', (accounts) => { // Here the block header is signed off chain but by a a non-whitelisted validator it('Fail Submit Block unkown validator - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -238,78 +246,9 @@ contract('Validation.js', (accounts) => { }) - it('Submission of two sequential blocks - SubmitBlocks()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Generate the arrays which will store the block header and indices - let signedHeaders = []; - let signedHeaderIndices = []; - let unsignedHeaders = []; - let unsignedHeaderIndices = []; - - // Fetch block 1 from testrpc - let block = web3.eth.getBlock(1); - - let rlpHeaders = encoder.encodeBlockHeader(block); - let signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); - assert.equal(block.hash, signedHeaderHash); - - // Start creating the long list of block headers - signedHeaders.push(rlpHeaders.signed); - signedHeaderIndices.push(utils.hexToBytes(rlpHeaders.signed).splice(1).length); - unsignedHeaders.push(rlpHeaders.unsigned); - unsignedHeaderIndices.push(utils.hexToBytes(rlpHeaders.unsigned).splice(1).length); - - // Fetch block 1 from testrpc - block = web3.eth.getBlock(2); - - rlpHeaders = encoder.encodeBlockHeader(block); - signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); - signedHeaders.push(rlpHeaders.signed); - assert.equal(block.hash, signedHeaderHash); - - // Start creating the long list of block headers - signedHeaders.push(rlpHeaders.signed); - signedHeaderIndices.push(utils.hexToBytes(rlpHeaders.signed).splice(1).length + signedHeaderIndices[signedHeaderIndices.length - 1]); - unsignedHeaders.push(rlpHeaders.unsigned); - unsignedHeaderIndices.push(utils.hexToBytes(rlpHeaders.unsigned).splice(1).length + unsignedHeaderIndices[unsignedHeaderIndices.length - 1]); - - // Submit block should succeed - let joinedSignedBlocks = utils.joinHex(signedHeaders); - let joinedUnsignedBlocks = utils.joinHex(unsignedHeaders); - - - // Submit two blocks at the same time - const validationReceipt = await validation.SubmitBlocks( - TESTCHAINID, - joinedUnsignedBlocks, - joinedSignedBlocks, - unsignedHeaderIndices, - signedHeaderIndices, - ); - - const recoveredBlockHash = await validationReceipt.logs[2].args['blockHash']; - assert.equal(signedHeaderHash, recoveredBlockHash); - console.log("\tGas used to submit block = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); - assert.equal(blockHash, true); - - let header = await validation.m_blockheaders(TESTCHAINID, block.hash); - - // Separate fetched header info - parentHash = header[2]; - - // Assert that block was persisted correctly - assert.equal(parentHash, block.parentHash); - }) - it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -325,7 +264,7 @@ contract('Validation.js', (accounts) => { it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(DEPLOYEDCHAINID, ion.address); + const validation = await Validation.new(ion.address); await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -373,7 +312,7 @@ contract('Validation.js', (accounts) => { extraDataShort, // extraData minus the signature block.mixHash, block.nonce - ]; + ]; const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); @@ -384,6 +323,81 @@ contract('Validation.js', (accounts) => { // Submit block should succeed await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader).should.be.rejected; - + + }) + + // This test checks that new validators get added into the validator list as blocks are submitted to the contract. + // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 + // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. + it('Add Validators Through Block Submission', async () => { + const ion = await Ion.new(DEPLOYEDCHAINID); + const validation = await Validation.new(ion.address); + + await validation.RegisterChain(TESTCHAINID, VALIDATORS_START, ADD_VALIDATORS_GENESIS_HASH); + + let voteThreshold = await validation.m_threshold(TESTCHAINID); + assert.equal(voteThreshold, 2); + + let voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Fetch block 873982 from rinkeby + let block = rinkeby.eth.getBlock(873982); + let rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + let validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873982 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873983 from rinkeby + block = rinkeby.eth.getBlock(873983); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873983 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Check proposal is added + voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 1); + + + // Fetch block 873984 from rinkeby + block = rinkeby.eth.getBlock(873984); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873984 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873985 from rinkeby + block = rinkeby.eth.getBlock(873985); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873985 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873986 from rinkeby + block = rinkeby.eth.getBlock(873986); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); + console.log("\tGas used to submit block 873986 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Check proposal is added + voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Check all new validators are added + let validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[0]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[2]); + assert.equal(validators, true); + validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[3]); + assert.equal(validators, true); }) }); From c2b6ad28fdc6cb61823aa325ad3a711752e08795 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Mon, 1 Oct 2018 14:38:50 +0100 Subject: [PATCH 151/203] Removed redundant files --- test/helpers/merkle.js | 135 ----------------------------------------- 1 file changed, 135 deletions(-) delete mode 100644 test/helpers/merkle.js diff --git a/test/helpers/merkle.js b/test/helpers/merkle.js deleted file mode 100644 index d80e3bb..0000000 --- a/test/helpers/merkle.js +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const Web3Utils = require('web3-utils'); -const BN = require('bignumber.js') - -/* -const bnjs = require('bn.js') -const bitTest = (n,b) => (new bnjs(n.toString(16),16)).testn(b) -const bitClear = (n,b) => bitTest(n,b) ? new BN((new bnjs(n.toString(16),16)).xor((new bnjs(1)).bincn(b))) : n -const bitSet = (n,b) => new BN((new bnjs(n.toString(16),16)).setn(b)) -*/ - -const toggleBit = (n,b,bitValue) => { - //b += 1 - let resStr = n.toString(2).padStart(b,'0') - const idx = resStr.length - b - resStr = resStr.substr(0,idx) + bitValue + resStr.substr(idx+1) - const bnRes = new BN(resStr,2) - return bnRes -} - - -const bitTest = (n,b) => { - //b += 1 - const resStr = n.toString(2).padStart(b,'0') - const idx = resStr.length - b - return Number(resStr[idx]) === 1 -} - - -const bitClear = (n,b) => toggleBit(n,b,'0') - - -const bitSet = (n,b) => toggleBit(n,b,'1') - - -const toHex = n => { - let nHex = n.toString(16) - if(nHex.length <= 64) - nHex = '0x' + nHex.padStart(64,'0') - else - nHex = '0x' + nHex.padStart(64*2,'0') - return nHex -} - - -const joinHex2BN = (a,b) => new BN('0x' + toHex(a) + toHex(b).substring(2)) - - -const hash = n => new BN(Web3Utils.sha3(Web3Utils.isBigNumber(n) ? toHex(n) : n)) - - -const merkleHash = n => bitClear(hash(n), 0xFF) - - -const treeLevel = items => items.reduce((prev,el, idx, arr) => { - if(idx % 2) - return prev.concat(merkleHash(joinHex2BN(arr[idx-1],el))) - return prev -} , []) - - -const createMerkle = (items) => { - const extraHash = merkleHash('merkle-tree-extra') - const leafHash = items - .map((leaf) => merkleHash(leaf)) - .sort((a,b) => (new BN(a)) - (new BN(b))) - if(leafHash.length % 2 !== 0) leafHash.push(extraHash) - const tree = [ leafHash ] - while (tree[0].length !== 1) { - const level = treeLevel(tree[0]) - if(level.length !== 1 && level.length % 2 !== 0) level.push(extraHash) //levels need to be pair - tree.unshift(level) - } - const root = tree[0]; - return [tree.sort(l => 1)].concat(root) -} - - -const pathMerkle = (leaf,tree) => { - const leafHash = merkleHash(leaf) - let idx = tree[0].findIndex(h => h.equals(leafHash)) - // console.log(leafHash) - // let idx = tree[0].findIndex(h => { - // console.log(Object.keys(h)); - // h.equals(leafHash) - // }) - //console.log(tree.map(l => l.map(b=>(b||'0x0').toString(16)))) - - const result = tree - .slice(0,-1) - .reduce((path,level) => { - const hash = (idx % 2) ? level[idx-1] : bitSet(level[idx+1],0xFF) - idx = idx >> 1 // divide by 2 - return path.concat(hash) - },[]) - - return result -} - - -const proofMerkle = (leaf, path, root, hashLeaf,debug) => { - const leafHash = hashLeaf ? leaf : merkleHash(leaf) - const result = path - .reduce((prev,item) => { - const bitSide = bitTest(item, 0xFF) - const h1 = bitSide ? prev : item - const h2 = bitSide ? bitClear(item, 0xFF) : prev - const hashValue = merkleHash(joinHex2BN(h1,h2)) - if(debug) { - console.log(bitSide) - console.log(h1.toString(16).length,h2.toString(16).length, h1.toString(16),h2.toString(16)) - console.log(joinHex2BN(h1,h2).toString(16).length) - console.log(hashValue.toString(16).length,hashValue.toString(16)) - console.log('=======================================================') - } - return hashValue - }, leafHash) - return (result.equals(root)) -} - - -const merkle = { - createMerkle, - treeLevel, - hash, - merkleHash, - bitClear, - bitSet, - pathMerkle, - proofMerkle, - bitTest, -} -module.exports = merkle From 03a829f1d8aafd2f6b60a3251b01b7f086b73094 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Mon, 1 Oct 2018 14:57:12 +0100 Subject: [PATCH 152/203] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2fefab0..994968b 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,15 @@ To facilitate this Ion has three main components: * Modular Validation Scheme * Ion Framework Contracts -The Ion hub contract is the core component of the framework, the contract persists key data of all valid blocks submitted to the validation contracts. To prove a transaction has occurred on an external blockchain the Ion framework contract require: +The Ion hub contract is the core component of the framework, the contract persists key data of all valid blocks submitted to the validation contracts required to verify a state transition. To prove a transaction has occurred on an external blockchain the Ion framework contract require (for EVM-based chains): -* Block Header (RLP encoding of the following array of items): - * Previous block hash - * State root hash +* Block Header: * Tx root hash - * TxReceipt root hash + * Receipt root hash * Block Hash +For other blockchains, different data will be required to prove state transitions and as such contracts must be written that adhere to those system-specific mechanisms. + For each block submitted to the validation contracts this information is appended to the Ion hub contract, thus creating a generic interface for Ion framework contracts to receive valid block data. Ion provides a generalised interoperability framework and thus block validation is designed to be modular, in order to allow for interop between chains with any consensus mechanism. When external blockchains are registered with a specific validation contract, having its own consensus specific validation mechanism, the validation contract adds the chain to the Ion hub. Subsequently all blocks successfully submitted to the validation contract are added to the Ion hub. From ecc53a2e3ae274f3246e05c471dd681493dd8ed7 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 8 Nov 2018 16:31:17 +0000 Subject: [PATCH 153/203] Clique + Ion unit tests with mocked classes. Rearchitected and enhanced entire suite of contracts. --- contracts/Ion.sol | 258 +- contracts/IonCompatible.sol | 4 +- contracts/{ => functional}/Function.sol | 14 +- contracts/{ => functional}/Trigger.sol | 0 .../{ => functional}/TriggerEventVerifier.sol | 6 +- contracts/libraries/Merkle.sol | 53 - contracts/mock/MockIon.sol | 27 + contracts/mock/MockStorage.sol | 25 + contracts/mock/MockValidation.sol | 16 + contracts/storage/BlockStore.sol | 56 + .../{Validation.sol => validation/Clique.sol} | 108 +- migrations/2_deploy_contracts.js | 13 +- package-lock.json | 2164 ++++++++++++++++- package.json | 7 +- test/clique.js | 346 +++ test/helpers/encoder.js | 2 + test/ion.js | 248 +- test/validation.js | 403 --- truffle.js | 1 + 19 files changed, 2688 insertions(+), 1063 deletions(-) rename contracts/{ => functional}/Function.sol (90%) rename contracts/{ => functional}/Trigger.sol (100%) rename contracts/{ => functional}/TriggerEventVerifier.sol (95%) delete mode 100644 contracts/libraries/Merkle.sol create mode 100644 contracts/mock/MockIon.sol create mode 100644 contracts/mock/MockStorage.sol create mode 100644 contracts/mock/MockValidation.sol create mode 100644 contracts/storage/BlockStore.sol rename contracts/{Validation.sol => validation/Clique.sol} (70%) create mode 100644 test/clique.js delete mode 100644 test/validation.js diff --git a/contracts/Ion.sol b/contracts/Ion.sol index 3daca9d..39d5454 100644 --- a/contracts/Ion.sol +++ b/contracts/Ion.sol @@ -6,28 +6,13 @@ import "./libraries/ECVerify.sol"; import "./libraries/RLP.sol"; import "./libraries/PatriciaTrie.sol"; import "./libraries/SolidityUtils.sol"; +import "./storage/BlockStore.sol"; contract Ion { - using RLP for RLP.RLPItem; - using RLP for RLP.Iterator; - using RLP for bytes; - - /* - * @description BlockHeader struct containing trie root hashes for tx verifications - */ - struct BlockHeader { - bytes32 txRootHash; - bytes32 receiptRootHash; - } bytes32 public chainId; - bytes32[] public registeredChains; - - mapping (bytes32 => bool) public m_chains; - mapping (address => bool) public m_validation_modules; - mapping (bytes32 => bool) public m_blockhashes; - mapping (bytes32 => BlockHeader) public m_blockheaders; - + mapping (address => bool) public m_registered_validation; + address[] public validation_modules; /* * Constructor @@ -41,239 +26,48 @@ contract Ion { chainId = _id; } - enum ProofType { TX, RECEIPT, ROOTS } - - event VerifiedProof(bytes32 chainId, bytes32 blockHash, uint proofType); - event BroadcastSignature(address signer); - event BroadcastHash(bytes32 blockHash); - -/* -======================================================================================================================== - - Modifiers - -======================================================================================================================== -*/ - - /* - * onlyRegisteredChains - * param: _id (bytes32) Unique id of chain supplied to function - * - * Modifier that checks if the provided chain id has been registered to this contract - */ - modifier onlyRegisteredChains(bytes32 _id) { - require(m_chains[_id], "Chain is not registered"); - _; - } - /* * onlyRegisteredValidation * param: _addr (address) Address of the Validation module being registered * * Modifier that checks if the provided chain id has been registered to this contract */ - modifier onlyRegisteredValidation(address _addr) { - require(m_validation_modules[_addr], "Validation module is not registered"); + modifier onlyRegisteredValidation() { + require( isContract(msg.sender), "Caller address is not a valid contract. Please inherit the BlockStore contract for proper usage." ); + require( m_registered_validation[msg.sender], "Validation module is not registered"); _; } - /* - * onlyExistingBlocks - * param: _id (bytes32) Unique id of chain supplied to function - * param: _hash (bytes32) Block hash which needs validation - * - * Modifier that checks if the provided block hash has been verified by the validation contract - */ - modifier onlyExistingBlocks(bytes32 _id, bytes32 _hash) { - require(m_blockhashes[_hash], "Block does not exist for chain"); - _; + // Pseudo-modifier returns boolean, used with different 'require's to input custom revert messages + function isContract(address _addr) internal returns (bool) { + uint size; + assembly { size := extcodesize(_addr) } + return (size > 0); } -/* -======================================================================================================================== - - Functions -======================================================================================================================== -*/ - - /* - * addChain - * param: id Unique id of another chain to interoperate with - * param: addr Address of the validation module used for this new chain - * - * Supplied with an id of another chain, checks if this id already exists in the known set of ids - * and adds it to the list of known m_chains. - * - *Should be called by the validation registerChain() function - */ - function addChain(bytes32 _id) public returns (bool) { - require( _id != chainId, "Cannot add this chain id to chain register" ); - require(!m_chains[_id], "Chain already exists" ); - m_chains[_id] = true; - m_validation_modules[msg.sender] = true; - registeredChains.push(_id); - - return true; - } - - /* - * CheckTxProof - * param: _id (bytes32) Unique id of chain submitting block from - * param: _blockHash (bytes32) Block hash of block being submitted - * param: _value (bytes) RLP-encoded transaction object array with fields defined as: https://github.com/ethereumjs/ethereumjs-tx/blob/0358fad36f6ebc2b8bea441f0187f0ff0d4ef2db/index.js#L50 - * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove - * param: _path (bytes) Byte array of the path to the node to be proved - * - * emits: VerifiedTxProof(chainId, blockHash, proofType) - * chainId: (bytes32) hash of the chain verifying proof against - * blockHash: (bytes32) hash of the block verifying proof against - * proofType: (uint) enum of proof type - * - * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution - * of this function to only allow if the chain the proof is for is registered to this contract and if the block that - * the proof is for has been submitted. - */ - function CheckTxProof( - bytes32 _id, - bytes32 _blockHash, - bytes _value, - bytes _parentNodes, - bytes _path - ) - onlyRegisteredChains(_id) - onlyExistingBlocks(_id, _blockHash) - public - returns (bool) - { - verifyProof(_value, _parentNodes, _path, m_blockheaders[_blockHash].txRootHash); + function registerValidationModule() public { + require( isContract(msg.sender), "Caller address is not a valid contract. Please inherit the BlockStore contract for proper usage." ); + require( !m_registered_validation[msg.sender], "Validation module has already been registered." ); - emit VerifiedProof(_id, _blockHash, uint(ProofType.TX)); - return true; + m_registered_validation[msg.sender] = true; + validation_modules.push(msg.sender); } - /* - * CheckReceiptProof - * param: _id (bytes32) Unique id of chain submitting block from - * param: _blockHash (bytes32) Block hash of block being submitted - * param: _value (bytes) RLP-encoded receipt object array with fields defined as: https://github.com/ethereumjs/ethereumjs-tx/blob/0358fad36f6ebc2b8bea441f0187f0ff0d4ef2db/index.js#L50 - * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove - * param: _path (bytes) Byte array of the path to the node to be proved - * - * emits: VerifiedTxProof(chainId, blockHash, proofType) - * chainId: (bytes32) hash of the chain verifying proof against - * blockHash: (bytes32) hash of the block verifying proof against - * proofType: (uint) enum of proof type - * - * All data associated with the proof must be constructed and paddChainrovided to this function. Modifiers restrict execution - * of this function to only allow if the chain the proof is for is registered to this contract and if the block that - * the proof is for has been submitted. - */ - function CheckReceiptProof( - bytes32 _id, - bytes32 _blockHash, - bytes _value, - bytes _parentNodes, - bytes _path - ) - onlyRegisteredChains(_id) - onlyExistingBlocks(_id, _blockHash) - public - returns (bool) - { - verifyProof(_value, _parentNodes, _path, m_blockheaders[_blockHash].receiptRootHash); - - emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); - return true; + function addChain(address _storageAddress, bytes32 _chainId) onlyRegisteredValidation public { + BlockStore store = BlockStore(_storageAddress); + store.addChain(_chainId); } /* - * CheckRootsProof - * param: _id (bytes32) Unique id of chain submitting block from - * param: _blockHash (bytes32) Block hash of block being submitted - * param: _txNodes (bytes) RLP-encoded relevant nodes of the Tx trie - * param: _receiptNodes (bytes) RLP-encoded relevant nodes of the Receipt trie + * storeBlock + * param: * - * emits: VerifiedTxProof(chainId, blockHash, proofType) - * chainId: (bytes32) hash of the chain verifying proof against - * blockHash: (bytes32) hash of the block verifying proof against - * proofType: (uint) enum of proof type - * - * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution - * of this function to only allow if the chain the proof is for is registered to this contract and if the block that - * the proof is for has been submitted. */ - function CheckRootsProof( - bytes32 _id, - bytes32 _blockHash, - bytes _txNodes, - bytes _receiptNodes - ) - onlyRegisteredChains(_id) - onlyExistingBlocks(_id, _blockHash) - public - returns (bool) - { - assert( m_blockheaders[_blockHash].txRootHash == getRootNodeHash(_txNodes) ); - assert( m_blockheaders[_blockHash].receiptRootHash == getRootNodeHash(_receiptNodes) ); - - emit VerifiedProof(_id, _blockHash, uint(ProofType.ROOTS)); - return true; - } + function storeBlock(address _storageAddress, bytes32 _chainId, bytes32 _blockHash, bytes _blockBlob) onlyRegisteredValidation public { + require( isContract(_storageAddress), "Storage address provided is not contract."); + BlockStore store = BlockStore(_storageAddress); - /* - * Verify proof assertion to avoid stack to deep error (it doesn't show during compile time but it breaks - * blockchain simulator) - */ - function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _hash) { - assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, _hash) ); + store.addBlock(_chainId, _blockHash, _blockBlob); } - - /* - * @description when a block is submitted the header must be added to a mapping of blockhashes and m_chains to blockheaders - * @param _hash root hash of the block being added - * @param _txRootHash transaction root hash of the block being added - * @param _receiptRootHash receipt root hash of the block being added - */ - function addBlock(bytes32 _id, bytes32 _hash, bytes32 _txRootHash, bytes32 _receiptRootHash, bytes _rlpBlockHeader) - onlyRegisteredValidation(msg.sender) - onlyRegisteredChains(_id) - { - require(!m_blockhashes[_hash]); - - RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); - - bytes32 hashedHeader = keccak256(_rlpBlockHeader); - require(hashedHeader == _hash, "Hashed header does not match submitted block hash!"); - - m_blockhashes[_hash] = true; - m_blockheaders[_hash].txRootHash = _txRootHash; - m_blockheaders[_hash].receiptRootHash = _receiptRootHash; - } - - -/* -======================================================================================================================== - - Helper Functions - -======================================================================================================================== -*/ - - /* - * @description returns the root node of an RLP encoded Patricia Trie - * @param _rlpNodes RLP encoded trie - * @returns root hash - */ - function getRootNodeHash(bytes _rlpNodes) private returns (bytes32) { - RLP.RLPItem memory nodes = RLP.toRLPItem(_rlpNodes); - RLP.RLPItem[] memory nodeList = RLP.toList(nodes); - - bytes memory b_nodeRoot = RLP.toBytes(nodeList[0]); - - return keccak256(b_nodeRoot); - } - - -} - +} \ No newline at end of file diff --git a/contracts/IonCompatible.sol b/contracts/IonCompatible.sol index 8144614..0b98a61 100644 --- a/contracts/IonCompatible.sol +++ b/contracts/IonCompatible.sol @@ -8,7 +8,7 @@ contract IonCompatible { blocks have been submitted to the Ion contract. */ Ion internal ion; - constructor(address ionAddr) public { - ion = Ion(ionAddr); + constructor(address _ionAddr) public { + ion = Ion(_ionAddr); } } diff --git a/contracts/Function.sol b/contracts/functional/Function.sol similarity index 90% rename from contracts/Function.sol rename to contracts/functional/Function.sol index 5743802..591d370 100644 --- a/contracts/Function.sol +++ b/contracts/functional/Function.sol @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; -import "./IonCompatible.sol"; +import "../storage/EthereumStore.sol"; contract TriggerEventVerifier { function verify(bytes20 _contractEmittedAddress, bytes _rlpReceipt, bytes20 _expectedAddress) public returns (bool); @@ -23,7 +23,8 @@ contract TriggerEventVerifier { This would also bloat the local scope which is prone to 'stack too deep' issues which would require custom workarounds. */ -contract Function is IonCompatible { +contract Function { + EthereumStore blockStore; /* The event verifier for the specific event being consumed. Each event would require a different event verifier to be deployed and each consumer would reference the relevant verifier to prove logs. */ @@ -34,7 +35,8 @@ contract Function is IonCompatible { /* Constructor. Requires Ion contract address and all used event verifier contract addresses. In this case we only use one verifier. */ - constructor(address _ionAddr, address _verifierAddr) IonCompatible(_ionAddr) public { + constructor(address _storeAddr, address _verifierAddr) public { + blockStore = EthereumStore(_storeAddr); verifier = TriggerEventVerifier(_verifierAddr); } @@ -82,9 +84,9 @@ contract Function is IonCompatible { bytes _receiptNodes, bytes20 _expectedAddress ) public returns (bool) { - assert( ion.CheckRootsProof(_chainId, _blockHash, _txNodes, _receiptNodes) ); - assert( ion.CheckTxProof(_chainId, _blockHash, _tx, _txNodes, _path) ); - assert( ion.CheckReceiptProof(_chainId, _blockHash, _receipt, _receiptNodes, _path) ); + assert( blockStore.CheckRootsProof(_chainId, _blockHash, _txNodes, _receiptNodes) ); + assert( blockStore.CheckTxProof(_chainId, _blockHash, _tx, _txNodes, _path) ); + assert( blockStore.CheckReceiptProof(_chainId, _blockHash, _receipt, _receiptNodes, _path) ); if (verifier.verify(_contractEmittedAddress, _receipt, _expectedAddress)) { execute(); diff --git a/contracts/Trigger.sol b/contracts/functional/Trigger.sol similarity index 100% rename from contracts/Trigger.sol rename to contracts/functional/Trigger.sol diff --git a/contracts/TriggerEventVerifier.sol b/contracts/functional/TriggerEventVerifier.sol similarity index 95% rename from contracts/TriggerEventVerifier.sol rename to contracts/functional/TriggerEventVerifier.sol index abd72da..3aef97a 100644 --- a/contracts/TriggerEventVerifier.sol +++ b/contracts/functional/TriggerEventVerifier.sol @@ -2,9 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; -import "./libraries/RLP.sol"; -import "./libraries/SolidityUtils.sol"; -import "./EventVerifier.sol"; +import "../libraries/RLP.sol"; +import "../libraries/SolidityUtils.sol"; +import "../EventVerifier.sol"; /* TriggerEventVerifier diff --git a/contracts/libraries/Merkle.sol b/contracts/libraries/Merkle.sol deleted file mode 100644 index c25a22c..0000000 --- a/contracts/libraries/Merkle.sol +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.23; - -library Merkle { - //uint256 constant ONE_SHL_255 = 57896044618658097711785492504343953926634992332820282019728792003956564819968; - uint256 constant ONE_SHL_255 = 28948022309329048855892746252171976963317496166410141009864396001978282409984; - - function Hash( uint256 a, uint256 b ) - internal pure - returns (uint256) - { - bytes32 outputHash = keccak256(abi.encodePacked(a, b)); - uint256 x = uint256(outputHash); - - // Clears highest bit from result - // left/right of node is stored there - if( x & ONE_SHL_255 > 0 ) - return x ^ ONE_SHL_255; - return x; - } - - /* - * Test case: - * "0x1a792cf089bfa56eae57ffe87e9b22f9c9bfe52c1ac300ea1f43f4ab53b4b794","0x2584db4a68aa8b172f70bc04e2e74541617c003374de6eb4b295e823e5beab01",["0x1ab0c6948a275349ae45a06aad66a8bd65ac18074615d53676c09b67809099e0","0x093fd25755220b8f497d65d2538c01ed279c131f63e42b2942867f2bd6622486","0xb1d101d9a9d27c3a8ed9d1b6548626eacf3d19546306117eb8af547d1e97189e","0xcb431dd627bc8dcfd858eae9304dc71a8d3f34a8de783c093188bb598eeafd04"] - */ - - function Verify( uint256 root, uint256 leaf_hash, uint256[] path ) - internal pure returns (bool) { - if( leaf_hash & ONE_SHL_255 > 0 ) - leaf_hash ^= ONE_SHL_255; - - if( path.length == 0 ) - return leaf_hash == root; - - uint256 node = leaf_hash; - uint256 item; - - for( uint256 i = 0; i < path.length; i++ ) - { - item = path[i]; - - if( (item & ONE_SHL_255) > 0 ) { - node = Hash(node, item ^ ONE_SHL_255); - } - else { - node = Hash(item, node); - } - } - - return node == root; - } -} diff --git a/contracts/mock/MockIon.sol b/contracts/mock/MockIon.sol new file mode 100644 index 0000000..776912b --- /dev/null +++ b/contracts/mock/MockIon.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.4.24; + +import "../Ion.sol"; +import "../storage/BlockStore.sol"; + +contract MockIon is Ion { + + constructor(bytes32 _id) Ion(_id) {} + + function registerValidationModule() public { + require( isContract(msg.sender), "Caller address is not a valid contract. Please inherit the BlockStore contract for proper usage." ); + require( !m_registered_validation[msg.sender], "Validation module has already been registered." ); + + m_registered_validation[msg.sender] = true; + validation_modules.push(msg.sender); + } + + function addChain(address _storageAddress, bytes32 _chainId) { + BlockStore store = BlockStore(_storageAddress); + store.addChain(_chainId); + } + + function storeBlock(address _storageAddress, bytes32 _chainId, bytes32 _blockHash, bytes _blockBlob) public { + BlockStore store = BlockStore(_storageAddress); + store.addBlock(_chainId, _blockHash, _blockBlob); + } +} \ No newline at end of file diff --git a/contracts/mock/MockStorage.sol b/contracts/mock/MockStorage.sol new file mode 100644 index 0000000..ac3e56b --- /dev/null +++ b/contracts/mock/MockStorage.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.4.24; + +import "../storage/BlockStore.sol"; + +/* + Mock Block Store contract + + This mocking contract is used to simulate interactions and asserting certain return data from interaction via other + contracts being tested. Use as a tool for testing ONLY. + + This is not an accurate representation of a block store contract and should not be used in any way as a + representation of a block store contract. Please refer to BlockStore.sol and inherit functionality from that base + contract and see EthereumStore.sol for more implementation details. + +*/ + +contract MockStorage is BlockStore { + + constructor(address _ionAddr) BlockStore(_ionAddr) public {} + + event AddedBlock(bytes32 blockHash); + function addBlock(bytes32 _chainId, bytes32 _blockHash, bytes _blockBlob) { + emit AddedBlock(_blockHash); + } +} diff --git a/contracts/mock/MockValidation.sol b/contracts/mock/MockValidation.sol new file mode 100644 index 0000000..0db9646 --- /dev/null +++ b/contracts/mock/MockValidation.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.4.24; + +import "../IonCompatible.sol"; + +contract MockValidation is IonCompatible { + constructor (address _ionAddr) IonCompatible(_ionAddr) public {} + + function register() public returns (bool) { + ion.registerValidationModule(); + return true; + } + + function SubmitBlock(address _storageAddress, bytes32 _chainId, bytes32 _blockHash, bytes _blockBlob) { + ion.storeBlock(_storageAddress, _chainId, _blockHash, _blockBlob); + } +} diff --git a/contracts/storage/BlockStore.sol b/contracts/storage/BlockStore.sol new file mode 100644 index 0000000..712ad18 --- /dev/null +++ b/contracts/storage/BlockStore.sol @@ -0,0 +1,56 @@ +pragma solidity ^0.4.24; + +import "../IonCompatible.sol"; + +contract BlockStore is IonCompatible { + bytes32[] public registeredChains; + + mapping (bytes32 => bool) public m_chains; + + modifier onlyIon() { + require(msg.sender == address(ion), "Block does not exist for chain"); + _; + } + + /* + * onlyRegisteredChains + * param: _id (bytes32) Unique id of chain supplied to function + * + * Modifier that checks if the provided chain id has been registered to this contract + */ + modifier onlyRegisteredChains(bytes32 _chainId) { + require(m_chains[_chainId], "Chain is not registered"); + _; + } + + /* + * Constructor + * param: id (bytes32) Unique id to identify this chain that the contract is being deployed to. + * + * Supplied with a unique id to identify this chain to others that may interoperate with it. + * The deployer must assert that the id is indeed public and that it is not already being used + * by another chain + */ + constructor(address _ionAddr) IonCompatible(_ionAddr) public {} + + /* + * addChain + * param: id (bytes32) Unique id of another chain to interoperate with + * + * Supplied with an id of another chain, checks if this id already exists in the known set of ids + * and adds it to the list of known m_chains. + * + *Should be called by the validation registerChain() function + */ + function addChain(bytes32 _chainId) onlyIon public returns (bool) { + require( _chainId != ion.chainId(), "Cannot add this chain id to chain register" ); + require(!m_chains[_chainId], "Chain already exists" ); + + m_chains[_chainId] = true; + registeredChains.push(_chainId); + + return true; + } + + function addBlock(bytes32 _chainId, bytes32 _blockHash, bytes _blockBlob) onlyIon onlyRegisteredChains(_chainId); +} diff --git a/contracts/Validation.sol b/contracts/validation/Clique.sol similarity index 70% rename from contracts/Validation.sol rename to contracts/validation/Clique.sol index 460dac9..5659a4b 100644 --- a/contracts/Validation.sol +++ b/contracts/validation/Clique.sol @@ -2,18 +2,22 @@ // SPDX-License-Identifier: LGPL-3.0+ pragma solidity ^0.4.23; -import "./libraries/ECVerify.sol"; -import "./libraries/RLP.sol"; -import "./libraries/SolidityUtils.sol"; -import "./Ion.sol"; - -contract Validation { +import "../libraries/ECVerify.sol"; +import "../libraries/RLP.sol"; +import "../libraries/SolidityUtils.sol"; +import "../IonCompatible.sol"; +import "../storage/BlockStore.sol"; + +/* + Smart contract for validation of blocks that use the Clique PoA consensus algorithm + Blocks must be submitted sequentially due to the voting mechanism of Clique. +*/ + +contract Clique is IonCompatible { using RLP for RLP.RLPItem; using RLP for RLP.Iterator; using RLP for bytes; - Ion ion; - /* * @description persists the last submitted block of a chain being validated */ @@ -25,6 +29,17 @@ contract Validation { bytes32 receiptRootHash; } + /* + * onlyRegisteredChains + * param: _id (bytes32) Unique id of chain supplied to function + * + * Modifier that checks if the provided chain id has been registered to this contract + */ + modifier onlyRegisteredChains(bytes32 _id) { + require(chains[_id], "Chain is not registered"); + _; + } + mapping (bytes32 => bool) public chains; mapping (bytes32 => bytes32) public m_latestblock; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; @@ -33,14 +48,12 @@ contract Validation { mapping (bytes32 => mapping (address => bool)) public m_validators; mapping (bytes32 => mapping (address => uint256)) public m_proposals; - /* - * @param _id genesis block of the blockchain where the contract is deployed - * @param _ion address of the Ion hub contract with which this validation contract is connected - */ - constructor (address _ionAddr) public { - ion = Ion(_ionAddr); - } + constructor (address _ionAddr) IonCompatible(_ionAddr) public {} + function register() public returns (bool) { + ion.registerValidationModule(); + return true; + } /* * RegisterChain @@ -51,23 +64,24 @@ contract Validation { * Supplied with an id of another chain, checks if this id already exists in the known set of ids * and adds it to the list of known chains. */ - function RegisterChain(bytes32 _id, address[] _validators, bytes32 _genesisHash) public { - require( _id != ion.chainId(), "Cannot add this chain id to chain register" ); - require(!chains[_id], "Chain already exists" ); - chains[_id] = true; + function RegisterChain(address _storeAddr, bytes32 _chainId, address[] _validators, bytes32 _genesisBlockHash) public { + require( _chainId != ion.chainId(), "Cannot add this chain id to chain register" ); + require(!chains[_chainId], "Chain already exists" ); + chains[_chainId] = true; // Append validators and vote threshold for (uint256 i = 0; i < _validators.length; i++) { - m_validators[_id][_validators[i]] = true; + m_validators[_chainId][_validators[i]] = true; } - m_threshold[_id] = (_validators.length/2) + 1; + m_threshold[_chainId] = (_validators.length/2) + 1; - require(ion.addChain(_id), "Chain not added to Ion successfully!"); + ion.addChain(_storeAddr, _chainId); - m_blockheaders[_id][_genesisHash].blockNumber = 0; - m_blockheaders[_id][_genesisHash].blockHash = _genesisHash; - m_blockhashes[_id][_genesisHash] = true; - m_latestblock[_id] = _genesisHash; + BlockHeader storage header = m_blockheaders[_chainId][_genesisBlockHash]; + header.blockNumber = 0; + header.blockHash = _genesisBlockHash; + m_blockhashes[_chainId][_genesisBlockHash] = true; + m_latestblock[_chainId] = _genesisBlockHash; } /* @@ -79,7 +93,7 @@ contract Validation { * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered * and if valid the block is persisted as BlockHeader structs defined above. */ - function SubmitBlock(bytes32 _id, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader) onlyRegisteredChains(_id) public { + function SubmitBlock(bytes32 _chainId, bytes _rlpBlockHeader, bytes _rlpSignedBlockHeader, address _storageAddr) onlyRegisteredChains(_chainId) public { RLP.RLPItem[] memory header = _rlpBlockHeader.toRLPItem().toList(); RLP.RLPItem[] memory signedHeader = _rlpSignedBlockHeader.toRLPItem().toList(); require( header.length == signedHeader.length, "Header properties length mismatch" ); @@ -100,20 +114,16 @@ contract Validation { // Check the parent hash is the same as the previous block submitted bytes32 parentBlockHash = SolUtils.BytesToBytes32(header[0].toBytes(), 1); - require(m_blockhashes[_id][parentBlockHash], "Not child of previous block!"); - - // Check the blockhash - bytes32 blockHash = keccak256(_rlpSignedBlockHeader); - - require (checkSignature(_id, signedHeader[12].toBytes(), _rlpBlockHeader), "Signer is not validator" ); + require(m_blockhashes[_chainId][parentBlockHash], "Not child of previous block!"); + require (checkSignature(_chainId, signedHeader[12].toBytes(), _rlpBlockHeader), "Signer is not validator" ); // Append the new block to the struct - addProposal(_id, SolUtils.BytesToAddress(header[2].toBytes(), 1)); - storeBlock(_id, blockHash, parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint(), _rlpSignedBlockHeader); - updateBlockHash(_id, blockHash); + addProposal(_chainId, SolUtils.BytesToAddress(header[2].toBytes(), 1)); + storeBlock(_chainId, keccak256(_rlpSignedBlockHeader), parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint(), _rlpSignedBlockHeader, _storageAddr); + updateBlockHash(_chainId, keccak256(_rlpSignedBlockHeader)); } - function checkSignature(bytes32 _id, bytes signedHeader, bytes _rlpBlockHeader) internal returns (bool) { + function checkSignature(bytes32 _chainId, bytes signedHeader, bytes _rlpBlockHeader) internal returns (bool) { bytes memory extraDataSig = new bytes(65); uint256 length = signedHeader.length; SolUtils.BytesToBytes(extraDataSig, signedHeader, length-65); @@ -121,7 +131,7 @@ contract Validation { // Recover the signature of address sigAddr = ECVerify.ecrecovery(keccak256(_rlpBlockHeader), extraDataSig); - return m_validators[_id][sigAddr]; + return m_validators[_chainId][sigAddr]; } function addProposal(bytes32 _id, address _vote) internal { @@ -144,17 +154,18 @@ contract Validation { * @param _hash root hash of the block being added */ function storeBlock( - bytes32 _id, + bytes32 _chainId, bytes32 _hash, bytes32 _parentHash, bytes32 _txRootHash, bytes32 _receiptRootHash, uint256 _height, - bytes _rlpBlock + bytes _rlpBlockHeader, + address _storageAddr ) internal { - m_blockhashes[_id][_hash] = true; + m_blockhashes[_chainId][_hash] = true; - BlockHeader storage header = m_blockheaders[_id][_hash]; + BlockHeader storage header = m_blockheaders[_chainId][_hash]; header.blockNumber = _height; header.blockHash = _hash; header.prevBlockHash = _parentHash; @@ -162,7 +173,7 @@ contract Validation { header.receiptRootHash = _receiptRootHash; // Add block to Ion - ion.addBlock(_id, _hash, _txRootHash, _receiptRootHash, _rlpBlock); + ion.storeBlock(_storageAddr, _chainId, _hash, _rlpBlockHeader); } /* @@ -183,16 +194,5 @@ contract Validation { return m_latestblock[_id]; } - /* - * onlyRegisteredChains - * param: _id (bytes32) Unique id of chain supplied to function - * - * Modifier that checks if the provided chain id has been registered to this contract - */ - modifier onlyRegisteredChains(bytes32 _id) { - require(chains[_id], "Chain is not registered"); - _; - } - } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 60ec21a..39ca2b1 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,18 +1,21 @@ const Ion = artifacts.require("Ion"); -const Validation = artifacts.require("Validation"); +const Clique = artifacts.require("Clique"); +const EthereumStore = artifacts.require("EthereumStore"); const PatriciaTrie = artifacts.require("PatriciaTrie"); const EventFunction = artifacts.require("Function"); const EventVerifier = artifacts.require("TriggerEventVerifier"); module.exports = async (deployer) => { - try { + try { deployer.deploy(PatriciaTrie) .then(() => PatriciaTrie.deployed) - .then(() => deployer.link(PatriciaTrie, Ion)) + .then(() => deployer.link(PatriciaTrie, EthereumStore)) .then(() => deployer.deploy(Ion, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) .then(() => Ion.deployed) - .then(() => deployer.deploy(Validation, Ion.address)) - .then(() => Validation.deployed) + .then(() => deployer.deploy(EthereumStore, Ion.address)) + .then(() => EthereumStore.deployed) + .then(() => deployer.deploy(Clique, Ion.address)) + .then(() => Clique.deployed) .then(() => deployer.deploy(EventVerifier)) .then(() => EventVerifier.deployed) .then(() => deployer.deploy(EventFunction, Ion.address, EventVerifier.address)) diff --git a/package-lock.json b/package-lock.json index cbb3bd7..c713787 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,11 +31,41 @@ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" }, + "@types/node": { + "version": "10.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.2.tgz", + "integrity": "sha512-53ElVDSnZeFUUFIYzI8WLQ25IhWzb6vbddNp8UHlXQyU0ET2RhV5zg0NfubzU7iNMh5bBXb0htCzfvrSVNgzaQ==" + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" }, + "abi-decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/abi-decoder/-/abi-decoder-1.2.0.tgz", + "integrity": "sha512-y2OKSEW4gf2838Eavc56vQY9V46zaXkf3Jl1WpTfUBbzAVrXSr4JRZAAWv55Tv9s5WNz1rVgBgz5d2aJIL1QCg==", + "requires": { + "web3": "0.18.4" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + }, + "web3": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", + "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + } + } + }, "abstract-leveldown": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", @@ -80,6 +110,11 @@ } } }, + "aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -248,8 +283,7 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, "assign-symbols": { "version": "1.0.0", @@ -1215,6 +1249,11 @@ } } }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -1268,11 +1307,18 @@ "safe-buffer": "5.1.2" } }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } + }, "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "dev": true + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" }, "bn.js": { "version": "4.11.8", @@ -1400,6 +1446,15 @@ "electron-to-chromium": "1.3.52" } }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "1.3.0", + "ieee754": "1.1.12" + } + }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", @@ -1414,6 +1469,11 @@ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -1603,9 +1663,9 @@ } }, "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" }, "cipher-base": { "version": "1.0.4", @@ -1987,6 +2047,21 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "requires": { + "decompress-tar": "4.1.1", + "decompress-tarbz2": "4.1.1", + "decompress-targz": "4.1.1", + "decompress-unzip": "4.0.1", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "pify": "2.3.0", + "strip-dirs": "2.1.0" + } + }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -1995,6 +2070,72 @@ "mimic-response": "1.0.1" } }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "5.2.0", + "is-stream": "1.1.0", + "tar-stream": "1.6.1" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "4.1.1", + "file-type": "6.2.0", + "is-stream": "1.1.0", + "seek-bzip": "1.0.5", + "unbzip2-stream": "1.3.1" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "4.1.1", + "file-type": "5.2.0", + "is-stream": "1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "3.9.0", + "get-stream": "2.3.1", + "pify": "2.3.0", + "yauzl": "2.10.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + } + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -2257,6 +2398,46 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "requires": { + "abstract-leveldown": "5.0.0", + "inherits": "2.0.3", + "level-codec": "9.0.0", + "level-errors": "2.0.0", + "xtend": "4.0.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "4.0.1" + } + }, + "level-codec": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz", + "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==" + }, + "level-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", + "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", + "requires": { + "errno": "0.1.7" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -2513,6 +2694,22 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "requires": { + "idna-uts46-hx": "2.3.1", + "js-sha3": "0.5.7" + }, + "dependencies": { + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + } + } + }, "eth-lib": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", @@ -2538,7 +2735,7 @@ "dependencies": { "ethereumjs-block": { "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "resolved": "http://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", "requires": { "async": "2.6.1", @@ -2548,15 +2745,24 @@ "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" } }, + "level-ws": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", + "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, "merkle-patricia-tree": { "version": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", - "integrity": "sha512-wJSFtpBHTdtRsqrVH7UoEyQOm0KNqqmTdE3vzZ/FamCe/w3cIhv7+khBiMlNlvRsrhxIhCCeVbshaG/FMz+xiQ==", + "integrity": "sha512-CSjgzZmkrQXg/DRwVPc1Icxw6WbOPkxAtPCz+ue8IkoYN6u9ZIPUmIEjpTQnXQgtB1kRajIR7L/rJ2KDl3+dUQ==", "requires": { "async": "1.5.2", "ethereumjs-util": "5.2.0", - "level-ws": "0.0.0", - "levelup": "1.3.9", - "memdown": "1.4.1", + "level-mem": "3.0.1", + "level-ws": "1.0.0", "readable-stream": "2.3.6", "rlp": "2.1.0", "semaphore": "1.1.0" @@ -2564,10 +2770,15 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" } } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" } } }, @@ -2632,6 +2843,55 @@ "secp256k1": "3.5.0" } }, + "ethers": { + "version": "4.0.0-beta.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.1.tgz", + "integrity": "sha512-SoYhktEbLxf+fiux5SfCEwdzWENMvgIbMZD90I62s4GZD9nEjgEWy8ZboI3hck193Vs0bDoTohDISx84f2H2tw==", + "requires": { + "@types/node": "10.12.2", + "aes-js": "3.0.0", + "bn.js": "4.11.8", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + } + } + }, "ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -3191,6 +3451,14 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "1.2.0" + } + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -3208,6 +3476,11 @@ "object-assign": "4.1.1" } }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -3359,6 +3632,28 @@ "rimraf": "2.6.2" } }, + "fs-promise": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-2.0.3.tgz", + "integrity": "sha1-9k5PhUvPaJqovdy6JokW2z20aFQ=", + "requires": { + "any-promise": "1.3.0", + "fs-extra": "2.1.2", + "mz": "2.7.0", + "thenify-all": "1.6.0" + }, + "dependencies": { + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0" + } + } + } + }, "fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -3899,6 +4194,17 @@ } } }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -4172,6 +4478,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, "grouped-queue": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", @@ -4409,6 +4720,26 @@ "safer-buffer": "2.1.2" } }, + "idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "requires": { + "punycode": "2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" + } + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -4691,6 +5022,11 @@ "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", @@ -5149,6 +5485,105 @@ } } }, + "level-mem": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", + "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", + "requires": { + "level-packager": "4.0.1", + "memdown": "3.0.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "4.0.1" + } + }, + "memdown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", + "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", + "requires": { + "abstract-leveldown": "5.0.0", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.2" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "level-packager": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", + "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", + "requires": { + "encoding-down": "5.0.4", + "levelup": "3.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "4.0.1" + } + }, + "deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "requires": { + "abstract-leveldown": "5.0.0", + "inherits": "2.0.3" + } + }, + "level-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", + "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", + "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "levelup": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", + "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "requires": { + "deferred-leveldown": "4.0.2", + "level-errors": "2.0.0", + "level-iterator-stream": "3.0.1", + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, "level-ws": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", @@ -5857,6 +6292,14 @@ } } }, + "mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "requires": { + "mkdirp": "0.5.1" + } + }, "mocha": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", @@ -5902,6 +6345,16 @@ } } }, + "mock-fs": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.7.0.tgz", + "integrity": "sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA==" + }, + "mout": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", + "integrity": "sha1-ujYR318OWx/7/QEWa48C0fX6K5k=" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5923,6 +6376,16 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "1.3.0", + "object-assign": "4.1.1", + "thenify-all": "1.6.0" + } + }, "nan": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", @@ -5989,9 +6452,9 @@ "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" }, "node-abi": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", - "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.5.0.tgz", + "integrity": "sha512-9g2twBGSP6wIR5PW7tXvAWnEWKJDH/VskdXp168xsw9VVxpEGov8K4jsP4/VeoC7b2ZAyzckvMCuQuQlw44lXg==", "requires": { "semver": "5.4.1" } @@ -6517,6 +6980,11 @@ "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -6578,7 +7046,7 @@ "github-from-package": "0.0.0", "minimist": "1.2.0", "mkdirp": "0.5.1", - "node-abi": "2.4.3", + "node-abi": "2.5.0", "noop-logger": "0.1.1", "npmlog": "4.1.2", "os-homedir": "1.0.2", @@ -7194,6 +7662,11 @@ "nan": "2.10.0" } }, + "scrypt-js": { + "version": "2.0.3", + "resolved": "http://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" + }, "scrypt.js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", @@ -7226,13 +7699,31 @@ "safe-buffer": "5.1.2" } }, - "semaphore": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" - }, - "semver": { - "version": "5.4.1", + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": "1.0.1" + } + } + } + }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "semver": { + "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, @@ -7319,6 +7810,11 @@ } } }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", @@ -7755,6 +8251,14 @@ "strip-bom": "2.0.0" } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -7778,6 +8282,98 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, + "swarm-js": { + "version": "0.1.37", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.37.tgz", + "integrity": "sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ==", + "requires": { + "bluebird": "3.5.1", + "buffer": "5.2.1", + "decompress": "4.2.0", + "eth-lib": "0.1.27", + "fs-extra": "2.1.2", + "fs-promise": "2.0.3", + "got": "7.1.0", + "mime-types": "2.1.19", + "mkdirp-promise": "5.0.1", + "mock-fs": "4.7.0", + "setimmediate": "1.0.5", + "tar.gz": "1.0.7", + "xhr-request-promise": "0.1.2" + }, + "dependencies": { + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0" + } + }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + } + } + }, "symbol-observable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", @@ -7856,12 +8452,22 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" }, + "tar": { + "version": "2.2.1", + "resolved": "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, "tar-fs": { "version": "1.16.3", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", "requires": { - "chownr": "1.0.1", + "chownr": "1.1.1", "mkdirp": "0.5.1", "pump": "1.0.3", "tar-stream": "1.6.1" @@ -7899,6 +8505,25 @@ } } }, + "tar.gz": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tar.gz/-/tar.gz-1.0.7.tgz", + "integrity": "sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg==", + "requires": { + "bluebird": "2.11.0", + "commander": "2.11.0", + "fstream": "1.0.11", + "mout": "0.11.1", + "tar": "2.2.1" + }, + "dependencies": { + "bluebird": { + "version": "2.11.0", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + } + } + }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", @@ -7925,6 +8550,22 @@ "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "requires": { + "any-promise": "1.3.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": "3.3.0" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -8041,6 +8682,184 @@ "solc": "0.4.24" } }, + "truffle-assertions": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/truffle-assertions/-/truffle-assertions-0.6.3.tgz", + "integrity": "sha512-0j8WU7tc4tDhQauiGqgRFOQtH0QLlc/T/jd2KjSrw3kvJxu4IZU0KAdosohN2nFAnrGHF/O4K1da/yEQjwgH7g==", + "requires": { + "assertion-error": "1.1.0", + "web3": "1.0.0-beta.36" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.0.0-beta.36.tgz", + "integrity": "sha512-fZDunw1V0AQS27r5pUN3eOVP7u8YAvyo6vOapdgVRolAu5LgaweP7jncYyLINqIX9ZgWdS5A090bt+ymgaYHsw==", + "requires": { + "web3-bzz": "1.0.0-beta.36", + "web3-core": "1.0.0-beta.36", + "web3-eth": "1.0.0-beta.36", + "web3-eth-personal": "1.0.0-beta.36", + "web3-net": "1.0.0-beta.36", + "web3-shh": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.36.tgz", + "integrity": "sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-requestmanager": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz", + "integrity": "sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz", + "integrity": "sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz", + "integrity": "sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz", + "integrity": "sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-providers-http": "1.0.0-beta.36", + "web3-providers-ipc": "1.0.0-beta.36", + "web3-providers-ws": "1.0.0-beta.36" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz", + "integrity": "sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz", + "integrity": "sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz", + "integrity": "sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz", + "integrity": "sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz", + "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-utils": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.36.tgz", + "integrity": "sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "truffle-events": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/truffle-events/-/truffle-events-0.0.7.tgz", + "integrity": "sha1-K85JudQ6MZHHCBfpljwI3V7Ai9w=", + "requires": { + "abi-decoder": "1.2.0" + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -8167,6 +8986,37 @@ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, + "unbzip2-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz", + "integrity": "sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==", + "requires": { + "buffer": "3.6.0", + "through": "2.3.8" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" + }, + "buffer": { + "version": "3.6.0", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "requires": { + "base64-js": "0.0.8", + "ieee754": "1.1.12", + "isarray": "1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", @@ -8387,54 +9237,118 @@ "xmlhttprequest": "1.8.0" } }, - "web3-core": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.35.tgz", - "integrity": "sha512-ayGavbgVk4KL9Y88Uv411fBJ0SVgVfKhKEBweKYzmP0zOqneMzWt6YsyD1n6kRvjAbqA0AfUPEOKyMNjcx2tjw==", - "requires": { - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-core-requestmanager": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - } - }, - "web3-core-helpers": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz", - "integrity": "sha512-APOu3sEsamyqWt//8o4yq9KF25/uqGm+pQShson/sC4gKzmfJB07fLo2ond0X30E8fIqAPeVCotPXQxGciGUmA==", - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - }, - "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - } - } - }, - "web3-core-method": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz", - "integrity": "sha512-jidImCide8q0GpfsO4L73qoHrbkeWgwU3uOH5DKtJtv0ccmG086knNMRgryb/o9ZgetDWLmDEsJnHjBSoIwcbA==", + "web3-bzz": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.0.0-beta.36.tgz", + "integrity": "sha512-clDRS/ziboJ5ytnrfxq80YSu9HQsT0vggnT3BkoXadrauyEE/9JNLxRu016jjUxqdkfdv4MgIPDdOS3Bv2ghiw==", "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-promievent": "1.0.0-beta.35", - "web3-core-subscriptions": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" + "got": "7.1.0", + "swarm-js": "0.1.37", + "underscore": "1.8.3" }, "dependencies": { - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - } - } - }, - "web3-core-promievent": { + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + } + } + }, + "web3-core": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.35.tgz", + "integrity": "sha512-ayGavbgVk4KL9Y88Uv411fBJ0SVgVfKhKEBweKYzmP0zOqneMzWt6YsyD1n6kRvjAbqA0AfUPEOKyMNjcx2tjw==", + "requires": { + "web3-core-helpers": "1.0.0-beta.35", + "web3-core-method": "1.0.0-beta.35", + "web3-core-requestmanager": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz", + "integrity": "sha512-APOu3sEsamyqWt//8o4yq9KF25/uqGm+pQShson/sC4gKzmfJB07fLo2ond0X30E8fIqAPeVCotPXQxGciGUmA==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-method": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz", + "integrity": "sha512-jidImCide8q0GpfsO4L73qoHrbkeWgwU3uOH5DKtJtv0ccmG086knNMRgryb/o9ZgetDWLmDEsJnHjBSoIwcbA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35", + "web3-core-promievent": "1.0.0-beta.35", + "web3-core-subscriptions": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-core-promievent": { "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz", "integrity": "sha512-GvqXqKq07OmHuVi5uNRg6k79a1/CI0ViCC+EtNv4CORHtDRmYEt5Bvdv6z6FJEiaaQkD0lKbFwNhLxutx7HItw==", @@ -8479,69 +9393,935 @@ } } }, - "web3-eth-abi": { + "web3-eth": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.36.tgz", + "integrity": "sha512-uEa0UnbnNHUB4N2O1U+LsvxzSPJ/w3azy5115IseaUdDaiz6IFFgFfFP3ssauayQNCf7v2F44GXLfPhrNeb/Sw==", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.36", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-eth-abi": "1.0.0-beta.36", + "web3-eth-accounts": "1.0.0-beta.36", + "web3-eth-contract": "1.0.0-beta.36", + "web3-eth-ens": "1.0.0-beta.36", + "web3-eth-iban": "1.0.0-beta.36", + "web3-eth-personal": "1.0.0-beta.36", + "web3-net": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.36.tgz", + "integrity": "sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-requestmanager": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz", + "integrity": "sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz", + "integrity": "sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz", + "integrity": "sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz", + "integrity": "sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-providers-http": "1.0.0-beta.36", + "web3-providers-ipc": "1.0.0-beta.36", + "web3-providers-ws": "1.0.0-beta.36" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz", + "integrity": "sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.36.tgz", + "integrity": "sha512-fBfW+7hvA0rxEMV45fO7JU+0R32ayT7aRwG9Cl6NW2/QvhFeME2qVbMIWw0q5MryPZGIN8A6366hKNuWvVidDg==", + "requires": { + "ethers": "4.0.0-beta.1", + "underscore": "1.8.3", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-eth-accounts": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.36.tgz", + "integrity": "sha512-MmgIlBEZ0ILLWV4+wfMrbeVVMU/VmQnCpgSDcw7wHKOKu47bKncJ6rVqVsUbC6d9F613Rios+Yj2Ua6SCHtmrg==", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.36", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + }, + "dependencies": { + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "xhr-request-promise": "0.1.2" + } + } + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz", + "integrity": "sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz", + "integrity": "sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz", + "integrity": "sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz", + "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-utils": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.36.tgz", + "integrity": "sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz", + "integrity": "sha512-KUDC+EtFFYG8z01ZleKrASdjj327/rtWHzEt6RWsEj7bBa0bGp9nEh+nqdZx/Sdgz1O8tnfFzJlrRcXpfr1vGg==", + "dev": true, + "requires": { + "bn.js": "4.11.6", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + } + } + }, + "web3-eth-accounts": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz", + "integrity": "sha512-duIgRsfht/0kAW/eQ0X9lKtVIykbETrnM2H7EnvplCzPHtQLodpib4o9JXfh9n6ZDgdDC7cuJoiVB9QJg089ew==", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.35", + "web3-core-helpers": "1.0.0-beta.35", + "web3-core-method": "1.0.0-beta.35", + "web3-utils": "1.0.0-beta.35" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "web3-eth-contract": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.36.tgz", + "integrity": "sha512-cywqcIrUsCW4fyqsHdOb24OCC8AnBol8kNiptI+IHRylyCjTNgr53bUbjrXWjmEnear90rO0QhAVjLB1a4iEbQ==", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.36", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-eth-abi": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.36.tgz", + "integrity": "sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-requestmanager": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz", + "integrity": "sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz", + "integrity": "sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz", + "integrity": "sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz", + "integrity": "sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-providers-http": "1.0.0-beta.36", + "web3-providers-ipc": "1.0.0-beta.36", + "web3-providers-ws": "1.0.0-beta.36" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz", + "integrity": "sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.36.tgz", + "integrity": "sha512-fBfW+7hvA0rxEMV45fO7JU+0R32ayT7aRwG9Cl6NW2/QvhFeME2qVbMIWw0q5MryPZGIN8A6366hKNuWvVidDg==", + "requires": { + "ethers": "4.0.0-beta.1", + "underscore": "1.8.3", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz", + "integrity": "sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz", + "integrity": "sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz", + "integrity": "sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz", + "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-utils": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.36.tgz", + "integrity": "sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-eth-ens": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.36.tgz", + "integrity": "sha512-8ZdD7XoJfSX3jNlZHSLe4G837xQ0v5a8cHCcDcd1IoqoY855X9SrIQ0Xdqia9p4mR1YcH1vgmkXY9/3hsvxS7g==", + "requires": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.36", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-eth-abi": "1.0.0-beta.36", + "web3-eth-contract": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.36.tgz", + "integrity": "sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-requestmanager": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz", + "integrity": "sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz", + "integrity": "sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz", + "integrity": "sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz", + "integrity": "sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-providers-http": "1.0.0-beta.36", + "web3-providers-ipc": "1.0.0-beta.36", + "web3-providers-ws": "1.0.0-beta.36" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz", + "integrity": "sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.36.tgz", + "integrity": "sha512-fBfW+7hvA0rxEMV45fO7JU+0R32ayT7aRwG9Cl6NW2/QvhFeME2qVbMIWw0q5MryPZGIN8A6366hKNuWvVidDg==", + "requires": { + "ethers": "4.0.0-beta.1", + "underscore": "1.8.3", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz", + "integrity": "sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz", + "integrity": "sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz", + "integrity": "sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz", + "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-utils": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.36.tgz", + "integrity": "sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, + "web3-eth-iban": { "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz", - "integrity": "sha512-KUDC+EtFFYG8z01ZleKrASdjj327/rtWHzEt6RWsEj7bBa0bGp9nEh+nqdZx/Sdgz1O8tnfFzJlrRcXpfr1vGg==", - "dev": true, + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz", + "integrity": "sha512-H5wkcNcAIc+h/WoDIKv7ZYmrM2Xqu3O7jBQl1IWo73EDVQji+AoB2i3J8tuwI1yZRInRwrfpI3Zuwuf54hXHmQ==", "requires": { "bn.js": "4.11.6", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35", "web3-utils": "1.0.0-beta.35" }, "dependencies": { "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" } } }, - "web3-eth-accounts": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz", - "integrity": "sha512-duIgRsfht/0kAW/eQ0X9lKtVIykbETrnM2H7EnvplCzPHtQLodpib4o9JXfh9n6ZDgdDC7cuJoiVB9QJg089ew==", + "web3-eth-personal": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.36.tgz", + "integrity": "sha512-+oxvhojeWh4C/XtnlYURWRR3F5Cg7bQQNjtN1ZGnouKAZyBLoYDVVJ6OaPiveNtfC9RKnzLikn9/Uqc0xz410A==", "requires": { - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.7", - "scrypt.js": "0.2.0", - "underscore": "1.8.3", - "uuid": "2.0.1", - "web3-core": "1.0.0-beta.35", - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" + "web3-core": "1.0.0-beta.36", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-net": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" }, "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.36.tgz", + "integrity": "sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-requestmanager": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz", + "integrity": "sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz", + "integrity": "sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz", + "integrity": "sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz", + "integrity": "sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-providers-http": "1.0.0-beta.36", + "web3-providers-ipc": "1.0.0-beta.36", + "web3-providers-ws": "1.0.0-beta.36" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz", + "integrity": "sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz", + "integrity": "sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz", + "integrity": "sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz", + "integrity": "sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz", + "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-utils": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.36.tgz", + "integrity": "sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } } } }, - "web3-eth-iban": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz", - "integrity": "sha512-H5wkcNcAIc+h/WoDIKv7ZYmrM2Xqu3O7jBQl1IWo73EDVQji+AoB2i3J8tuwI1yZRInRwrfpI3Zuwuf54hXHmQ==", + "web3-net": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.36.tgz", + "integrity": "sha512-BriXK0Pjr6Hc/VDq1Vn8vyOum4JB//wpCjgeGziFD6jC7Of8YaWC7AJYXje89OckzfcqX1aJyJlBwDpasNkAzQ==", "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.35" + "web3-core": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" }, "dependencies": { "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.36.tgz", + "integrity": "sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-requestmanager": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz", + "integrity": "sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz", + "integrity": "sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz", + "integrity": "sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz", + "integrity": "sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-providers-http": "1.0.0-beta.36", + "web3-providers-ipc": "1.0.0-beta.36", + "web3-providers-ws": "1.0.0-beta.36" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz", + "integrity": "sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz", + "integrity": "sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz", + "integrity": "sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz", + "integrity": "sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz", + "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-utils": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.36.tgz", + "integrity": "sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } } } }, @@ -8597,6 +10377,164 @@ } } }, + "web3-shh": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.0.0-beta.36.tgz", + "integrity": "sha512-bREGHS/WprYFSvGUhyIk8RSpT2Z5SvJOKGBrsUW2nDIMWO6z0Op8E7fzC6GXY2HZfZliAqq6LirbXLgcLRWuPw==", + "requires": { + "web3-core": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-net": "1.0.0-beta.36" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "web3-core": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.36.tgz", + "integrity": "sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-core-requestmanager": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz", + "integrity": "sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz", + "integrity": "sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-core-promievent": "1.0.0-beta.36", + "web3-core-subscriptions": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz", + "integrity": "sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz", + "integrity": "sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "web3-providers-http": "1.0.0-beta.36", + "web3-providers-ipc": "1.0.0-beta.36", + "web3-providers-ws": "1.0.0-beta.36" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz", + "integrity": "sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz", + "integrity": "sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.36" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz", + "integrity": "sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog==", + "requires": { + "web3-core-helpers": "1.0.0-beta.36", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz", + "integrity": "sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz", + "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.36", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-utils": { + "version": "1.0.0-beta.36", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.36.tgz", + "integrity": "sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + } + } + } + }, "web3-utils": { "version": "1.0.0-beta.35", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.35.tgz", @@ -8886,6 +10824,15 @@ } } }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "requires": { + "debug": "2.6.9", + "nan": "2.10.0", + "typedarray-to-buffer": "3.1.5", + "yaeti": "0.0.6" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -9075,6 +11022,15 @@ "lodash.assign": "4.2.0" } }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.1.0" + } + }, "yeoman-environment": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.3.1.tgz", diff --git a/package.json b/package.json index 1f95c3d..c8d43ff 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "solc": "^0.4.23", "solhint": "^1.1.10", "solidity-coverage": "^0.5.0 ", + "truffle-assertions": "^0.6.3", "web3-eth-accounts": "^1.0.0-beta.34" }, "devDependencies": { @@ -37,9 +38,9 @@ "scripts": { "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", "compile": "truffle compile", - "deploy": "truffle deploy --network development", - "depclique": "truffle deploy --network clique", - "test": "truffle test --network clique", + "deploy": "truffle deploy", + "test": "truffle test", + "debug": "truffle debug", "coverage": "solidity-coverage", "lint": "solhint contracts/**/*.sol", "genbin": "solc --overwrite --bin ./contracts/*.sol -o abi", diff --git a/test/clique.js b/test/clique.js new file mode 100644 index 0000000..fc265dc --- /dev/null +++ b/test/clique.js @@ -0,0 +1,346 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const eth_util = require('ethereumjs-util'); +const utils = require('./helpers/utils.js'); +const encoder = require('./helpers/encoder.js'); +const Web3 = require('web3'); +const Web3Utils = require('web3-utils'); +const rlp = require('rlp'); +const truffleAssert = require('truffle-assertions'); +const sha3 = require('js-sha3').keccak_256 + +const Clique = artifacts.require("Clique"); +const MockIon = artifacts.require("MockIon"); +const MockStorage = artifacts.require("MockStorage"); + +const web3 = new Web3(); +const rinkeby = new Web3(); + +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); +rinkeby.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +// Takes a header and private key returning the signed data +// Needs extraData just to be sure of the final byte +signHeader = (headerHash, privateKey, extraData) => { + const sig = eth_util.ecsign(headerHash, privateKey) + if (this._chainId > 0) { + sig.v += this._chainId * 2 + 8 + } + + const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); + const addrBuf = eth_util.pubToAddress(pubKey); + + const newSigBytes = Buffer.concat([sig.r, sig.s]); + let newSig; + + const bytes = utils.hexToBytes(extraData) + const finalByte = bytes.splice(bytes.length-1) + if (finalByte.toString('hex')=="0") { + newSig = newSigBytes.toString('hex') + '00'; + } + if (finalByte.toString('hex')=="1") { + newSig = newSigBytes.toString('hex') + '01'; + } + + return newSig; +} + +const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" +const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" + +const VALIDATORS_START = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; +const VALIDATORS_FINISH = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; +const GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; +const ADD_VALIDATORS_GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; + + +contract('Clique.js', (accounts) => { + const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); + + const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); + + // Fetch genesis from testrpc + const genesisBlock = rinkeby.eth.getBlock(0); + const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + const GENESIS_HASH = genesisBlock.hash; + + it('Deploy Contract', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + let chainId = await ion.chainId(); + + assert.equal(chainId, DEPLOYEDCHAINID); + }) + + describe('Register Chain', () => { + it('Successful Register Chain', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + // Successfully add id of another chain + let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); + let chain = await clique.chains(TESTCHAINID); + + assert(chain); + + // Fail adding id of this chain + await clique.RegisterChain(storage.address, DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + + // Fail adding id of chain already initialised + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + }) + + it('Check Validators', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + // Successfully add id of another chain + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + for (let i = 0; i < VALIDATORS.length; i++) { + let validatorExists = await clique.m_validators(TESTCHAINID, VALIDATORS[i]); + assert(validatorExists); + } + }) + + it('Check Genesis Hash', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + // Successfully add id of another chain + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + let header = await clique.m_blockheaders(TESTCHAINID, GENESIS_HASH); + let blockHeight = header[0]; + + assert.equal(0, blockHeight); + }) + }) + + describe('Submit Block', () => { + it('Authentic Submission Happy Path', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from rinkeby + const block = rinkeby.eth.getBlock(1); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + // Submit block should succeed + const validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = validationReceipt.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("AddedBlock(bytes32)") }); + assert.ok(event, "Stored event not emitted"); + + const recoveredBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, recoveredBlockHash); + + let blockHashExists = await clique.m_blockhashes(TESTCHAINID, block.hash); + assert(blockHashExists); + + let header = await clique.m_blockheaders(TESTCHAINID, block.hash); + + // Separate fetched header info + parentHash = header[2]; + + // Assert that block was persisted correctly + assert.equal(parentHash, block.parentHash); + }) + + // Here the block header is signed off chain but by a a non-whitelisted validator + it('Fail Submit Block unkown validator - SubmitBlock()', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + // Successfully add id of another chain + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from rinkeby + const block = rinkeby.eth.getBlock(1); + + // Alter txHashin the unsigned header concatenation + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeader = rlpHeaders.signed; + const unsignedHeader = rlpHeaders.unsigned; + + // Remove last 65 Bytes of extraData + const extraBytesShort = rlpHeaders.extraBytesShort; + const extraDataSignature = rlpHeaders.extraDataSignature; + const extraDataShort = rlpHeaders.extraDataShort; + + const signedHeaderHash = Web3Utils.sha3(signedHeader); + const unsignedHeaderHash = Web3Utils.sha3(unsignedHeader); + + // Encode and sign the new header + const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); + const newSignedHeaderHash = eth_util.sha3(unsignedHeader); + + const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') + + let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); + + // Append signature to the end of extraData + const sigBytes = utils.hexToBytes(signature.toString('hex')); + const newExtraDataBytes = extraBytesShort.concat(sigBytes); + const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); + + const newSignedHeader = [ + block.parentHash, + block.sha3Uncles, + block.miner, + block.stateRoot, + block.transactionsRoot, + block.receiptsRoot, + block.logsBloom, + Web3Utils.toBN(block.difficulty), + Web3Utils.toBN(block.number), + block.gasLimit, + block.gasUsed, + Web3Utils.toBN(block.timestamp), + newExtraData, // Off-chain signed block + block.mixHash, + block.nonce + ]; + + // Encode the offchain signed header + const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); + const offchainHeaderHash = Web3Utils.sha3(offchainSignedHeader); + + await clique.SubmitBlock(TESTCHAINID, unsignedHeader, offchainSignedHeader, storage.address).should.be.rejected; + + }) + + it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = web3.eth.getBlock(1); + + const rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should fail + await clique.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", rlpHeaders.unsigned, rlpHeaders.signed, storage.address).should.be.rejected; + + }) + + it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from testrpc + const block = rinkeby.eth.getBlock(1); + + const rlpHeaders = encoder.encodeBlockHeader(block); + + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let unsignedHeader = rlpHeaders.rawunsigned; + unsignedHeader[5] = unsignedHeader[5].slice(0, -2) + "fa"; + const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); + const unsignedHeaderHash = Web3Utils.sha3(rlpHeaders.unsigned); + + // Submit block should fail + await clique.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, rlpHeaders.signed, storage.address).should.be.rejected; + + }) + + + + + // This test checks that new validators get added into the validator list as blocks are submitted to the contract. + // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 + // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. + it('Add Validators Through Block Submission', async () => { + const ion = await MockIon.new(DEPLOYEDCHAINID); + const clique = await Clique.new(ion.address); + const storage = await MockStorage.new(ion.address); + + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_START, ADD_VALIDATORS_GENESIS_HASH); + + let voteThreshold = await clique.m_threshold(TESTCHAINID); + assert.equal(voteThreshold, 2); + + let voteProposal = await clique.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Fetch block 873982 from rinkeby + let block = rinkeby.eth.getBlock(873982); + let rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + let validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + console.log("\tGas used to submit block 873982 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873983 from rinkeby + block = rinkeby.eth.getBlock(873983); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + console.log("\tGas used to submit block 873983 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Check proposal is added + voteProposal = await clique.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 1); + + + // Fetch block 873984 from rinkeby + block = rinkeby.eth.getBlock(873984); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + console.log("\tGas used to submit block 873984 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873985 from rinkeby + block = rinkeby.eth.getBlock(873985); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + console.log("\tGas used to submit block 873985 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Fetch block 873986 from rinkeby + block = rinkeby.eth.getBlock(873986); + rlpHeaders = encoder.encodeBlockHeader(block); + + // Submit block should succeed + validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + console.log("\tGas used to submit block 873986 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + + // Check proposal is added + voteProposal = await clique.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Check all new validators are added + for (let i = 0; i < VALIDATORS_FINISH.length; i++) { + let validatorExists = await clique.m_validators(TESTCHAINID, VALIDATORS_FINISH[i]); + assert(validatorExists); + } + + }) + }) +}); diff --git a/test/helpers/encoder.js b/test/helpers/encoder.js index 930169d..d735e7c 100644 --- a/test/helpers/encoder.js +++ b/test/helpers/encoder.js @@ -60,6 +60,8 @@ encoder.encodeBlockHeader = (block) => { return { unsigned: encodedUnsignedHeader, signed: encodedSignedHeader, + rawunsigned: unsignedHeader, + rawsigned: signedHeader, extraDataSignature: extraDataSignature, extraDataShort: extraDataShort, extraBytesShort: extraBytesShort diff --git a/test/ion.js b/test/ion.js index 42152a1..12fda00 100644 --- a/test/ion.js +++ b/test/ion.js @@ -13,12 +13,13 @@ const sha3 = require('js-sha3').keccak_256 // Connect to the Test RPC running const Web3 = require('web3'); const web3 = new Web3(); -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); const Ion = artifacts.require("Ion"); -const Validation = artifacts.require("Validation"); -const TriggerEventVerifier = artifacts.require("TriggerEventVerifier"); -const FunctionEvent = artifacts.require("Function"); +const MockValidation = artifacts.require("MockValidation"); +const MockStorage = artifacts.require("MockStorage"); +//const TriggerEventVerifier = artifacts.require("TriggerEventVerifier"); +//const FunctionEvent = artifacts.require("Function"); require('chai') .use(require('chai-as-promised')) @@ -150,215 +151,66 @@ const GENESIS_HASH = TESTBLOCK.parentHash; contract('Ion.js', (accounts) => { + let ion; + let validation; + let storage; + + beforeEach('setup contract for each test', async function () { + ion = await Ion.new(DEPLOYEDCHAINID); + validation = await MockValidation.new(ion.address); + storage = await MockStorage.new(ion.address); + }) + it('Deploy Ion', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); let chainId = await ion.chainId(); assert.equal(chainId, DEPLOYEDCHAINID); }) - it('Register Chain', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - let chain = await ion.m_chains(TESTCHAINID); - - assert.equal(chain, true); - - // Fail adding id of this chain - await validation.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; - - // Fail adding id of chain already registered - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; - }) - - it('Check Tx Proof', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - const val = await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - - let tx = await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); - - console.log("\tGas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); - }) - - it('Fail Tx Proof', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); + describe('Register Validation', () => { + it('Successful registration', async () => { + // Successfully add id of another chain + let registered = await validation.register.call(); + await validation.register(); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + assert(registered); + }) - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + it('Fail second registration', async () => { + // Successfully add id of another chain + let registered = await validation.register.call(); + await validation.register(); - // Fail with wrong chain ID - await ion.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + assert(registered); - // Fail with wrong block hash - await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + // Fail second attempt to register validation + validation.register.call().should.be.rejected; + }) - // Fail with wrong path - await ion.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, "0xff").should.be.rejected; + it('Fail registration by non-contract', async () => { + ion.registerValidationModule().should.be.rejected; + }) }) - it('Check Receipt Proof', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); + describe('Store Block', () => { + it('Successful Store Block', async () => { + await validation.register(); - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); + const tx = await validation.SubmitBlock(storage.address, TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("AddedBlock(bytes32)") }); + assert.ok(event, "Block not stored"); + }) - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); + it('Fail Store Block by unregistered validation', async () => { + validation.SubmitBlock(storage.address, TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; + }) - nodes = generateTestReceiptRLPNodes(); + it('Fail Store Block by non-contract', async () => { + ion.storeBlock(storage.address, TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; + }) - let tx = await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, "0x"+nodes.toString('hex'), TEST_PATH); - console.log("\tGas used to submit check receipt proof = " + tx.receipt.gasUsed.toString() + " gas"); + it('Fail Store Block with non contract storage address', async () => { + ion.storeBlock(accounts[0], TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; + }) }) - - it('Fail Receipt Proof', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - - // Fail with wrong chain ID - await ion.CheckReceiptProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; - - // Fail with wrong block hash - await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; - - // Fail with wrong path - await ion.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, "0xff").should.be.rejected; - }) - - it('Check Roots Proof', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - - - let tx = await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); - - console.log("\tGas used to submit check roots proof = " + tx.receipt.gasUsed.toString() + " gas"); - }) - - it('Fail Roots Proof', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - - - // Fail with wrong chain ID - await ion.CheckRootsProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected - - // Fail with wrong block hash - await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; - - // Fail with wrong tx nodes - await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_NODES).should.be.rejected; - - // Fail with wrong receipt nodes - await ion.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; - }) - - it('Deploy Function Contract', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - const verifier = await TriggerEventVerifier.new(); - const functionContract = await FunctionEvent.new(ion.address, verifier.address); - }) - - it('Verify Function Execution', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - const verifier = await TriggerEventVerifier.new(); - const functionContract = await FunctionEvent.new(ion.address, verifier.address); - - // Register chain and submit block to Ion - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - - let tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); - - executeEventFound = tx.logs.some(l => { return l.event == "Executed" }); - assert.ok(executeEventFound, "Function did not execute"); - - console.log("\tGas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); - - }) - - it('Fail Function Execution', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - const verifier = await TriggerEventVerifier.new(); - const functionContract = await FunctionEvent.new(ion.address, verifier.address); - - // Register chain and submit block to Ion - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - await validation.SubmitBlock(TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER); - - // Fail with wrong chain ID - await functionContract.verifyAndExecute(DEPLOYEDCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; - - // Fail with wrong block hash - await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; - - // Fail with wrong deployed contract address - await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_CALLED_BY, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; - - // Fail with wrong path - await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, "0xff", TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; - - // Fail with wrong tx nodes - await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; - - // Fail with wrong receipt nodes - await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0", TRIG_CALLED_BY).should.be.rejected; - - // Fail with wrong expected value - await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_DEPLOYED_RINKEBY_ADDR).should.be.rejected; - }) - -}) - -async function verifyReceipts(eP, txHash) { - await eP.getReceiptTrieRoot(txHash).then( (root) => { - console.log("EP RECEIPT Root hash = 0x" + root.toString('hex')) - }) - - var verified; - await eP.getReceiptProof(txHash).then( (proof) => { - verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); - }) - return verified; -} - -function generateTestReceiptRLPNodes() { - let root = Buffer.from("f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080", 'hex'); - second = Buffer.from("f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080", 'hex'); - leaf = Buffer.from("f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e", 'hex'); - - decodedRoot = rlp.decode(root); - decodedSecond = rlp.decode(second); - decodedLeaf = rlp.decode(leaf); - - nodes = rlp.encode([decodedRoot, decodedSecond, decodedLeaf]); - return nodes; -} \ No newline at end of file +}) \ No newline at end of file diff --git a/test/validation.js b/test/validation.js deleted file mode 100644 index c233a43..0000000 --- a/test/validation.js +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2016-2018 Clearmatics Technologies Ltd -// SPDX-License-Identifier: LGPL-3.0+ - -const eth_util = require('ethereumjs-util'); -const utils = require('./helpers/utils.js'); -const encoder = require('./helpers/encoder.js'); -const Web3 = require('web3'); -const Web3Utils = require('web3-utils'); -const rlp = require('rlp'); - -const Validation = artifacts.require("Validation"); -const Ion = artifacts.require("Ion"); - -const web3 = new Web3(); -const rinkeby = new Web3(); - -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501')); -rinkeby.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); - -require('chai') - .use(require('chai-as-promised')) - .should(); - -// Takes a header and private key returning the signed data -// Needs extraData just to be sure of the final byte -signHeader = (headerHash, privateKey, extraData) => { - const sig = eth_util.ecsign(headerHash, privateKey) - if (this._chainId > 0) { - sig.v += this._chainId * 2 + 8 - } - - const pubKey = eth_util.ecrecover(headerHash, sig.v, sig.r, sig.s); - const addrBuf = eth_util.pubToAddress(pubKey); - - const newSigBytes = Buffer.concat([sig.r, sig.s]); - let newSig; - - const bytes = utils.hexToBytes(extraData) - const finalByte = bytes.splice(bytes.length-1) - if (finalByte.toString('hex')=="0") { - newSig = newSigBytes.toString('hex') + '00'; - } - if (finalByte.toString('hex')=="1") { - newSig = newSigBytes.toString('hex') + '01'; - } - - return newSig; -} - -const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" -const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" - -const VALIDATORS_START = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; -const VALIDATORS_FINISH = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0"]; -const GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; -const ADD_VALIDATORS_GENESIS_HASH = "0xf32b505a5ad95dfa88c2bd6904a1ba81a92a1db547dc17f4d7c0f64cf2cddbb1"; - - -contract('Validation.js', (accounts) => { - const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join(''); - - const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); - - // Fetch genesis from testrpc - const genesisBlock = web3.eth.getBlock(0); - const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); - const GENESIS_HASH = genesisBlock.hash; - - it('Deploy Contract', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - let chainId = await ion.chainId(); - - assert.equal(chainId, DEPLOYEDCHAINID); - }) - - it('Register Chain', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - // Successfully add id of another chain - let tx = await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); - let chain = await validation.chains(TESTCHAINID); - - assert.equal(chain, true); - - // Fail adding id of this chain - await validation.RegisterChain(DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; - - // Fail adding id of chain already initialised - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; - }) - - it('Register Chain - Check Validators', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - let validators = await validation.m_validators.call(TESTCHAINID, VALIDATORS[0]); - assert.equal(validators, true); - }) - - - it('Register Chain - Check Genesis Hash', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - // Successfully add id of another chain - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - let header = await validation.m_blockheaders.call(TESTCHAINID, GENESIS_HASH); - let blockHeight = header[0]; - - assert.equal(0, blockHeight); - }) - - it('Authentic Submission Happy Path - SubmitBlock()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - const rlpHeaders = encoder.encodeBlockHeader(block); - const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); - assert.equal(block.hash, signedHeaderHash); - - // Submit block should succeed - const validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - const recoveredBlockHash = await validation.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, recoveredBlockHash); - console.log("\tGas used to submit block = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - let blockHash = await validation.m_blockhashes(TESTCHAINID, block.hash); - assert.equal(blockHash, true); - - let header = await validation.m_blockheaders(TESTCHAINID, block.hash); - - // Separate fetched header info - parentHash = header[2]; - - // Assert that block was persisted correctly - assert.equal(parentHash, block.parentHash); - }) - - // Here the block header is signed off chain but by a a non-whitelisted validator - it('Fail Submit Block unkown validator - SubmitBlock()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - // Alter txHashin the unsigned header concatenation - const signedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; - - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); - - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); - - // Encode and sign the new header - const encodedExtraData = '0x' + rlp.encode(extraDataShort).toString('hex'); - const newSignedHeaderHash = eth_util.sha3(encodedUnsignedHeader); - - const privateKey = Buffer.from('4f35bad50b8b07fff875ec9d4dec6034b1cb0f7d283db4ce7df8fcfaa2030308', 'hex') - - let signature = await signHeader(newSignedHeaderHash, privateKey, block.extraData); - - // Append signature to the end of extraData - const sigBytes = utils.hexToBytes(signature.toString('hex')); - const newExtraDataBytes = extraBytesShort.concat(sigBytes); - const newExtraData = '0x' + utils.bytesToHex(newExtraDataBytes); - - const newSignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - newExtraData, // Off-chain signed block - block.mixHash, - block.nonce - ]; - - // Encode the offchain signed header - const offchainSignedHeader = '0x' + rlp.encode(newSignedHeader).toString('hex'); - const offchainHeaderHash = Web3Utils.sha3(offchainSignedHeader); - - await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, offchainSignedHeader).should.be.rejected; - - }) - - it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - const rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - await validation.SubmitBlock(TESTCHAINID.slice(0, -2) + "ff", rlpHeaders.unsigned, rlpHeaders.signed).should.be.rejected; - - }) - - it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH); - - // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); - - const signedHeader = [ - block.parentHash, -// web3.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - block.extraData, - block.mixHash, - block.nonce - ]; - - // Remove last 65 Bytes of extraData - const extraBytes = utils.hexToBytes(block.extraData); - const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); - const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); - const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); - - const unsignedHeader = [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot.slice(0, -2) + "fa", - block.logsBloom, - Web3Utils.toBN(block.difficulty), - Web3Utils.toBN(block.number), - block.gasLimit, - block.gasUsed, - Web3Utils.toBN(block.timestamp), - extraDataShort, // extraData minus the signature - block.mixHash, - block.nonce - ]; - - const encodedSignedHeader = '0x' + rlp.encode(signedHeader).toString('hex'); - const signedHeaderHash = Web3Utils.sha3(encodedSignedHeader); - assert.equal(block.hash, signedHeaderHash); - - const encodedUnsignedHeader = '0x' + rlp.encode(unsignedHeader).toString('hex'); - const unsignedHeaderHash = Web3Utils.sha3(encodedUnsignedHeader); - - // Submit block should succeed - await validation.SubmitBlock(TESTCHAINID, encodedUnsignedHeader, encodedSignedHeader).should.be.rejected; - - }) - - // This test checks that new validators get added into the validator list as blocks are submitted to the contract. - // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 - // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. - it('Add Validators Through Block Submission', async () => { - const ion = await Ion.new(DEPLOYEDCHAINID); - const validation = await Validation.new(ion.address); - - await validation.RegisterChain(TESTCHAINID, VALIDATORS_START, ADD_VALIDATORS_GENESIS_HASH); - - let voteThreshold = await validation.m_threshold(TESTCHAINID); - assert.equal(voteThreshold, 2); - - let voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(voteProposal, 0); - - // Fetch block 873982 from rinkeby - let block = rinkeby.eth.getBlock(873982); - let rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - let validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873982 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Fetch block 873983 from rinkeby - block = rinkeby.eth.getBlock(873983); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873983 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Check proposal is added - voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(voteProposal, 1); - - - // Fetch block 873984 from rinkeby - block = rinkeby.eth.getBlock(873984); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873984 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Fetch block 873985 from rinkeby - block = rinkeby.eth.getBlock(873985); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873985 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Fetch block 873986 from rinkeby - block = rinkeby.eth.getBlock(873986); - rlpHeaders = encoder.encodeBlockHeader(block); - - // Submit block should succeed - validationReceipt = await validation.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed); - console.log("\tGas used to submit block 873986 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); - - // Check proposal is added - voteProposal = await validation.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(voteProposal, 0); - - // Check all new validators are added - let validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[0]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[1]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[2]); - assert.equal(validators, true); - validators = await validation.m_validators(TESTCHAINID, VALIDATORS_FINISH[3]); - assert.equal(validators, true); - }) -}); diff --git a/truffle.js b/truffle.js index f7d55b7..d4f5e8f 100644 --- a/truffle.js +++ b/truffle.js @@ -3,6 +3,7 @@ module.exports = { development: { host: "localhost", port: 8545, + gas: 0xFFFFFFFFFFF, network_id: "*" }, clique: { From a48114190eaf602eff880b5ff267b4e1e09f7cbd Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 8 Nov 2018 19:29:47 +0000 Subject: [PATCH 154/203] Ethereum storage tests included. Ethereum storage + clique validation integration with event consumption tests working. --- contracts/storage/EthereumStore.sol | 206 ++++++++ test/clique.js | 44 +- test/integration-clique_ethereum.js | 696 ++++++++++++++++++++++++++++ test/storage-ethereum.js | 399 ++++++++++++++++ 4 files changed, 1312 insertions(+), 33 deletions(-) create mode 100644 contracts/storage/EthereumStore.sol create mode 100644 test/integration-clique_ethereum.js create mode 100644 test/storage-ethereum.js diff --git a/contracts/storage/EthereumStore.sol b/contracts/storage/EthereumStore.sol new file mode 100644 index 0000000..c82de31 --- /dev/null +++ b/contracts/storage/EthereumStore.sol @@ -0,0 +1,206 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.24; + +import "../libraries/ECVerify.sol"; +import "../libraries/RLP.sol"; +import "../libraries/PatriciaTrie.sol"; +import "../libraries/SolidityUtils.sol"; +import "./BlockStore.sol"; + +contract EthereumStore is BlockStore { + using RLP for RLP.RLPItem; + using RLP for RLP.Iterator; + using RLP for bytes; + + /* + * @description BlockHeader struct containing trie root hashes for tx verifications + */ + struct BlockHeader { + bytes32 txRootHash; + bytes32 receiptRootHash; + } + + mapping (bytes32 => bool) public m_blockhashes; + mapping (bytes32 => BlockHeader) public m_blockheaders; + + enum ProofType { TX, RECEIPT, ROOTS } + + event BlockAdded(bytes32 chainID, bytes32 blockHash); + event VerifiedProof(bytes32 chainId, bytes32 blockHash, uint proofType); + + constructor(address _ionAddr) BlockStore(_ionAddr) public {} + + /* + * onlyExistingBlocks + * param: _id (bytes32) Unique id of chain supplied to function + * param: _hash (bytes32) Block hash which needs validation + * + * Modifier that checks if the provided block hash has been verified by the validation contract + */ + modifier onlyExistingBlocks(bytes32 _hash) { + require(m_blockhashes[_hash], "Block does not exist for chain"); + _; + } + + + /* + * @description when a block is submitted the header must be added to a mapping of blockhashes and m_chains to blockheaders + * @param _chainId ID of the chain the block is from + * @param _blockHash Block hash of the block being added + * @param _blockBlob Bytes blob of the RLP-encoded block header being added + */ + function addBlock(bytes32 _chainId, bytes32 _blockHash, bytes _blockBlob) + onlyIon + onlyRegisteredChains(_chainId) + { + require(!m_blockhashes[_blockHash], "Block already exists" ); + RLP.RLPItem[] memory header = _blockBlob.toRLPItem().toList(); + + bytes32 hashedHeader = keccak256(_blockBlob); + require(hashedHeader == _blockHash, "Hashed header does not match submitted block hash!"); + + m_blockhashes[_blockHash] = true; + m_blockheaders[_blockHash].txRootHash = header[4].toBytes32(); + m_blockheaders[_blockHash].receiptRootHash = header[5].toBytes32(); + + emit BlockAdded(_chainId, _blockHash); + } + + /* + * CheckTxProof + * param: _id (bytes32) Unique id of chain submitting block from + * param: _blockHash (bytes32) Block hash of block being submitted + * param: _value (bytes) RLP-encoded transaction object array with fields defined as: https://github.com/ethereumjs/ethereumjs-tx/blob/0358fad36f6ebc2b8bea441f0187f0ff0d4ef2db/index.js#L50 + * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove + * param: _path (bytes) Byte array of the path to the node to be proved + * + * emits: VerifiedTxProof(chainId, blockHash, proofType) + * chainId: (bytes32) hash of the chain verifying proof against + * blockHash: (bytes32) hash of the block verifying proof against + * proofType: (uint) enum of proof type + * + * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution + * of this function to only allow if the chain the proof is for is registered to this contract and if the block that + * the proof is for has been submitted. + */ + function CheckTxProof( + bytes32 _id, + bytes32 _blockHash, + bytes _value, + bytes _parentNodes, + bytes _path + ) + onlyRegisteredChains(_id) + onlyExistingBlocks(_blockHash) + public + returns (bool) + { + verifyProof(_value, _parentNodes, _path, m_blockheaders[_blockHash].txRootHash); + + emit VerifiedProof(_id, _blockHash, uint(ProofType.TX)); + return true; + } + + /* + * CheckReceiptProof + * param: _id (bytes32) Unique id of chain submitting block from + * param: _blockHash (bytes32) Block hash of block being submitted + * param: _value (bytes) RLP-encoded receipt object array with fields defined as: https://github.com/ethereumjs/ethereumjs-tx/blob/0358fad36f6ebc2b8bea441f0187f0ff0d4ef2db/index.js#L50 + * param: _parentNodes (bytes) RLP-encoded array of all relevant nodes from root node to node to prove + * param: _path (bytes) Byte array of the path to the node to be proved + * + * emits: VerifiedTxProof(chainId, blockHash, proofType) + * chainId: (bytes32) hash of the chain verifying proof against + * blockHash: (bytes32) hash of the block verifying proof against + * proofType: (uint) enum of proof type + * + * All data associated with the proof must be constructed and paddChainrovided to this function. Modifiers restrict execution + * of this function to only allow if the chain the proof is for is registered to this contract and if the block that + * the proof is for has been submitted. + */ + function CheckReceiptProof( + bytes32 _id, + bytes32 _blockHash, + bytes _value, + bytes _parentNodes, + bytes _path + ) + onlyRegisteredChains(_id) + onlyExistingBlocks(_blockHash) + public + returns (bool) + { + verifyProof(_value, _parentNodes, _path, m_blockheaders[_blockHash].receiptRootHash); + + emit VerifiedProof(_id, _blockHash, uint(ProofType.RECEIPT)); + return true; + } + + /* + * CheckRootsProof + * param: _id (bytes32) Unique id of chain submitting block from + * param: _blockHash (bytes32) Block hash of block being submitted + * param: _txNodes (bytes) RLP-encoded relevant nodes of the Tx trie + * param: _receiptNodes (bytes) RLP-encoded relevant nodes of the Receipt trie + * + * emits: VerifiedTxProof(chainId, blockHash, proofType) + * chainId: (bytes32) hash of the chain verifying proof against + * blockHash: (bytes32) hash of the block verifying proof against + * proofType: (uint) enum of proof type + * + * All data associated with the proof must be constructed and provided to this function. Modifiers restrict execution + * of this function to only allow if the chain the proof is for is registered to this contract and if the block that + * the proof is for has been submitted. + */ + function CheckRootsProof( + bytes32 _id, + bytes32 _blockHash, + bytes _txNodes, + bytes _receiptNodes + ) + onlyRegisteredChains(_id) + onlyExistingBlocks(_blockHash) + public + returns (bool) + { + assert( m_blockheaders[_blockHash].txRootHash == getRootNodeHash(_txNodes) ); + assert( m_blockheaders[_blockHash].receiptRootHash == getRootNodeHash(_receiptNodes) ); + + emit VerifiedProof(_id, _blockHash, uint(ProofType.ROOTS)); + return true; + } + + /* + * Verify proof assertion to avoid stack to deep error (it doesn't show during compile time but it breaks + * blockchain simulator) + */ + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _hash) { + assert( PatriciaTrie.verifyProof(_value, _parentNodes, _path, _hash) ); + } + +/* +======================================================================================================================== + + Helper Functions + +======================================================================================================================== +*/ + + /* + * @description returns the root node of an RLP encoded Patricia Trie + * @param _rlpNodes RLP encoded trie + * @returns root hash + */ + function getRootNodeHash(bytes _rlpNodes) private returns (bytes32) { + RLP.RLPItem memory nodes = RLP.toRLPItem(_rlpNodes); + RLP.RLPItem[] memory nodeList = RLP.toList(nodes); + + bytes memory b_nodeRoot = RLP.toBytes(nodeList[0]); + + return keccak256(b_nodeRoot); + } + + +} + diff --git a/test/clique.js b/test/clique.js index fc265dc..cc43f8e 100644 --- a/test/clique.js +++ b/test/clique.js @@ -68,10 +68,18 @@ contract('Clique.js', (accounts) => { const genesisBlock = rinkeby.eth.getBlock(0); const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); const GENESIS_HASH = genesisBlock.hash; + + let ion; + let clique; + let storage; + + beforeEach('setup contract for each test', async function () { + ion = await MockIon.new(DEPLOYEDCHAINID); + clique = await Clique.new(ion.address); + storage = await MockStorage.new(ion.address); + }) it('Deploy Contract', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); let chainId = await ion.chainId(); assert.equal(chainId, DEPLOYEDCHAINID); @@ -79,10 +87,6 @@ contract('Clique.js', (accounts) => { describe('Register Chain', () => { it('Successful Register Chain', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); - // Successfully add id of another chain let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); @@ -98,10 +102,6 @@ contract('Clique.js', (accounts) => { }) it('Check Validators', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); - // Successfully add id of another chain await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -112,10 +112,6 @@ contract('Clique.js', (accounts) => { }) it('Check Genesis Hash', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); - // Successfully add id of another chain await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -128,10 +124,6 @@ contract('Clique.js', (accounts) => { describe('Submit Block', () => { it('Authentic Submission Happy Path', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from rinkeby @@ -163,10 +155,6 @@ contract('Clique.js', (accounts) => { // Here the block header is signed off chain but by a a non-whitelisted validator it('Fail Submit Block unkown validator - SubmitBlock()', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); - // Successfully add id of another chain await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -226,10 +214,6 @@ contract('Clique.js', (accounts) => { }) it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); // Fetch block 1 from testrpc @@ -243,9 +227,7 @@ contract('Clique.js', (accounts) => { }) it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -274,10 +256,6 @@ contract('Clique.js', (accounts) => { // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. it('Add Validators Through Block Submission', async () => { - const ion = await MockIon.new(DEPLOYEDCHAINID); - const clique = await Clique.new(ion.address); - const storage = await MockStorage.new(ion.address); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_START, ADD_VALIDATORS_GENESIS_HASH); let voteThreshold = await clique.m_threshold(TESTCHAINID); diff --git a/test/integration-clique_ethereum.js b/test/integration-clique_ethereum.js new file mode 100644 index 0000000..c836911 --- /dev/null +++ b/test/integration-clique_ethereum.js @@ -0,0 +1,696 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Web3Utils = require('web3-utils'); +const utils = require('./helpers/utils.js'); +const BN = require('bignumber.js') +const encoder = require('./helpers/encoder.js') +const rlp = require('rlp'); +const async = require('async') +const levelup = require('levelup'); +const sha3 = require('js-sha3').keccak_256 + +// Connect to the Test RPC running +const Web3 = require('web3'); +const web3 = new Web3(); +const rinkeby = new Web3(); +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); +rinkeby.setProvider(new web3.providers.HttpProvider('https://rinkeby.infura.io')); + +const Ion = artifacts.require("Ion"); +const Clique = artifacts.require("Clique"); +const EthereumStore = artifacts.require("EthereumStore"); + +const TriggerEventVerifier = artifacts.require("TriggerEventVerifier"); +const FunctionEvent = artifacts.require("Function"); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" +const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" + +/* +TESTRPC TEST DATA +*/ + +const TESTBLOCK = { + difficulty: 2, + extraData: '0xd68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100', + gasLimit: 7509409, + gasUsed: 2883490, + hash: '0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7', + logsBloom: '0x22440000020000090000000000000000041000080000008000088000080000000200000400000800000000000000400000000000000000000010000008020102000000000000080000000008800000000000022000000004000000010000000000080000000620400440100010200400082000000000000080040010000100020020000000000000080080000001000000000100000400480000000002000000002000080018000008108000100000000000000000020000050010001004000000000102000040004000000000000000000000004400000000000000000000000208000000000400008200020000004022400000000004000200848000000000', + miner: '0x0000000000000000000000000000000000000000', + mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x0000000000000000', + number: 2657422, + parentHash: '0x3471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35', + receiptsRoot: '0x907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ff', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: 4848, + stateRoot: '0xf526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444', + timestamp: 1531931421, + totalDifficulty: 5023706, + transactions: + [ '0x7adbc5ee3712552a1e85962c3ea3d82394cfed7960d60c12d60ebafe67445450', + '0x6be870e6dfb11894b64371560ec39e563cef91642afd193bfa67874f3508a282', + '0x5ba6422455cb7127958df15c453bfe60d92921b647879864b531fd6589e36af4', + '0xa2597e6fe6882626e12055b1378025aa64a85a03dd23f5dc66034f2ef3746810', + '0x7ffb940740050ae3604f99a4eef07c83de5d75076cae42cb1561c370cba3a0a3', + '0x4d6326a6d4cf606c7e44a4ae6710acd3876363bcaabd1b1b59d29fff4da223c5', + '0x10b3360ef00cd7c4faf826365fddbd33938292c98c55a4cdb37194a142626f63', + '0x655290cb44be2e64d3b1825a86d5647579015c5cffb03ede7f67eb34cea6b97f', + '0x6b5e025ea558f4872112a39539ce9a819bfbb795b04eefcc45e1cf5ea947614c', + '0xefd68b516babcf8a4ca74a358cfca925d9d2d5177ef7b859f3d9183ff522efe8', + '0xa056eeeeb098fd5adb283e12e77a239797c96860c21712963f183937613d3391', + '0xa5d1adf694e3442975a13685a9c7d9013c05a4fdcea5bc827566a331b2fead2b', + '0x95a47360f89c48f0b1a484cbeee8816b6a0e2fc321bdb9db48082bd7272b4ebc', + '0x896d29a87393c6607844fa545d38eb96056d5310a6b4e056dc00adde67c24be2', + '0xef3ce2ad9259920094f7fd5ad00453b35888662696ae9b85a393e55cde3ec28d', + '0x2de8af9b4e84b3ac93adfce81964cc69bafd0a2dbcac3a5f7628ee9e56fd1c8a', + '0x2790cdb3377f556e8f5bc8eaaf9c6c0d36d0f242c2e4226af2aac0203f43019b', + '0x98ae65246249785bd1ac8157900f7e1a2c69d5c3b3ffc97d55b9eacab3e212f0', + '0x7d4f090c58880761eaaab1399864d4a52631db8f0b21bfb7051f9a214ad07993', + '0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e', + '0x2af8f6c49d1123077f1efd13764cb2a50ff922fbaf49327efc44c6048c38c968', + '0x6d5e1753dc91dae7d528ab9b02350e726e006a5591a5d315a34a46e2a951b3fb', + '0xdc864827159c7fde6bbd1672ed9a90ce5d69f5d0c81761bf689775d19a90387e', + '0x22fb4d90a7125988b2857c50709e544483f898cb1e8036477f9ddd94b177bf93', + '0x999c2e2ba342bed4ccedea01d638db3bbd1abd6d10784c317843880841db6dec', + '0x11355abb5fe745ed458b2a78e116f4a8c2fe046a131eafe08f30d23bd9d10394' ], + transactionsRoot: '0x07f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586', + uncles: [] +} + +const VALIDATORS_B2657422 = [ + "0x42eb768f2244c8811c63729a21a3569731535f06", + "0x6635f83421bf059cd8111f180f0727128685bae4", + "0x7ffc57839b00206d1ad20c69a1981b489f772031", + "0xb279182d99e65703f0076e4812653aab85fca0f0", + "0xd6ae8250b8348c94847280928c79fb3b63ca453e", + "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", + "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"] + +const signedHeader = [ + TESTBLOCK.parentHash, + TESTBLOCK.sha3Uncles, + TESTBLOCK.miner, + TESTBLOCK.stateRoot, + TESTBLOCK.transactionsRoot, + TESTBLOCK.receiptsRoot, + TESTBLOCK.logsBloom, + Web3Utils.toBN(TESTBLOCK.difficulty), + Web3Utils.toBN(TESTBLOCK.number), + TESTBLOCK.gasLimit, + TESTBLOCK.gasUsed, + Web3Utils.toBN(TESTBLOCK.timestamp), + TESTBLOCK.extraData, + TESTBLOCK.mixHash, + TESTBLOCK.nonce + ]; + +// Remove last 65 Bytes of extraData +const extraBytes = utils.hexToBytes(TESTBLOCK.extraData); +const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); +const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + +const unsignedHeader = [ + TESTBLOCK.parentHash, + TESTBLOCK.sha3Uncles, + TESTBLOCK.miner, + TESTBLOCK.stateRoot, + TESTBLOCK.transactionsRoot, + TESTBLOCK.receiptsRoot, + TESTBLOCK.logsBloom, + Web3Utils.toBN(TESTBLOCK.difficulty), + Web3Utils.toBN(TESTBLOCK.number), + TESTBLOCK.gasLimit, + TESTBLOCK.gasUsed, + Web3Utils.toBN(TESTBLOCK.timestamp), + extraDataShort, // extraData minus the signature + TESTBLOCK.mixHash, + TESTBLOCK.nonce + ]; + +const TEST_SIGNED_HEADER = '0x' + rlp.encode(signedHeader).toString('hex'); +const signedHeaderHash = Web3Utils.sha3(TEST_SIGNED_HEADER); + +const TEST_UNSIGNED_HEADER = '0x' + rlp.encode(unsignedHeader).toString('hex'); +const unsignedHeaderHash = Web3Utils.sha3(TEST_UNSIGNED_HEADER); + +const TESTRLPENCODING = "0xf9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +const TEST_PATH = "0x13" + +const TEST_TX_VALUE = "0xf86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" +const TEST_TX_NODES = "0xf90235f871a0804f9c841a6a1d3361d79980581c84e5b4d3e4c9bf33951346775542d0ee0728a0edadb5e660118ea4323654191131b62c81fc00203a15a21c925f9f50d0e4b3e4808080808080a03eda2d64b94c5ed45026a29c75c99677d44c561ea5efea30c1db6299871d5c2e8080808080808080f90151a0bc285699e68d2fe18e7af2cdf7e7e6456e91a3fd31e3c9935bc5bef92e94bf4ba06eb963b2c3a3b6c07a7221aa6f6f86f7cb8ddb45ab1ff1a9dc781f34da1f081fa0deea5b5566e7a5634d91c5fb56e25f4370e3531e2fd71ee17ed6c4ad0be2ced3a0b4e9d14555f162e811cfbcbff9b98a271a197b75271565f693912c2ff75e2131a03b0bc2d764fbefd76848ee2da7b211eb230ede08d8c54e6a868be9f5e42122c1a0b6dd488ad4fb82b0a98dff81ac6766d1dec26b29dc06174de1d315b0ab0bdf0ca066c20ff06dc33777f53eec32b0b9a8d99872bec24bb3998bb520ae6897c21d7ea02db2a399f611ba7993efb4768938a6f61b4add8959ce4c89f201f41e882ff375a02e31051a9f938b9b342b8070db3dd829f62da8d0c83a6dff91a4e3b4cb2adb9ea090e75708e7dbf856b75ed126a960085419fcde0e6a0129a92dffc0cb83ac089680808080808080f86c20b869f86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" + +const TEST_RECEIPT_VALUE = "0xf901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" +const TEST_RECEIPT_NODES = "0xf90335f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" + +const TRIG_DEPLOYED_RINKEBY_ADDR = "0x61621bcf02914668f8404c1f860e92fc1893f74c"; +const TRIG_FIRED_RINKEBY_TXHASH = "0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e" +const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 +const TRIG_CALLED_BY = "0x279884e133f9346f2fad9cc158222068221b613e"; + +const TRIG_GENESIS_HASH = TESTBLOCK.parentHash; + + +contract('Clique-Ethereum Integration', (accounts) => { + const genesisBlock = rinkeby.eth.getBlock(0); + const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + const GENESIS_HASH = genesisBlock.hash; + + let ion; + let clique; + let storage; + + beforeEach('setup contract for each test', async function () { + ion = await Ion.new(DEPLOYEDCHAINID); + clique = await Clique.new(ion.address); + storage = await EthereumStore.new(ion.address); + }) + + describe('Register Clique Module', () => { + it('Successful Register', async () => { + await clique.register(); + }) + + it('Fail Register Twice', async () => { + await clique.register(); + await clique.register().should.be.rejected; + }) + }) + + describe('Register Chain', () => { + it('Successful Register Chain', async () => { + await clique.register(); + + let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); + let chain = await clique.chains(TESTCHAINID); + + assert(chain); + }) + + it('Fail Register Twice', async () => { + await clique.register(); + + let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); + let chain = await clique.chains(TESTCHAINID); + + assert(chain); + + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + }) + + it('Fail Register Deployment Chain', async () => { + await clique.register(); + let tx = await clique.RegisterChain(storage.address, DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + }) + + it('Fail Register Chain without registering clique module', async () => { + let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + }) + }) + + describe('Add Block', () => { + it('Successful Add Block', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from rinkeby + const block = rinkeby.eth.getBlock(1); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + }) + + it('Successful Add Block from different genesis', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + }) + + it('Fail Add Block with unregistered chain id', async () => { + await clique.register(); +// await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 1 from rinkeby + const block = rinkeby.eth.getBlock(1); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address).should.be.rejected; + }) + + it('Fail Add Block with non-sequential block', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + + // Fetch block 2 from rinkeby instead of block 1 + const block = rinkeby.eth.getBlock(2); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address).should.be.rejected; + }) + + it('Fail Add Block from non-clique', async () => { + // Fetch block 1 from rinkeby + const block = rinkeby.eth.getBlock(1); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + // Fail direct adding of block to storage + await storage.addBlock(TESTCHAINID, block.hash, rlpHeaders.unsigned).should.be.rejected; + }) + }) + + describe('Check Tx Proof of Tx 0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e on Rinkeby', () => { + it('Successful Check Tx Proof', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + tx = await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); + console.log("\tGas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Tx Proof with wrong tx value', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Tx Proof with wrong tx nodes', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Tx Proof with wrong path', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, '0x10').should.be.rejected; + }) + }) + + describe('Check Receipt Proof of Tx 0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e on Rinkeby', () => { + it('Successful Check Receipt Proof', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + tx = await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH); + console.log("\tGas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Receipt Proof with wrong receipt value', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Receipt Proof with wrong receipt nodes', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Receipt Proof with wrong path', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + + await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, '0x10').should.be.rejected; + }) + }) + + describe('Check Roots Proof', () => { + it('Successful Check Roots Proof', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + tx = await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); + console.log("\tGas used to submit check roots proof = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Roots Proof with wrong chain id', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + // Fail with wrong chain ID + await storage.CheckRootsProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; + }) + + it('Fail Roots Proof with wrong block hash', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + // Fail with wrong block hash + await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; + }) + + it('Fail Roots Proof with wrong tx nodes', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + // Fail with wrong tx nodes + await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_NODES).should.be.rejected; + }) + + it('Fail Roots Proof with wrong receipt nodes', async () => { + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + // Fail with wrong receipt nodes + await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; + }) + }) + + describe('Event Consumption Contract', () => { + it('Deploy Function Contract', async () => { + const verifier = await TriggerEventVerifier.new(); + const functionContract = await FunctionEvent.new(storage.address, verifier.address); + }) + + it('Submit Block, verify tx and event, and execute', async () => { + const verifier = await TriggerEventVerifier.new(); + const functionContract = await FunctionEvent.new(storage.address, verifier.address); + + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); + event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("Executed()") }); + assert.ok(event, "Executed event not emitted"); + + console.log("\tGas used to verify all proofs against ion, verify logs against the verifier and execute the function = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Function Execution', async () => { + const verifier = await TriggerEventVerifier.new(); + const functionContract = await FunctionEvent.new(storage.address, verifier.address); + + await clique.register(); + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + + // Fetch block 2657422 from rinkeby + const block = rinkeby.eth.getBlock(TESTBLOCK.number); + + const rlpHeaders = encoder.encodeBlockHeader(block); + const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); + assert.equal(block.hash, signedHeaderHash); + + let tx = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); + let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); + assert.ok(event, "BlockAdded event not emitted"); + + const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); + assert.equal(signedHeaderHash, latestBlockHash); + + // Fail with wrong chain ID + await functionContract.verifyAndExecute(DEPLOYEDCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong block hash + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong deployed contract address + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_CALLED_BY, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong path + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, "0xff", TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong tx nodes + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong receipt nodes + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0", TRIG_CALLED_BY).should.be.rejected; + + // Fail with wrong expected event parameter + await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_DEPLOYED_RINKEBY_ADDR).should.be.rejected; + }) + }) +}) + +async function verifyReceipts(eP, txHash) { + await eP.getReceiptTrieRoot(txHash).then( (root) => { + console.log("EP RECEIPT Root hash = 0x" + root.toString('hex')) + }) + + var verified; + await eP.getReceiptProof(txHash).then( (proof) => { + verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); + }) + return verified; +} + +function generateTestReceiptRLPNodes() { + let root = Buffer.from("f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080", 'hex'); + second = Buffer.from("f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080", 'hex'); + leaf = Buffer.from("f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e", 'hex'); + + decodedRoot = rlp.decode(root); + decodedSecond = rlp.decode(second); + decodedLeaf = rlp.decode(leaf); + + nodes = rlp.encode([decodedRoot, decodedSecond, decodedLeaf]); + return nodes; +} \ No newline at end of file diff --git a/test/storage-ethereum.js b/test/storage-ethereum.js new file mode 100644 index 0000000..447129d --- /dev/null +++ b/test/storage-ethereum.js @@ -0,0 +1,399 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Web3Utils = require('web3-utils'); +const utils = require('./helpers/utils.js'); +const BN = require('bignumber.js') +const encoder = require('./helpers/encoder.js') +const rlp = require('rlp'); +const async = require('async') +const levelup = require('levelup'); +const sha3 = require('js-sha3').keccak_256 + +// Connect to the Test RPC running +const Web3 = require('web3'); +const web3 = new Web3(); +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); + +const MockIon = artifacts.require("MockIon"); +const MockValidation = artifacts.require("MockValidation"); +const EthereumStore = artifacts.require("EthereumStore"); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" + +const TESTCHAINID = "0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254" + +/* +TESTRPC TEST DATA +*/ +const block = web3.eth.getBlock(1); + +const TESTBLOCK = { + difficulty: 2, + extraData: '0xd68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100', + gasLimit: 7509409, + gasUsed: 2883490, + hash: '0x694752333dd1bd0f806cc6ef1063162f4f330c88f9dcd9e61174fcf5e4927eb7', + logsBloom: '0x22440000020000090000000000000000041000080000008000088000080000000200000400000800000000000000400000000000000000000010000008020102000000000000080000000008800000000000022000000004000000010000000000080000000620400440100010200400082000000000000080040010000100020020000000000000080080000001000000000100000400480000000002000000002000080018000008108000100000000000000000020000050010001004000000000102000040004000000000000000000000004400000000000000000000000208000000000400008200020000004022400000000004000200848000000000', + miner: '0x0000000000000000000000000000000000000000', + mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x0000000000000000', + number: 2657422, + parentHash: '0x3471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35', + receiptsRoot: '0x907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ff', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: 4848, + stateRoot: '0xf526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444', + timestamp: 1531931421, + totalDifficulty: 5023706, + transactions: + [ '0x7adbc5ee3712552a1e85962c3ea3d82394cfed7960d60c12d60ebafe67445450', + '0x6be870e6dfb11894b64371560ec39e563cef91642afd193bfa67874f3508a282', + '0x5ba6422455cb7127958df15c453bfe60d92921b647879864b531fd6589e36af4', + '0xa2597e6fe6882626e12055b1378025aa64a85a03dd23f5dc66034f2ef3746810', + '0x7ffb940740050ae3604f99a4eef07c83de5d75076cae42cb1561c370cba3a0a3', + '0x4d6326a6d4cf606c7e44a4ae6710acd3876363bcaabd1b1b59d29fff4da223c5', + '0x10b3360ef00cd7c4faf826365fddbd33938292c98c55a4cdb37194a142626f63', + '0x655290cb44be2e64d3b1825a86d5647579015c5cffb03ede7f67eb34cea6b97f', + '0x6b5e025ea558f4872112a39539ce9a819bfbb795b04eefcc45e1cf5ea947614c', + '0xefd68b516babcf8a4ca74a358cfca925d9d2d5177ef7b859f3d9183ff522efe8', + '0xa056eeeeb098fd5adb283e12e77a239797c96860c21712963f183937613d3391', + '0xa5d1adf694e3442975a13685a9c7d9013c05a4fdcea5bc827566a331b2fead2b', + '0x95a47360f89c48f0b1a484cbeee8816b6a0e2fc321bdb9db48082bd7272b4ebc', + '0x896d29a87393c6607844fa545d38eb96056d5310a6b4e056dc00adde67c24be2', + '0xef3ce2ad9259920094f7fd5ad00453b35888662696ae9b85a393e55cde3ec28d', + '0x2de8af9b4e84b3ac93adfce81964cc69bafd0a2dbcac3a5f7628ee9e56fd1c8a', + '0x2790cdb3377f556e8f5bc8eaaf9c6c0d36d0f242c2e4226af2aac0203f43019b', + '0x98ae65246249785bd1ac8157900f7e1a2c69d5c3b3ffc97d55b9eacab3e212f0', + '0x7d4f090c58880761eaaab1399864d4a52631db8f0b21bfb7051f9a214ad07993', + '0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e', + '0x2af8f6c49d1123077f1efd13764cb2a50ff922fbaf49327efc44c6048c38c968', + '0x6d5e1753dc91dae7d528ab9b02350e726e006a5591a5d315a34a46e2a951b3fb', + '0xdc864827159c7fde6bbd1672ed9a90ce5d69f5d0c81761bf689775d19a90387e', + '0x22fb4d90a7125988b2857c50709e544483f898cb1e8036477f9ddd94b177bf93', + '0x999c2e2ba342bed4ccedea01d638db3bbd1abd6d10784c317843880841db6dec', + '0x11355abb5fe745ed458b2a78e116f4a8c2fe046a131eafe08f30d23bd9d10394' ], + transactionsRoot: '0x07f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586', + uncles: [] +} + +const VALIDATORS = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"] + +const signedHeader = [ + TESTBLOCK.parentHash, + TESTBLOCK.sha3Uncles, + TESTBLOCK.miner, + TESTBLOCK.stateRoot, + TESTBLOCK.transactionsRoot, + TESTBLOCK.receiptsRoot, + TESTBLOCK.logsBloom, + Web3Utils.toBN(TESTBLOCK.difficulty), + Web3Utils.toBN(TESTBLOCK.number), + TESTBLOCK.gasLimit, + TESTBLOCK.gasUsed, + Web3Utils.toBN(TESTBLOCK.timestamp), + TESTBLOCK.extraData, + TESTBLOCK.mixHash, + TESTBLOCK.nonce + ]; + +// Remove last 65 Bytes of extraData +const extraBytes = utils.hexToBytes(TESTBLOCK.extraData); +const extraBytesShort = extraBytes.splice(1, extraBytes.length-66); +const extraDataSignature = '0x' + utils.bytesToHex(extraBytes.splice(extraBytes.length-65)); +const extraDataShort = '0x' + utils.bytesToHex(extraBytesShort); + +const unsignedHeader = [ + TESTBLOCK.parentHash, + TESTBLOCK.sha3Uncles, + TESTBLOCK.miner, + TESTBLOCK.stateRoot, + TESTBLOCK.transactionsRoot, + TESTBLOCK.receiptsRoot, + TESTBLOCK.logsBloom, + Web3Utils.toBN(TESTBLOCK.difficulty), + Web3Utils.toBN(TESTBLOCK.number), + TESTBLOCK.gasLimit, + TESTBLOCK.gasUsed, + Web3Utils.toBN(TESTBLOCK.timestamp), + extraDataShort, // extraData minus the signature + TESTBLOCK.mixHash, + TESTBLOCK.nonce + ]; + +const TEST_SIGNED_HEADER = '0x' + rlp.encode(signedHeader).toString('hex'); +const signedHeaderHash = Web3Utils.sha3(TEST_SIGNED_HEADER); + +const TEST_UNSIGNED_HEADER = '0x' + rlp.encode(unsignedHeader).toString('hex'); +const unsignedHeaderHash = Web3Utils.sha3(TEST_UNSIGNED_HEADER); + +const TESTRLPENCODING = "0xf9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" +const TEST_PATH = "0x13" + +const TEST_TX_VALUE = "0xf86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" +const TEST_TX_NODES = "0xf90235f871a0804f9c841a6a1d3361d79980581c84e5b4d3e4c9bf33951346775542d0ee0728a0edadb5e660118ea4323654191131b62c81fc00203a15a21c925f9f50d0e4b3e4808080808080a03eda2d64b94c5ed45026a29c75c99677d44c561ea5efea30c1db6299871d5c2e8080808080808080f90151a0bc285699e68d2fe18e7af2cdf7e7e6456e91a3fd31e3c9935bc5bef92e94bf4ba06eb963b2c3a3b6c07a7221aa6f6f86f7cb8ddb45ab1ff1a9dc781f34da1f081fa0deea5b5566e7a5634d91c5fb56e25f4370e3531e2fd71ee17ed6c4ad0be2ced3a0b4e9d14555f162e811cfbcbff9b98a271a197b75271565f693912c2ff75e2131a03b0bc2d764fbefd76848ee2da7b211eb230ede08d8c54e6a868be9f5e42122c1a0b6dd488ad4fb82b0a98dff81ac6766d1dec26b29dc06174de1d315b0ab0bdf0ca066c20ff06dc33777f53eec32b0b9a8d99872bec24bb3998bb520ae6897c21d7ea02db2a399f611ba7993efb4768938a6f61b4add8959ce4c89f201f41e882ff375a02e31051a9f938b9b342b8070db3dd829f62da8d0c83a6dff91a4e3b4cb2adb9ea090e75708e7dbf856b75ed126a960085419fcde0e6a0129a92dffc0cb83ac089680808080808080f86c20b869f86707843b9aca008257c39461621bcf02914668f8404c1f860e92fc1893f74c8084457094cc1ba07e2ebe15f4ece2fd8ffc9a49d7e9e4e71a30534023ca6b24ab4000567709ad53a013a61e910eb7145aa93e865664c54846f26e09a74bd577eaf66b5dd00d334288" + +const TEST_RECEIPT_VALUE = "0xf901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" +const TEST_RECEIPT_NODES = "0xf90335f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e" + +const TRIG_DEPLOYED_RINKEBY_ADDR = "0x61621bcf02914668f8404c1f860e92fc1893f74c"; +const TRIG_FIRED_RINKEBY_TXHASH = "0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e" +const TRIG_FIRED_RINKEBY_BLOCKNO = 2657422 +const TRIG_CALLED_BY = "0x279884e133f9346f2fad9cc158222068221b613e"; + +const GENESIS_HASH = TESTBLOCK.parentHash; + + +contract('EthereumStore.js', (accounts) => { + let ion; + let validation; + let storage; + + beforeEach('setup contract for each test', async function () { + ion = await MockIon.new(DEPLOYEDCHAINID); + validation = await MockValidation.new(ion.address); + storage = await EthereumStore.new(ion.address); + }) + + describe('Register Chain', () => { + it('Successful Register Chain', async () => { + // Successfully add id of another chain + await ion.addChain(storage.address, TESTCHAINID); + + let chainRegistered = storage.m_chains(TESTCHAINID); + assert(chainRegistered); + }) + + it('Fail Register Current Chain', async () => { + // Fail adding deployment chain id + await ion.addChain(storage.address, DEPLOYEDCHAINID).should.be.rejected; + }) + + it('Fail Register Chain Twice', async () => { + // Successfully add id of another chain + await ion.addChain(storage.address, TESTCHAINID); + + let chainRegistered = storage.m_chains(TESTCHAINID); + assert(chainRegistered); + + await ion.addChain(storage.address, TESTCHAINID).should.be.rejected; + }) + }) + + describe('Add Block', () => { + it('Successful Add Block', async () => { + // Successfully add id of another chain + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + }) + + it('Fail Add Block from unregistered chain', async () => { + // Successfully add id of another chain + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING).should.be.rejected; + }) + + it('Fail Add Block from non-ion', async () => { + // Successfully add id of another chain + await ion.addChain(storage.address, TESTCHAINID); + + await storage.addBlock(TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING).should.be.rejected; + }) + + it('Fail Add Block with malformed data', async () => { + // Successfully add id of another chain + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE).should.be.rejected; + }) + + it('Fail Add Block with incorrect block hash', async () => { + // Successfully add id of another chain + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, unsignedHeaderHash, TESTRLPENCODING).should.be.rejected; + }) + + it('Fail Add Same Block Twice', async () => { + // Successfully add id of another chain + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING).should.be.rejected; + }) + }) + + describe('Check Tx Proof', () => { + it('Successful Check Tx Proof', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + let tx = await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); + + console.log("\tGas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Tx Proof with wrong chain id', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await storage.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Tx Proof with wrong tx value', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await storage.CheckTxProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Tx Proof with wrong block hash', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong block hash + await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Tx Proof with wrong path', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong path + await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, "0xff").should.be.rejected; + }) + }) + + describe('Check Receipt Proof', () => { + it('Successful Check Receipt Proof', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + nodes = generateTestReceiptRLPNodes(); + + let tx = await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, "0x"+nodes.toString('hex'), TEST_PATH); + console.log("\tGas used to submit check receipt proof = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Receipt Proof with wrong chain id', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await storage.CheckReceiptProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Receipt Proof with wrong receipt value', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await storage.CheckReceiptProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Receipt Proof with wrong block hash', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong block hash + await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; + }) + + it('Fail Receipt Proof with wrong path', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong path + await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, "0xff").should.be.rejected; + }) + }) + + describe('Check Roots Proof', () => { + it('Successful Check Roots Proof', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + let tx = await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); + console.log("\tGas used to submit check roots proof = " + tx.receipt.gasUsed.toString() + " gas"); + }) + + it('Fail Roots Proof with wrong chain id', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong chain ID + await storage.CheckRootsProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; + }) + + it('Fail Roots Proof with wrong block hash', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong block hash + await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; + }) + + it('Fail Roots Proof with wrong tx nodes', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong tx nodes + await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_NODES).should.be.rejected; + }) + + it('Fail Roots Proof with wrong receipt nodes', async () => { + await ion.addChain(storage.address, TESTCHAINID); + + await ion.storeBlock(storage.address, TESTCHAINID, TESTBLOCK.hash, TESTRLPENCODING); + + // Fail with wrong receipt nodes + await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; + }) + }) +}) + +async function verifyReceipts(eP, txHash) { + await eP.getReceiptTrieRoot(txHash).then( (root) => { + console.log("EP RECEIPT Root hash = 0x" + root.toString('hex')) + }) + + var verified; + await eP.getReceiptProof(txHash).then( (proof) => { + verified = EP.receipt(proof.path, proof.value, proof.parentNodes, proof.header, proof.blockHash); + }) + return verified; +} + +function generateTestReceiptRLPNodes() { + let root = Buffer.from("f871a012d378fe6800bc18f22e715a31971ef7e73ac5d1d85384f4b66ac32036ae43dea004d6e2678656a957ac776dbef512a04d266c1af3e2c5587fd233261a3d423213808080808080a05fac317a4d6d78181319fbc7e2cae4a9260f1a6afb5c6fea066e2308eed416818080808080808080", 'hex'); + second = Buffer.from("f90151a03da235c6dd0fbdaf208c60cbdca0d609dee2ba107495aa7adaa658362616c8aaa09ebf378a9064aa4da0512c55c790a5e007ac79d2713e4533771cd2c95be47a4da0c06fed36ffe1f2ec164ba88f73b353960448d2decbb65355c5298a33555de742a0e057afe423ee17e5499c570a56880b0f5b5c1884b90ff9b9b5baa827f72fc816a093e06093cd2fdb67e0f87cfcc35ded2f445cc1309a0ff178e59f932aeadb6d73a0193e4e939fbc5d34a570bea3fff7c6d54adcb1c3ab7ef07510e7bd5fcef2d4b3a0a17a0c71c0118092367220f65b67f2ba2eb9068ff5270baeabe8184a01a37f14a03479a38e63123d497588ad5c31d781276ec8c11352dd3895c8add34f9a2b786ba042254728bb9ab94b58adeb75d2238da6f30382969c00c65e55d4cc4aa474c0a6a03c088484aa1c73b8fb291354f80e9557ab75a01c65d046c2471d19bd7f2543d880808080808080", 'hex'); + leaf = Buffer.from("f9016b20b90167f901640183252867b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000f85af8589461621bcf02914668f8404c1f860e92fc1893f74ce1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000279884e133f9346f2fad9cc158222068221b613e", 'hex'); + + decodedRoot = rlp.decode(root); + decodedSecond = rlp.decode(second); + decodedLeaf = rlp.decode(leaf); + + nodes = rlp.encode([decodedRoot, decodedSecond, decodedLeaf]); + return nodes; +} \ No newline at end of file From dd59d0d3dc440efce7e2943649904ab650197c06 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 8 Nov 2018 19:40:20 +0000 Subject: [PATCH 155/203] PatriciaTrie tests are testing failures properly. Added comments in test files. --- test/PatriciaTrieTest.sol | 8 ++++---- test/clique.js | 9 +++++++++ test/ion.js | 11 +++++++++-- test/storage-ethereum.js | 9 +++++++++ 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/test/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol index 07c9682..61239b9 100644 --- a/test/PatriciaTrieTest.sol +++ b/test/PatriciaTrieTest.sol @@ -11,7 +11,7 @@ contract PatriciaTrieTest { instance = PatriciaTrie(DeployedAddresses.PatriciaTrie()); } - function testVerifyNestedNodes() returns (bool) { + function testSucceedVerifyNestedNodes() returns (bool) { bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; bytes memory path = hex"61"; @@ -45,11 +45,11 @@ contract PatriciaTrieTest { Assert.isTrue( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); } - function FailVerifyNestedNodes() returns (bool) { + function testFailVerifyNestedNodes() returns (bool) { bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; - bytes memory path = hex"62"; - bytes memory value = hex"857465737431"; + bytes memory path = hex"61"; + bytes memory value = hex"857465737432"; bytes memory nodes = hex"f83bf839808080808080c8318685746573743180a0207947cf85c03bd3d9f9ff5119267616318dcef0e12de2f8ca02ff2cdc720a978080808080808080"; Assert.isFalse( PatriciaTrie.verifyProof(value, nodes, path, rootHash), "PatriciaTrie verify failed" ); diff --git a/test/clique.js b/test/clique.js index cc43f8e..537c492 100644 --- a/test/clique.js +++ b/test/clique.js @@ -1,6 +1,15 @@ // Copyright (c) 2016-2018 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ +/* + Clique Validation contract test + + Tests here are standalone unit tests for clique module functionality. + Other contracts have been mocked to simulate basic behaviour. + + Tests the clique scheme for block submission, validator signature verification and more. +*/ + const eth_util = require('ethereumjs-util'); const utils = require('./helpers/utils.js'); const encoder = require('./helpers/encoder.js'); diff --git a/test/ion.js b/test/ion.js index 12fda00..cb2b050 100644 --- a/test/ion.js +++ b/test/ion.js @@ -1,6 +1,15 @@ // Copyright (c) 2016-2018 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ +/* + Ion Mediator contract test + + Tests here are standalone unit tests for Ion functionality. + Other contracts have been mocked to simulate basic behaviour. + + Tests the central mediator for block passing and validation registering. +*/ + const Web3Utils = require('web3-utils'); const utils = require('./helpers/utils.js'); const BN = require('bignumber.js') @@ -18,8 +27,6 @@ web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); const Ion = artifacts.require("Ion"); const MockValidation = artifacts.require("MockValidation"); const MockStorage = artifacts.require("MockStorage"); -//const TriggerEventVerifier = artifacts.require("TriggerEventVerifier"); -//const FunctionEvent = artifacts.require("Function"); require('chai') .use(require('chai-as-promised')) diff --git a/test/storage-ethereum.js b/test/storage-ethereum.js index 447129d..489d1cb 100644 --- a/test/storage-ethereum.js +++ b/test/storage-ethereum.js @@ -1,6 +1,15 @@ // Copyright (c) 2016-2018 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ +/* + Ethereum Storage contract test + + Tests here are standalone unit tests for Ion functionality. + Other contracts have been mocked to simulate basic behaviour. + + Tests Ethereum block structure decoding and verification of state transitions. +*/ + const Web3Utils = require('web3-utils'); const utils = require('./helpers/utils.js'); const BN = require('bignumber.js') From d43eae9bc8c468b1cd2c5b0c7516d2f85ffb4756 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 9 Nov 2018 17:06:10 +0000 Subject: [PATCH 156/203] Enhanced Clique contract to handle forking and evolving validator sets. Fixed issue where threshold was not updating upon validator set change. Updated tests and integration tests. --- contracts/validation/Clique.sol | 138 ++++++++++++++++++---------- test/clique.js | 38 +++++--- test/integration-clique_ethereum.js | 95 ++++++++++--------- 3 files changed, 168 insertions(+), 103 deletions(-) diff --git a/contracts/validation/Clique.sol b/contracts/validation/Clique.sol index 5659a4b..8d0c02e 100644 --- a/contracts/validation/Clique.sol +++ b/contracts/validation/Clique.sol @@ -29,6 +29,15 @@ contract Clique is IonCompatible { bytes32 receiptRootHash; } + struct Metadata { + address[] validators; + mapping (address => bool) m_validators; + mapping (address => uint256) m_proposals; + uint256 threshold; + } + + event BlockSubmitted(bytes32 chainId, bytes32 blockHash); + /* * onlyRegisteredChains * param: _id (bytes32) Unique id of chain supplied to function @@ -41,12 +50,14 @@ contract Clique is IonCompatible { } mapping (bytes32 => bool) public chains; - mapping (bytes32 => bytes32) public m_latestblock; mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; - mapping (bytes32 => uint256) public m_threshold; - mapping (bytes32 => mapping (address => bool)) public m_validators; - mapping (bytes32 => mapping (address => uint256)) public m_proposals; + mapping (bytes32 => mapping (bytes32 => Metadata)) public m_blockmetadata; + +// mapping (bytes32 => mapping (bytes32 => uint256)) public m_threshold; +// mapping (bytes32 => mapping (bytes32 => mapping (address => bool))) public m_validators; +// mapping (bytes32 => mapping (bytes32 => uint256)) public m_nValidators; +// mapping (bytes32 => mapping (bytes32 => mapping (address => uint256))) public m_proposals; constructor (address _ionAddr) IonCompatible(_ionAddr) public {} @@ -69,19 +80,23 @@ contract Clique is IonCompatible { require(!chains[_chainId], "Chain already exists" ); chains[_chainId] = true; - // Append validators and vote threshold - for (uint256 i = 0; i < _validators.length; i++) { - m_validators[_chainId][_validators[i]] = true; - } - m_threshold[_chainId] = (_validators.length/2) + 1; ion.addChain(_storeAddr, _chainId); BlockHeader storage header = m_blockheaders[_chainId][_genesisBlockHash]; header.blockNumber = 0; header.blockHash = _genesisBlockHash; + + Metadata storage metadata = m_blockmetadata[_chainId][_genesisBlockHash]; + metadata.validators = _validators; + + // Append validators and vote threshold + for (uint256 i = 0; i < _validators.length; i++) { + metadata.m_validators[_validators[i]] = true; + } + metadata.threshold = (_validators.length/2) + 1; + m_blockhashes[_chainId][_genesisBlockHash] = true; - m_latestblock[_chainId] = _genesisBlockHash; } /* @@ -106,44 +121,87 @@ contract Clique is IonCompatible { bytes memory extraDataSigned = new bytes(32); SolUtils.BytesToBytes(extraData, signedHeader[i].toBytes(), 2); SolUtils.BytesToBytes(extraDataSigned, header[i].toBytes(), 1); - require(keccak256(extraDataSigned)==keccak256(extraData), "Header data doesn't match!"); + require(keccak256(extraDataSigned) == keccak256(extraData), "Header data doesn't match!"); } else { - require(keccak256(header[i].toBytes())==keccak256(signedHeader[i].toBytes()), "Header data doesn't match!"); + require(keccak256(header[i].toBytes()) == keccak256(signedHeader[i].toBytes()), "Header data doesn't match!"); } } // Check the parent hash is the same as the previous block submitted bytes32 parentBlockHash = SolUtils.BytesToBytes32(header[0].toBytes(), 1); - require(m_blockhashes[_chainId][parentBlockHash], "Not child of previous block!"); - require (checkSignature(_chainId, signedHeader[12].toBytes(), _rlpBlockHeader), "Signer is not validator" ); + require( m_blockhashes[_chainId][parentBlockHash], "Not child of previous block!" ); + require( checkSignature(_chainId, signedHeader[12].toBytes(), _rlpBlockHeader, parentBlockHash), "Signer is not validator" ); // Append the new block to the struct - addProposal(_chainId, SolUtils.BytesToAddress(header[2].toBytes(), 1)); + addProposal(_chainId, SolUtils.BytesToAddress(header[2].toBytes(), 1), keccak256(_rlpSignedBlockHeader), parentBlockHash); storeBlock(_chainId, keccak256(_rlpSignedBlockHeader), parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint(), _rlpSignedBlockHeader, _storageAddr); - updateBlockHash(_chainId, keccak256(_rlpSignedBlockHeader)); + + emit BlockSubmitted(_chainId, keccak256(_rlpSignedBlockHeader)); } - function checkSignature(bytes32 _chainId, bytes signedHeader, bytes _rlpBlockHeader) internal returns (bool) { + function checkSignature(bytes32 _chainId, bytes _signedHeader, bytes _rlpBlockHeader, bytes32 _parentBlockHash) internal returns (bool) { bytes memory extraDataSig = new bytes(65); - uint256 length = signedHeader.length; - SolUtils.BytesToBytes(extraDataSig, signedHeader, length-65); + uint256 length = _signedHeader.length; + SolUtils.BytesToBytes(extraDataSig, _signedHeader, length-65); // Recover the signature of address sigAddr = ECVerify.ecrecovery(keccak256(_rlpBlockHeader), extraDataSig); + Metadata storage parentMetadata = m_blockmetadata[_chainId][_parentBlockHash]; - return m_validators[_chainId][sigAddr]; + // Check if signature is a validator that exists in previous block + return parentMetadata.m_validators[sigAddr]; } - function addProposal(bytes32 _id, address _vote) internal { - if (_vote!=(0x0)) { - m_proposals[_id][_vote]++; - // Add validator if does not exist else remove - if (m_proposals[_id][_vote]>=m_threshold[_id] && !m_validators[_id][_vote]) { - m_validators[_id][_vote] = true; - m_proposals[_id][_vote] = 0; - } else if (m_proposals[_id][_vote]>=m_threshold[_id] && m_validators[_id][_vote]) { - m_validators[_id][_vote] = false; - m_proposals[_id][_vote] = 0; + function addProposal(bytes32 _chainId, address _candidate, bytes32 _blockHash, bytes32 _parentBlockHash) internal { + Metadata storage parentMetadata = m_blockmetadata[_chainId][_parentBlockHash]; + Metadata storage metadata = m_blockmetadata[_chainId][_blockHash]; + + if (_candidate != 0x0) { + uint newVoteCount; + uint newThreshold = metadata.threshold; + address[] storage newValidators = metadata.validators; + + // If votes pass threshold, add validator if exists, remove validator if not exists. Else metadata equal to parent + if ( (parentMetadata.m_proposals[_candidate] + 1) >= parentMetadata.threshold && !parentMetadata.m_validators[_candidate]) { + newVoteCount = 0; + + for (uint i = 0; i < parentMetadata.validators.length; i++) { + newValidators.push(parentMetadata.validators[i]); + } + newValidators.push(_candidate); + } else if ( (parentMetadata.m_proposals[_candidate] + 1) >= parentMetadata.threshold && parentMetadata.m_validators[_candidate]) { + newVoteCount = 0; + + for (uint j = 0; j < parentMetadata.validators.length; j++) { + if (parentMetadata.validators[j] != _candidate) { + newValidators.push(parentMetadata.validators[j]); + } + } + } else { + newVoteCount = parentMetadata.m_proposals[_candidate] + 1; + + for (uint k = 0; k < parentMetadata.validators.length; k++) { + newValidators.push(parentMetadata.validators[k]); + } + } + + metadata.m_proposals[_candidate] = newVoteCount; + newThreshold = (newValidators.length/2) + 1; + + for (uint vi = 0; vi < newValidators.length; vi++) { + metadata.m_validators[newValidators[vi]] = true; + if (newValidators[vi] != _candidate) { + metadata.m_proposals[newValidators[vi]] = parentMetadata.m_proposals[newValidators[vi]]; + } + } + } else { + // If no vote, set current block metadata equal to parent block + metadata.validators = parentMetadata.validators; + metadata.threshold = parentMetadata.threshold; + + for (uint pi = 0; pi < parentMetadata.validators.length; pi++) { + metadata.m_validators[parentMetadata.validators[pi]] = true; + metadata.m_proposals[parentMetadata.validators[pi]] = parentMetadata.m_proposals[parentMetadata.validators[pi]]; } } } @@ -176,23 +234,11 @@ contract Clique is IonCompatible { ion.storeBlock(_storageAddr, _chainId, _hash, _rlpBlockHeader); } - /* - * @description when a block is submitted the latest block is updated here - * @param _id unique identifier of the chain from which the block hails - * @param _hash root hash of the block being added - */ - function updateBlockHash(bytes32 _id, bytes32 _hash) internal { - m_latestblock[_id] = _hash; + function getValidators(bytes32 _chainId, bytes32 _blockHash) constant returns (address[]) { + return m_blockmetadata[_chainId][_blockHash].validators; } - /* - * @description when a block is submitted the latest block is updated here - * @param _id unique identifier of the chain from which the block hails - * @param _hash root hash of the block being added - */ - function getLatestBlockHash(bytes32 _id) public returns (bytes32) { - return m_latestblock[_id]; + function getProposal(bytes32 _chainId, bytes32 _blockHash, address _candidate) constant returns (uint256) { + return m_blockmetadata[_chainId][_blockHash].m_proposals[_candidate]; } - - } diff --git a/test/clique.js b/test/clique.js index 537c492..886ac4d 100644 --- a/test/clique.js +++ b/test/clique.js @@ -99,9 +99,9 @@ contract('Clique.js', (accounts) => { // Successfully add id of another chain let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); - let chain = await clique.chains(TESTCHAINID); + let chainExists = await clique.chains(TESTCHAINID); - assert(chain); + assert(chainExists); // Fail adding id of this chain await clique.RegisterChain(storage.address, DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; @@ -114,8 +114,10 @@ contract('Clique.js', (accounts) => { // Successfully add id of another chain await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + let registeredValidators = await clique.getValidators.call(TESTCHAINID, GENESIS_HASH); + for (let i = 0; i < VALIDATORS.length; i++) { - let validatorExists = await clique.m_validators(TESTCHAINID, VALIDATORS[i]); + let validatorExists = registeredValidators.some(v => { return v == VALIDATORS[i] });; assert(validatorExists); } }) @@ -147,8 +149,8 @@ contract('Clique.js', (accounts) => { let event = validationReceipt.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("AddedBlock(bytes32)") }); assert.ok(event, "Stored event not emitted"); - const recoveredBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, recoveredBlockHash); + const submittedEvent = validationReceipt.logs.find(l => { return l.event == 'BlockSubmitted' }); + assert.equal(signedHeaderHash, submittedEvent.args.blockHash); let blockHashExists = await clique.m_blockhashes(TESTCHAINID, block.hash); assert(blockHashExists); @@ -236,7 +238,7 @@ contract('Clique.js', (accounts) => { }) it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { - + await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); @@ -259,18 +261,17 @@ contract('Clique.js', (accounts) => { }) - - // This test checks that new validators get added into the validator list as blocks are submitted to the contract. // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. it('Add Validators Through Block Submission', async () => { await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_START, ADD_VALIDATORS_GENESIS_HASH); - let voteThreshold = await clique.m_threshold(TESTCHAINID); + let registeredValidators = await clique.getValidators.call(TESTCHAINID, ADD_VALIDATORS_GENESIS_HASH); + let voteThreshold = Math.floor((registeredValidators.length/2) + 1); assert.equal(voteThreshold, 2); - let voteProposal = await clique.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + let voteProposal = await clique.getProposal.call(TESTCHAINID, ADD_VALIDATORS_GENESIS_HASH, VALIDATORS_FINISH[1]); assert.equal(voteProposal, 0); // Fetch block 873982 from rinkeby @@ -288,12 +289,13 @@ contract('Clique.js', (accounts) => { // Submit block should succeed validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); console.log("\tGas used to submit block 873983 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + let submittedEvent = validationReceipt.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; // Check proposal is added - voteProposal = await clique.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + voteProposal = await clique.getProposal.call(TESTCHAINID, blockHash, VALIDATORS_FINISH[1]); assert.equal(voteProposal, 1); - // Fetch block 873984 from rinkeby block = rinkeby.eth.getBlock(873984); rlpHeaders = encoder.encodeBlockHeader(block); @@ -317,17 +319,23 @@ contract('Clique.js', (accounts) => { // Submit block should succeed validationReceipt = await clique.SubmitBlock(TESTCHAINID, rlpHeaders.unsigned, rlpHeaders.signed, storage.address); console.log("\tGas used to submit block 873986 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); + submittedEvent = validationReceipt.logs.find(l => { return l.event == 'BlockSubmitted' }); + blockHash = submittedEvent.args.blockHash; // Check proposal is added - voteProposal = await clique.m_proposals(TESTCHAINID, VALIDATORS_FINISH[1]); + voteProposal = await clique.getProposal.call(TESTCHAINID, blockHash, VALIDATORS_FINISH[1]); assert.equal(voteProposal, 0); - // Check all new validators are added + // Check all validators exist + registeredValidators = await clique.getValidators.call(TESTCHAINID, blockHash); for (let i = 0; i < VALIDATORS_FINISH.length; i++) { - let validatorExists = await clique.m_validators(TESTCHAINID, VALIDATORS_FINISH[i]); + let validatorExists = registeredValidators.some(v => { return v == VALIDATORS_FINISH[i] });; assert(validatorExists); } + // Check that the vote threshold has increased with validator set size + voteThreshold = Math.floor((registeredValidators.length/2) + 1); + assert.equal(voteThreshold, 3); }) }) }); diff --git a/test/integration-clique_ethereum.js b/test/integration-clique_ethereum.js index c836911..a9e319c 100644 --- a/test/integration-clique_ethereum.js +++ b/test/integration-clique_ethereum.js @@ -233,8 +233,10 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + + assert.equal(signedHeaderHash, blockHash); }) it('Successful Add Block from different genesis', async () => { @@ -252,8 +254,10 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + + assert.equal(signedHeaderHash, blockHash); }) it('Fail Add Block with unregistered chain id', async () => { @@ -313,9 +317,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); tx = await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, TEST_PATH); console.log("\tGas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); @@ -336,9 +340,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; }) @@ -358,9 +362,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; }) @@ -380,9 +384,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); await storage.CheckTxProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_TX_NODES, '0x10').should.be.rejected; }) @@ -404,9 +408,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); tx = await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TEST_PATH); console.log("\tGas used to submit check tx proof = " + tx.receipt.gasUsed.toString() + " gas"); @@ -427,9 +431,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_VALUE, TEST_RECEIPT_NODES, TEST_PATH).should.be.rejected; }) @@ -449,9 +453,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_TX_NODES, TEST_PATH).should.be.rejected; }) @@ -471,9 +475,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); - + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); await storage.CheckReceiptProof(TESTCHAINID, TESTBLOCK.hash, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, '0x10').should.be.rejected; }) @@ -495,8 +499,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); tx = await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES); console.log("\tGas used to submit check roots proof = " + tx.receipt.gasUsed.toString() + " gas"); @@ -517,8 +522,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); // Fail with wrong chain ID await storage.CheckRootsProof(DEPLOYEDCHAINID, TESTBLOCK.hash, TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; @@ -539,8 +545,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); // Fail with wrong block hash await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash.substring(0, 30) + "ff", TEST_TX_NODES, TEST_RECEIPT_NODES).should.be.rejected; @@ -561,8 +568,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); // Fail with wrong tx nodes await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, "0xf9011FF851a0f2c8598d0469e213e269219f0f631bf9834344426238de6b986cf64e8ab7a76a80808080808080a04a397832771093a06e1fbfde782a2fc1624f214d090825c065d301f0325e0c7b8080808080808080f85180a0a6177c642f5f21f80f5e7ba81558bfb253da9fbe0bcedc768433cbff6f973073a0d56c80e3abbe59dfa6b65f3640f8f0661b485b76c44379d3c478545c59e508a48080808080808080808080808080f87520b872f8708302a122850ba43b740083015f909453e0551a1e31a40855bc8e086eb8db803a625bbf880e861ef96aefa800801ca03a92b0a4ffd7f8774688325c1306387e15e64225d03a5a43aeceaf2e53ea782da033f501d040a857572b747e7a0968f269107e34dae093f901b380423937862084", TEST_RECEIPT_NODES).should.be.rejected; @@ -583,8 +591,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); // Fail with wrong receipt nodes await storage.CheckRootsProof(TESTCHAINID, TESTBLOCK.hash, TEST_TX_NODES, "0xf90FF8f851a0e174e998404ccb578d781d64efceb6bf63547f4aed3d801e67229f1fbd827c6480808080808080a06e2f5c4a84018daf85387f2a09955f2fb535d8d459b867aabd0235ba97d991738080808080808080f85180a07d4e8719e289768c06065586d7e5b56a73b8c81e724724476ed75c9b5b59a5caa02eb7a5cd9716b4b4824e556c2df895a60fa6a0b68bd093081d24ba93eea522488080808080808080808080808080f9012f20b9012bf90128a0bbc7f826deb035ff86a12507aa7c967c931e920deffcf82bb61109267d88cab482f618b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0").should.be.rejected; @@ -615,8 +624,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); tx = await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY); event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("Executed()") }); @@ -643,8 +653,9 @@ contract('Clique-Ethereum Integration', (accounts) => { let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("BlockAdded(bytes32,bytes32)") }); assert.ok(event, "BlockAdded event not emitted"); - const latestBlockHash = await clique.getLatestBlockHash.call(TESTCHAINID); - assert.equal(signedHeaderHash, latestBlockHash); + let submittedEvent = tx.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + assert.equal(signedHeaderHash, blockHash); // Fail with wrong chain ID await functionContract.verifyAndExecute(DEPLOYEDCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_CALLED_BY).should.be.rejected; From 9e5f73af731d5e3add97de39293f0f98f2552bfc Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Mon, 12 Nov 2018 14:28:20 +0000 Subject: [PATCH 157/203] Added chain heads variable to keep track of open heads. Modified Clique to allow submission of multiple genesis blocks per chain to allow trustless submission and forking. --- contracts/validation/Clique.sol | 155 +++++++++++++++++++++++++------- 1 file changed, 122 insertions(+), 33 deletions(-) diff --git a/contracts/validation/Clique.sol b/contracts/validation/Clique.sol index 8d0c02e..3aab5cf 100644 --- a/contracts/validation/Clique.sol +++ b/contracts/validation/Clique.sol @@ -36,6 +36,7 @@ contract Clique is IonCompatible { uint256 threshold; } + event GenesisCreated(bytes32 chainId, bytes32 blockHash); event BlockSubmitted(bytes32 chainId, bytes32 blockHash); /* @@ -53,14 +54,16 @@ contract Clique is IonCompatible { mapping (bytes32 => mapping (bytes32 => bool)) public m_blockhashes; mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; mapping (bytes32 => mapping (bytes32 => Metadata)) public m_blockmetadata; - -// mapping (bytes32 => mapping (bytes32 => uint256)) public m_threshold; -// mapping (bytes32 => mapping (bytes32 => mapping (address => bool))) public m_validators; -// mapping (bytes32 => mapping (bytes32 => uint256)) public m_nValidators; -// mapping (bytes32 => mapping (bytes32 => mapping (address => uint256))) public m_proposals; + mapping (bytes32 => bytes32[]) public heads; constructor (address _ionAddr) IonCompatible(_ionAddr) public {} +/* ===================================================================================================================== + + Public Functions + + ===================================================================================================================== +*/ function register() public returns (bool) { ion.registerValidationModule(); return true; @@ -68,42 +71,34 @@ contract Clique is IonCompatible { /* * RegisterChain - * param: _id (bytes32) Unique id of another chain to interoperate with + * param: _chainId (bytes32) Unique id of another chain to interoperate with * param: _validators (address[]) Array containing the validators at the genesis block * param: _genesisHash (bytes32) Hash of the genesis block for the chain being registered with Ion + * param: _storeAddr (address) Address of block store contract to register chain to * - * Supplied with an id of another chain, checks if this id already exists in the known set of ids - * and adds it to the list of known chains. + * Registers knowledge of the id of another interoperable chain requiring the genesis block metadata. Allows + * the initialising of genesis blocks and their validator sets for chains. Multiple may be submitted and built upon + * and is not opinionated on how they are used. */ - function RegisterChain(address _storeAddr, bytes32 _chainId, address[] _validators, bytes32 _genesisBlockHash) public { + function RegisterChain(bytes32 _chainId, address[] _validators, bytes32 _genesisBlockHash, address _storeAddr) public { require( _chainId != ion.chainId(), "Cannot add this chain id to chain register" ); - require(!chains[_chainId], "Chain already exists" ); - chains[_chainId] = true; - - - ion.addChain(_storeAddr, _chainId); - - BlockHeader storage header = m_blockheaders[_chainId][_genesisBlockHash]; - header.blockNumber = 0; - header.blockHash = _genesisBlockHash; - Metadata storage metadata = m_blockmetadata[_chainId][_genesisBlockHash]; - metadata.validators = _validators; - - // Append validators and vote threshold - for (uint256 i = 0; i < _validators.length; i++) { - metadata.m_validators[_validators[i]] = true; + if (chains[_chainId]) { + require( !m_blockhashes[_chainId][_genesisBlockHash], "Chain already exists with identical genesis" ); + } else { + chains[_chainId] = true; + ion.addChain(_storeAddr, _chainId); } - metadata.threshold = (_validators.length/2) + 1; - m_blockhashes[_chainId][_genesisBlockHash] = true; + addGenesisBlock(_storeAddr, _chainId, _validators, _genesisBlockHash); } /* * SubmitBlock - * param: _id (bytes32) Unique id of chain submitting block from + * param: _chainId (bytes32) Unique id of chain submitting block from * param: _rlpBlockHeader (bytes) RLP-encoded byte array of the block header from other chain without the signature in extraData * param: _rlpSignedBlockHeader (bytes) RLP-encoded byte array of the block header from other chain with the signature in extraData + * param: _storeAddr (address) Address of block store contract to store block to * * Submission of block headers from another chain. Signatures held in the extraData field of _rlpSignedBlockHeader is recovered * and if valid the block is persisted as BlockHeader structs defined above. @@ -135,14 +130,62 @@ contract Clique is IonCompatible { // Append the new block to the struct addProposal(_chainId, SolUtils.BytesToAddress(header[2].toBytes(), 1), keccak256(_rlpSignedBlockHeader), parentBlockHash); storeBlock(_chainId, keccak256(_rlpSignedBlockHeader), parentBlockHash, SolUtils.BytesToBytes32(header[4].toBytes(), 1), SolUtils.BytesToBytes32(header[5].toBytes(), 1), header[8].toUint(), _rlpSignedBlockHeader, _storageAddr); + shiftHead(_chainId, keccak256(_rlpSignedBlockHeader), parentBlockHash); emit BlockSubmitted(_chainId, keccak256(_rlpSignedBlockHeader)); } - function checkSignature(bytes32 _chainId, bytes _signedHeader, bytes _rlpBlockHeader, bytes32 _parentBlockHash) internal returns (bool) { + +/* ===================================================================================================================== + + Internal Functions + + ===================================================================================================================== +*/ + + /* + * addGenesisBlock + * param: _chainId (bytes32) Unique id of another chain to interoperate with + * param: _validators (address[]) Array containing the validators at the genesis block + * param: _genesisHash (bytes32) Hash of the genesis block for the chain being registered with Ion + * param: _storeAddr (address) Address of block store contract to register chain to + * + * Adds a genesis block with the validators and other metadata for this genesis block + */ + function addGenesisBlock(bytes32 _chainId, address[] _validators, bytes32 _genesisBlockHash, address _storeAddr) internal { + BlockHeader storage header = m_blockheaders[_chainId][_genesisBlockHash]; + header.blockNumber = 0; + header.blockHash = _genesisBlockHash; + + Metadata storage metadata = m_blockmetadata[_chainId][_genesisBlockHash]; + metadata.validators = _validators; + + // Append validators and vote threshold + for (uint256 i = 0; i < _validators.length; i++) { + metadata.m_validators[_validators[i]] = true; + } + metadata.threshold = (_validators.length/2) + 1; + + m_blockhashes[_chainId][_genesisBlockHash] = true; + shiftHead(_chainId, _genesisBlockHash, 0x0); + + emit GenesisCreated(_chainId, _genesisBlockHash); + } + + /* + * checkSignature + * param: _chainId (bytes32) Unique id of interoperating chain + * param: _extraData (bytes) Byte array of the extra data containing signature + * param: _rlpBlockHeader (bytes) Byte array of RLP encoded unsigned block header + * param: _parentBlockHash (bytes32) Parent block hash of current block being checked + * + * Checks that the submitted block has actually been signed, recovers the signer and checks if they are validator in + * parent block + */ + function checkSignature(bytes32 _chainId, bytes _extraData, bytes _rlpBlockHeader, bytes32 _parentBlockHash) internal returns (bool) { bytes memory extraDataSig = new bytes(65); - uint256 length = _signedHeader.length; - SolUtils.BytesToBytes(extraDataSig, _signedHeader, length-65); + uint256 length = _extraData.length; + SolUtils.BytesToBytes(extraDataSig, _extraData, length-65); // Recover the signature of address sigAddr = ECVerify.ecrecovery(keccak256(_rlpBlockHeader), extraDataSig); @@ -152,6 +195,15 @@ contract Clique is IonCompatible { return parentMetadata.m_validators[sigAddr]; } + /* + * addProposal + * param: _chainId (bytes32) Unique id of interoperating chain + * param: _candidate (address) Byte array of the extra data containing signature + * param: _blockHash (bytes32) Current block hash being checked + * param: _parentBlockHash (bytes32) Parent block hash of current block being checked + * + * Modifies the proposal/validator set via votes collated from the block. Checks parent block for latest state. + */ function addProposal(bytes32 _chainId, address _candidate, bytes32 _blockHash, bytes32 _parentBlockHash) internal { Metadata storage parentMetadata = m_blockmetadata[_chainId][_parentBlockHash]; Metadata storage metadata = m_blockmetadata[_chainId][_blockHash]; @@ -207,9 +259,17 @@ contract Clique is IonCompatible { } /* - * @description when a block is submitted the root hash must be added to a mapping of chains to hashes - * @param _id unique identifier of the chain from which the block hails - * @param _hash root hash of the block being added + * storeBlock + * param: _chainId (bytes32) Unique id of interoperating chain + * param: _hash (address) Byte array of the extra data containing signature + * param: _parentHash (bytes32) Current block hash being checked + * param: _txRootHash (bytes32) Parent block hash of current block being checked + * param: _receiptRootHash (bytes32) Parent block hash of current block being checked + * param: _height (bytes32) Parent block hash of current block being checked + * param: _rlpBlockHeader (bytes32) Parent block hash of current block being checked + * param: _storageAddr (bytes32) Parent block hash of current block being checked + * + * Takes the submitted block to propagate to the storage contract. */ function storeBlock( bytes32 _chainId, @@ -234,6 +294,35 @@ contract Clique is IonCompatible { ion.storeBlock(_storageAddr, _chainId, _hash, _rlpBlockHeader); } + /* + * shiftHead + * param: _chainId (bytes32) Unique id of chain + * param: _childHash (bytes32) New block hash + * param: _parentHash (bytes32) Previous block hash + * + * Updates set of current open chain heads per chain. Open chain heads are blocks that do not have a child that can + * be built upon. + */ + function shiftHead(bytes32 _chainId, bytes32 _childHash, bytes32 _parentHash) public { + int index = -1; + bytes32[] storage chainHeads = heads[_chainId]; + + // Check if parent hash is an open head and replace with child + for (uint i = 0; i < chainHeads.length; i++) { + if (chainHeads[i] == _parentHash) { + index = int(i); + + delete chainHeads[index]; + chainHeads[index] = _childHash; + + return; + } + } + + // If parent is not an open head, child is, so append to heads + chainHeads.push(_childHash); + } + function getValidators(bytes32 _chainId, bytes32 _blockHash) constant returns (address[]) { return m_blockmetadata[_chainId][_blockHash].validators; } From 8cd677dc761c92692ae56bba233064c026dd4724 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 14 Nov 2018 11:41:26 +0000 Subject: [PATCH 158/203] Testing tweaks --- ion-cli/cli/cli.go | 112 ++++++++++++++++++++++++++------------------- ion-cli/main.go | 2 +- 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 991b180..64fdb4f 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -23,7 +23,7 @@ import ( // Launch - definition of commands and creates the iterface func Launch( - setup config.Setup, + config config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, Validation *compiler.Contract, @@ -46,13 +46,13 @@ func Launch( } // Create an authorized transactor and corrsponding privateKey - authTo, keyTo := config.InitUser(setup.KeystoreTo, setup.PasswordTo) + authTo, keyTo := config.InitUser(config.KeystoreTo, config.PasswordTo) authTo.Value = big.NewInt(0) // in wei authTo.GasLimit = uint64(100000) // in units authTo.GasPrice = gasPrice // Create an authorized transactor and spend 1 unicorn - authFrom, keyFrom := config.InitUser(setup.KeystoreFrom, setup.PasswordFrom) + authFrom, keyFrom := config.InitUser(config.KeystoreFrom, config.PasswordFrom) authFrom.Value = big.NewInt(0) // in wei authFrom.GasLimit = uint64(100000) // in units authFrom.GasPrice = gasPrice @@ -61,27 +61,6 @@ func Launch( // RPC Client Specific Commands //--------------------------------------------------------------------------------------------- - shell.AddCmd(&ishell.Cmd{ - Name: "latestBlock", - Help: "use: \tlatestBlock [TO/FROM] \n\t\t\t\tdescription: Returns number of latest block mined/sealed from chain [TO/FROM]", - Func: func(c *ishell.Context) { - if c.Args[0] == "TO" { - c.Println("Connecting to: " + setup.AddrTo) - c.Println("Get latest block number:") - lastBlock := latestBlock(ethclientTo) - c.Printf("latest block: %v\n", lastBlock.Number) - } else if c.Args[0] == "FROM" { - c.Println("Connecting to: " + setup.AddrFrom) - c.Println("Get latest block number:") - lastBlock := latestBlock(ethclientFrom) - c.Printf("latest block: %v\n", lastBlock.Number) - } else { - c.Println("Please choose enter TO or FROM only!") - } - c.Println("===============================================================") - }, - }) - shell.AddCmd(&ishell.Cmd{ Name: "getBlock", Help: "use: \tgetBlock [TO/FROM] [integer] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", @@ -89,16 +68,53 @@ func Launch( if len(c.Args) != 2 { c.Println("Error: Incorrect Arguments!") } else if c.Args[0] == "TO" { - c.Println("Connecting to: " + setup.AddrTo) + c.Println("Connecting to: " + config.AddrTo) getBlock(ethclientTo, c.Args[1]) } else if c.Args[0] == "FROM" { - c.Println("Connecting to: " + setup.AddrFrom) + c.Println("Connecting to: " + config.AddrFrom) getBlock(ethclientFrom, c.Args[1]) } c.Println("===============================================================") }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "getTxProof", + Help: "use: \tgetTxProof [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Func: func(c *ishell.Context) { + c.Println("Connecting to: " + config.AddrTo + " and " + config.AddrFrom) + c.ShowPrompt(false) + defer c.ShowPrompt(true) // yes, revert after login. + + // Get the chainId + bytesChainId := common.HexToHash(config.ChainId) + + // Get the transaction hash + c.Print("Enter Transaction Hash: ") + txHash := c.ReadLine() + bytesTxHash := common.HexToHash(txHash) + + // Get the blockHash + c.Print("Enter Block Hash: ") + blockHash := c.ReadLine() + bytesBlockHash := common.HexToHash(blockHash) + + // Generate the proof + txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( + ctx, + clientFrom, + bytesTxHash, + ) + + c.Printf(" Path: 0x%x\n + TxValue: 0x%x\n + TxNodes: 0x%x\n + ReceiptValue: 0x%x\n + ReceiptNodes: 0x%x\n", tx.Path, txValue, txNodes, receiptValue, receiptNodes) + c.Println("===============================================================") + }, + }) + //--------------------------------------------------------------------------------------------- // Validation Specific Commands //--------------------------------------------------------------------------------------------- @@ -106,12 +122,12 @@ func Launch( Name: "registerChainValidation", Help: "use: \tregisterChainValidation\n \t\t\t\t\tEnter Validators: [ADDRESS ADDRESS]\n \t\t\t\t\tEnter Genesis Hash: [HASH] \n\t\t\t\tdescription: Register new chain with validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + setup.AddrTo) + c.Println("Connecting to: " + config.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // Get the chainId - bytesChainId := common.HexToHash(setup.ChainId) + bytesChainId := common.HexToHash(config.ChainId) // Get the validators array c.Print("Enter Validators: ") @@ -134,7 +150,7 @@ func Launch( ethclientTo, keyTo.PrivateKey, Validation, - common.HexToAddress(setup.Validation), + common.HexToAddress(config.Validation), bytesChainId, validators, bytesGenesis, @@ -149,12 +165,12 @@ func Launch( Name: "submitBlockValidation", Help: "use: \tsubmitBlockValidation\n \t\t\t\t\tEnter Block Number: [INTEGER]\n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + setup.AddrTo) + c.Println("Connecting to: " + config.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) + bytesChainId, err := utils.StringToBytes32(config.ChainId) if err != nil { c.Printf("Error: %s", err) return @@ -172,7 +188,7 @@ func Launch( ethclientTo, keyTo.PrivateKey, Validation, - common.HexToAddress(setup.Validation), + common.HexToAddress(config.Validation), bytesChainId, unsignedBlock, signedBlock, @@ -187,12 +203,12 @@ func Launch( Name: "checkBlockValidation", Help: "use: \tcheckBlockValidation\n \t\t\t\t\tEnter Blockhash: [HASH]\n\t\t\t\tdescription: Returns true for validated blocks", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + setup.AddrTo) + c.Println("Connecting to: " + config.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. // Get the chainId - bytesChainId, err := utils.StringToBytes32(setup.ChainId) + bytesChainId, err := utils.StringToBytes32(config.ChainId) if err != nil { c.Printf("Error: %s", err) return @@ -211,8 +227,8 @@ func Launch( ctx, ethclientTo, Validation, - common.HexToAddress(setup.AddrTo), - common.HexToAddress(setup.Validation), + common.HexToAddress(config.AddrTo), + common.HexToAddress(config.Validation), bytesChainId, bytesBlockHash, ) @@ -227,21 +243,21 @@ func Launch( Name: "latestValidatedBlock", Help: "use: \tlatestValidatedBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + setup.AddrTo) + c.Println("Connecting to: " + config.AddrTo) // Get the chainId - bytesChainId := common.HexToHash(setup.ChainId) + bytesChainId := common.HexToHash(config.ChainId) result := contract.LatestValidBlock( ctx, ethclientTo, Validation, - common.HexToAddress(setup.AddrTo), - common.HexToAddress(setup.Validation), + common.HexToAddress(config.AddrTo), + common.HexToAddress(config.Validation), bytesChainId, ) c.Println("Checking for latest valid block:") - c.Printf("\nBlockHash:\t0x%x\nChainId:\t%s\n", result, setup.ChainId) + c.Printf("\nBlockHash:\t0x%x\nChainId:\t%s\n", result, config.ChainId) c.Println("===============================================================") }, }) @@ -253,14 +269,14 @@ func Launch( Name: "triggerEvent", Help: "use: \ttriggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + setup.AddrFrom) + c.Println("Connecting to: " + config.AddrFrom) tx := contract.Fire( ctx, ethclientFrom, keyFrom.PrivateKey, Trigger, - common.HexToAddress(setup.Trigger), + common.HexToAddress(config.Trigger), ) c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) @@ -275,12 +291,12 @@ func Launch( Name: "verifyAndExecute", Help: "use: \tverifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + setup.AddrTo + " and " + setup.AddrFrom) + c.Println("Connecting to: " + config.AddrTo + " and " + config.AddrFrom) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. // Get the chainId - bytesChainId := common.HexToHash(setup.ChainId) + bytesChainId := common.HexToHash(config.ChainId) // Get the transaction hash c.Print("Enter Transaction Hash: ") @@ -307,16 +323,16 @@ func Launch( ethclientTo, keyFrom.PrivateKey, Function, - common.HexToAddress(setup.Function), + common.HexToAddress(config.Function), bytesChainId, bytesBlockHash, - common.HexToAddress(setup.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, + common.HexToAddress(config.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, txPath, // TEST_PATH, txValue, // TEST_TX_VALUE, txNodes, // TEST_TX_NODES, receiptValue, // TEST_RECEIPT_VALUE, receiptNodes, // TEST_RECEIPT_NODES, - common.HexToAddress(setup.AccountFrom), // TRIG_CALLED_BY, + common.HexToAddress(config.AccountFrom), // TRIG_CALLED_BY, nil, ) diff --git a/ion-cli/main.go b/ion-cli/main.go index 9bd57d4..e71bb1e 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -13,7 +13,7 @@ import ( "github.com/clearmatics/ion/ion-cli/utils" ) -var configFile = flag.String("config", "setup.json", "Description:\n path to the configuration file") +var configFile = flag.String("config", "", "Description:\n path to the configuration file") func main() { flag.Parse() From 5f2805ce753dcb9db018572b57fb78271c5137d7 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 14 Nov 2018 14:33:44 +0000 Subject: [PATCH 159/203] Fixed Clique and clique tests. Changed testrpc script. --- contracts/validation/Clique.sol | 6 ++-- package.json | 2 +- test/clique.js | 20 ++++++------- test/integration-clique_ethereum.js | 46 ++++++++++++++--------------- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/contracts/validation/Clique.sol b/contracts/validation/Clique.sol index 3aab5cf..c51d350 100644 --- a/contracts/validation/Clique.sol +++ b/contracts/validation/Clique.sol @@ -90,7 +90,7 @@ contract Clique is IonCompatible { ion.addChain(_storeAddr, _chainId); } - addGenesisBlock(_storeAddr, _chainId, _validators, _genesisBlockHash); + addGenesisBlock(_chainId, _validators, _genesisBlockHash, _storeAddr); } /* @@ -312,8 +312,8 @@ contract Clique is IonCompatible { if (chainHeads[i] == _parentHash) { index = int(i); - delete chainHeads[index]; - chainHeads[index] = _childHash; + delete chainHeads[uint(index)]; + chainHeads[uint(index)] = _childHash; return; } diff --git a/package.json b/package.json index c8d43ff..c2aedbe 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "web3-utils": "^1.0.0-beta.33" }, "scripts": { - "testrpc": "ganache-cli --account='0xe176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b,1000000000000000000000000000000000000000' --account='0xd18bc3878eb28192238d92ae085cdb9438527e36faa92484dea2e3baa047b083,1000000000000000000000000000000000000000' --port 8545 --gasLimit 0xFFFFFFFFFFF --gasPrice 0 --networkId 1234 --deterministic grape crisp enroll avoid satoshi picnic term dice gown grocery situate depart", + "testrpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFFFFFF --gasPrice 0 --defaultBalanceEther 99999999999 --networkId 1234", "compile": "truffle compile", "deploy": "truffle deploy", "test": "truffle test", diff --git a/test/clique.js b/test/clique.js index 886ac4d..01c34f6 100644 --- a/test/clique.js +++ b/test/clique.js @@ -97,7 +97,7 @@ contract('Clique.js', (accounts) => { describe('Register Chain', () => { it('Successful Register Chain', async () => { // Successfully add id of another chain - let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + let tx = await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); let chainExists = await clique.chains(TESTCHAINID); @@ -107,12 +107,12 @@ contract('Clique.js', (accounts) => { await clique.RegisterChain(storage.address, DEPLOYEDCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; // Fail adding id of chain already initialised - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address).should.be.rejected; }) it('Check Validators', async () => { // Successfully add id of another chain - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); let registeredValidators = await clique.getValidators.call(TESTCHAINID, GENESIS_HASH); @@ -124,7 +124,7 @@ contract('Clique.js', (accounts) => { it('Check Genesis Hash', async () => { // Successfully add id of another chain - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); let header = await clique.m_blockheaders(TESTCHAINID, GENESIS_HASH); let blockHeight = header[0]; @@ -135,7 +135,7 @@ contract('Clique.js', (accounts) => { describe('Submit Block', () => { it('Authentic Submission Happy Path', async () => { - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby const block = rinkeby.eth.getBlock(1); @@ -167,7 +167,7 @@ contract('Clique.js', (accounts) => { // Here the block header is signed off chain but by a a non-whitelisted validator it('Fail Submit Block unkown validator - SubmitBlock()', async () => { // Successfully add id of another chain - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby const block = rinkeby.eth.getBlock(1); @@ -225,7 +225,7 @@ contract('Clique.js', (accounts) => { }) it('Fail Submit Block from unknown chain - SubmitBlock()', async () => { - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from testrpc const block = web3.eth.getBlock(1); @@ -238,9 +238,7 @@ contract('Clique.js', (accounts) => { }) it('Fail Submit Block with wrong unsigned header - SubmitBlock()', async () => { - - - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from testrpc const block = rinkeby.eth.getBlock(1); @@ -265,7 +263,7 @@ contract('Clique.js', (accounts) => { // Rinkeby adds its first non-genesis validator at block 873987 with the votes occuring at blocks 873983 and 873986 // we will start following the chain from 873982 and then add blocks until the vote threshold, n/2 + 1, is passed. it('Add Validators Through Block Submission', async () => { - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_START, ADD_VALIDATORS_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_START, ADD_VALIDATORS_GENESIS_HASH, storage.address); let registeredValidators = await clique.getValidators.call(TESTCHAINID, ADD_VALIDATORS_GENESIS_HASH); let voteThreshold = Math.floor((registeredValidators.length/2) + 1); diff --git a/test/integration-clique_ethereum.js b/test/integration-clique_ethereum.js index a9e319c..c685d05 100644 --- a/test/integration-clique_ethereum.js +++ b/test/integration-clique_ethereum.js @@ -188,7 +188,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Successful Register Chain', async () => { await clique.register(); - let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + let tx = await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); let chain = await clique.chains(TESTCHAINID); @@ -198,13 +198,13 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Register Twice', async () => { await clique.register(); - let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + let tx = await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); let chain = await clique.chains(TESTCHAINID); assert(chain); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address).should.be.rejected; }) it('Fail Register Deployment Chain', async () => { @@ -213,14 +213,14 @@ contract('Clique-Ethereum Integration', (accounts) => { }) it('Fail Register Chain without registering clique module', async () => { - let tx = await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH).should.be.rejected; + let tx = await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address).should.be.rejected; }) }) describe('Add Block', () => { it('Successful Add Block', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby const block = rinkeby.eth.getBlock(1); @@ -241,7 +241,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Successful Add Block from different genesis', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -262,7 +262,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Add Block with unregistered chain id', async () => { await clique.register(); -// await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); +// await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby const block = rinkeby.eth.getBlock(1); @@ -276,7 +276,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Add Block with non-sequential block', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS, GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 2 from rinkeby instead of block 1 const block = rinkeby.eth.getBlock(2); @@ -304,7 +304,7 @@ contract('Clique-Ethereum Integration', (accounts) => { describe('Check Tx Proof of Tx 0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e on Rinkeby', () => { it('Successful Check Tx Proof', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -327,7 +327,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Tx Proof with wrong tx value', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -349,7 +349,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Tx Proof with wrong tx nodes', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -371,7 +371,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Tx Proof with wrong path', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -395,7 +395,7 @@ contract('Clique-Ethereum Integration', (accounts) => { describe('Check Receipt Proof of Tx 0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e on Rinkeby', () => { it('Successful Check Receipt Proof', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -418,7 +418,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Receipt Proof with wrong receipt value', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -440,7 +440,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Receipt Proof with wrong receipt nodes', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -462,7 +462,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Receipt Proof with wrong path', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -486,7 +486,7 @@ contract('Clique-Ethereum Integration', (accounts) => { describe('Check Roots Proof', () => { it('Successful Check Roots Proof', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -509,7 +509,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Roots Proof with wrong chain id', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -532,7 +532,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Roots Proof with wrong block hash', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -555,7 +555,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Roots Proof with wrong tx nodes', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -578,7 +578,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Roots Proof with wrong receipt nodes', async () => { await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -611,7 +611,7 @@ contract('Clique-Ethereum Integration', (accounts) => { const functionContract = await FunctionEvent.new(storage.address, verifier.address); await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); @@ -640,7 +640,7 @@ contract('Clique-Ethereum Integration', (accounts) => { const functionContract = await FunctionEvent.new(storage.address, verifier.address); await clique.register(); - await clique.RegisterChain(storage.address, TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby const block = rinkeby.eth.getBlock(TESTBLOCK.number); From 3ddec29e5c55b6f96df1964cd44676bd4ba3521b Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 15 Nov 2018 18:06:19 +0000 Subject: [PATCH 160/203] Enhanced CLI functionality and generalised usage STILL BROKEN --- ion-cli/cli/cli.go | 292 ++++++++--- ion-cli/cli/rpc.go | 54 +- ...--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d | 1 - ion-cli/config/config.go | 5 + ion-cli/config/test.json | 15 +- ion-cli/contracts/contract.go | 17 +- ion-cli/contracts/function.go | 19 +- ion-cli/contracts/ion.go | 18 +- ion-cli/contracts/validation.go | 10 +- ...--b8844cf76df596e746f360957aa3af954ef51605 | 1 + ion-cli/main.go | 15 +- package-lock.json | 481 +----------------- package.json | 3 +- 13 files changed, 359 insertions(+), 572 deletions(-) delete mode 100644 ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d create mode 100644 ion-cli/keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605 diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 64fdb4f..3ae03b4 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -5,14 +5,17 @@ import ( "context" "fmt" "log" + //"encoding/json" "math/big" "strconv" + "errors" "strings" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/compiler" + // "github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/abiosoft/ishell" @@ -21,14 +24,11 @@ import ( "github.com/clearmatics/ion/ion-cli/utils" ) -// Launch - definition of commands and creates the iterface +// Launch - definition of commands and creates the interface func Launch( - config config.Setup, + configuration config.Setup, clientTo *rpc.Client, clientFrom *rpc.Client, - Validation *compiler.Contract, - Trigger *compiler.Contract, - Function *compiler.Contract, ) { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -36,9 +36,15 @@ func Launch( // Create new context ctx := context.Background() - ethclientTo := ethclient.NewClient(clientTo) + //ethclientTo := ethclient.NewClient(clientTo) ethclientFrom := ethclient.NewClient(clientFrom) + var ethClient *EthClient = nil + var contracts map[string]*contract.ContractInstance = make(map[string]*contract.ContractInstance) + var accounts map[string]*config.Account = make(map[string]*config.Account) + contracts = contracts + accounts = accounts + // Get a suggested gas price gasPrice, err := ethclientFrom.SuggestGasPrice(ctx) if err != nil { @@ -46,71 +52,189 @@ func Launch( } // Create an authorized transactor and corrsponding privateKey - authTo, keyTo := config.InitUser(config.KeystoreTo, config.PasswordTo) + authTo, keyTo := config.InitUser(configuration.KeystoreTo, configuration.PasswordTo) authTo.Value = big.NewInt(0) // in wei authTo.GasLimit = uint64(100000) // in units authTo.GasPrice = gasPrice // Create an authorized transactor and spend 1 unicorn - authFrom, keyFrom := config.InitUser(config.KeystoreFrom, config.PasswordFrom) + authFrom, keyFrom := config.InitUser(configuration.KeystoreFrom, configuration.PasswordFrom) authFrom.Value = big.NewInt(0) // in wei authFrom.GasLimit = uint64(100000) // in units authFrom.GasPrice = gasPrice + keyTo = keyTo + keyFrom = keyFrom + //--------------------------------------------------------------------------------------------- // RPC Client Specific Commands //--------------------------------------------------------------------------------------------- shell.AddCmd(&ishell.Cmd{ - Name: "getBlock", - Help: "use: \tgetBlock [TO/FROM] [integer] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Name: "connectToClient", + Help: "use: \tconnectToClient [rpc url] \n\t\t\t\tdescription: Connects to an RPC client to be used", + Func: func(c *ishell.Context) { + if len(c.Args) != 1 { + c.Println("Usage: \tconnectToClient [rpc url] \n") + } else { + c.Println("Connecting to client...\n") + ethClient = getClient(c.Args[0]) + c.Println("Connected!") + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "addContractInstance", + Help: "use: \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n\t\t\t\tdescription: Compiles a contract for use", + Func: func(c *ishell.Context) { + if len(c.Args) != 3 { + c.Println("Usage: \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n") + } else { + compiledContract := contract.CompileContractAt(c.Args[1]) + _, Abi := contract.GetContractBytecodeAndABI(compiledContract) + abistruct, err := abi.JSON(strings.NewReader(Abi)) + if err != nil { + c.Err(err) + } + contracts[c.Args[0]] = &contract.ContractInstance{Contract: compiledContract, Address: common.HexToAddress(c.Args[2]), Abi: &abistruct} + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "listContracts", + Help: "use: \tlistContracts \n\t\t\t\tdescription: List compiled contract instances", + Func: func(c *ishell.Context) { + for key := range contracts { + c.Println(key) + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "addAccount", + Help: "use: \taddAccount [name] [path/to/keystore] [password] \n\t\t\t\tdescription: Add account to be used for transactions", + Func: func(c *ishell.Context) { + if len(c.Args) != 3 { + c.Println("Usage: \taddAccount [name] [path/to/keystore] [password] \n") + } else { + auth, key := config.InitUser(c.Args[1], c.Args[2]) + account := &config.Account{Auth: auth, Key: key} + accounts[c.Args[0]] = account + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "listAccounts", + Help: "use: \tlistAccounts \n\t\t\t\tdescription: List all added accounts", + Func: func(c *ishell.Context) { + for key := range accounts { + c.Println(key) + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "messageCallFunction", + Help: "use: \tmessageCallFunction [contract name] [function name] [from account name] [amount] [gasLimit] \n\t\t\t\tdescription: Connects to an RPC client to be used", + Func: func(c *ishell.Context) { + if len(c.Args) != 5 { + c.Println("Usage: \tmessageCallFunction [contract name] [function name] [from account name] [amount] [gasLimit] \n") + } else { + instance := contracts[c.Args[0]] + account := accounts[c.Args[2]] + amount := new(big.Int) + amount, ok := amount.SetString(c.Args[3], 10) + if !ok { + c.Err(errors.New("Please enter an integer for ")) + } + gasLimit := new(big.Int) + gasLimit, ok = amount.SetString(c.Args[4], 10) + if !ok { + c.Err(errors.New("Please enter an integer for ")) + } + + account = account + amount = amount + gasLimit = gasLimit + + parseMethodParameters(c, instance.Abi, c.Args[1]) + + /*contract.TransactionContract( + ctx, + ethClient, + account.Key.PrivateKey, + instance.Address, + common.HexToHash(configuration.ChainId), + amount, + gasLimit, + c.Args[1], + , + + )*/ + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "getBlockByNumber", + Help: "use: \tgetBlockByNumber [rpc url] [integer] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", Func: func(c *ishell.Context) { if len(c.Args) != 2 { - c.Println("Error: Incorrect Arguments!") - } else if c.Args[0] == "TO" { - c.Println("Connecting to: " + config.AddrTo) - getBlock(ethclientTo, c.Args[1]) - } else if c.Args[0] == "FROM" { - c.Println("Connecting to: " + config.AddrFrom) - getBlock(ethclientFrom, c.Args[1]) + if ethClient != nil { + getBlockByNumber(ethClient, c.Args[0]) + } else { + c.Println("Usage: \tgetBlock [rpc url] [integer] \n") + } + } else { + c.Println("Connecting to client...\n") + newClient := getClient(c.Args[0]) + getBlockByNumber(newClient, c.Args[1]) } c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ - Name: "getTxProof", - Help: "use: \tgetTxProof [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", + Name: "getBlockByHash", + Help: "use: \tgetBlockByNumber [rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Func: func(c *ishell.Context) { + if len(c.Args) != 2 { + if (ethClient != nil) { + getBlockByHash(ethClient, c.Args[0]) + } else { + c.Println("Usage: \tgetBlock [rpc url] [hash] \n") + } + } else { + c.Println("Connecting to client...\n") + newClient := getClient(c.Args[0]) + getBlockByHash(newClient, c.Args[1]) + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "getProof", + Help: "use: \tgetProof [rpc url] [Transaction Hash] \n\t\t\t\tdescription: Returns a merkle patricia proof of a specific transaction and its receipt in a block", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + config.AddrTo + " and " + config.AddrFrom) - c.ShowPrompt(false) - defer c.ShowPrompt(true) // yes, revert after login. - - // Get the chainId - bytesChainId := common.HexToHash(config.ChainId) - - // Get the transaction hash - c.Print("Enter Transaction Hash: ") - txHash := c.ReadLine() - bytesTxHash := common.HexToHash(txHash) - - // Get the blockHash - c.Print("Enter Block Hash: ") - blockHash := c.ReadLine() - bytesBlockHash := common.HexToHash(blockHash) - - // Generate the proof - txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( - ctx, - clientFrom, - bytesTxHash, - ) - - c.Printf(" Path: 0x%x\n - TxValue: 0x%x\n - TxNodes: 0x%x\n - ReceiptValue: 0x%x\n - ReceiptNodes: 0x%x\n", tx.Path, txValue, txNodes, receiptValue, receiptNodes) + if len(c.Args) != 2 { + if (ethClient != nil) { + getProof(ethClient, c.Args[0]) + } else { + c.Println("Usage: \tgetBlock [rpc url] [hash] \n") + } + } else { + getProof(getClient(c.Args[0]), c.Args[1]) + } c.Println("===============================================================") }, }) @@ -118,16 +242,17 @@ func Launch( //--------------------------------------------------------------------------------------------- // Validation Specific Commands //--------------------------------------------------------------------------------------------- + /* shell.AddCmd(&ishell.Cmd{ Name: "registerChainValidation", Help: "use: \tregisterChainValidation\n \t\t\t\t\tEnter Validators: [ADDRESS ADDRESS]\n \t\t\t\t\tEnter Genesis Hash: [HASH] \n\t\t\t\tdescription: Register new chain with validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + config.AddrTo) + c.Println("Connecting to: " + configuration.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // Get the chainId - bytesChainId := common.HexToHash(config.ChainId) + bytesChainId := common.HexToHash(configuration.ChainId) // Get the validators array c.Print("Enter Validators: ") @@ -150,7 +275,7 @@ func Launch( ethclientTo, keyTo.PrivateKey, Validation, - common.HexToAddress(config.Validation), + common.HexToAddress(configuration.Validation), bytesChainId, validators, bytesGenesis, @@ -165,12 +290,12 @@ func Launch( Name: "submitBlockValidation", Help: "use: \tsubmitBlockValidation\n \t\t\t\t\tEnter Block Number: [INTEGER]\n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + config.AddrTo) + c.Println("Connecting to: " + configuration.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. // Get the chainId - bytesChainId, err := utils.StringToBytes32(config.ChainId) + bytesChainId, err := utils.StringToBytes32(configuration.ChainId) if err != nil { c.Printf("Error: %s", err) return @@ -179,7 +304,6 @@ func Launch( // Get the block number c.Print("Enter Block Number: ") blockNum := c.ReadLine() - // blockNum := "2776659" c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) signedBlock, unsignedBlock := calculateRlpEncoding(ethclientFrom, blockNum) @@ -188,7 +312,7 @@ func Launch( ethclientTo, keyTo.PrivateKey, Validation, - common.HexToAddress(config.Validation), + common.HexToAddress(configuration.Validation), bytesChainId, unsignedBlock, signedBlock, @@ -203,12 +327,12 @@ func Launch( Name: "checkBlockValidation", Help: "use: \tcheckBlockValidation\n \t\t\t\t\tEnter Blockhash: [HASH]\n\t\t\t\tdescription: Returns true for validated blocks", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + config.AddrTo) + c.Println("Connecting to: " + configuration.AddrTo) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. // Get the chainId - bytesChainId, err := utils.StringToBytes32(config.ChainId) + bytesChainId, err := utils.StringToBytes32(configuration.ChainId) if err != nil { c.Printf("Error: %s", err) return @@ -227,8 +351,8 @@ func Launch( ctx, ethclientTo, Validation, - common.HexToAddress(config.AddrTo), - common.HexToAddress(config.Validation), + common.HexToAddress(configuration.AddrTo), + common.HexToAddress(configuration.Validation), bytesChainId, bytesBlockHash, ) @@ -243,60 +367,63 @@ func Launch( Name: "latestValidatedBlock", Help: "use: \tlatestValidatedBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + config.AddrTo) + c.Println("Connecting to: " + configuration.AddrTo) // Get the chainId - bytesChainId := common.HexToHash(config.ChainId) + bytesChainId := common.HexToHash(configuration.ChainId) result := contract.LatestValidBlock( ctx, ethclientTo, Validation, - common.HexToAddress(config.AddrTo), - common.HexToAddress(config.Validation), + common.HexToAddress(configuration.AddrTo), + common.HexToAddress(configuration.Validation), bytesChainId, ) c.Println("Checking for latest valid block:") - c.Printf("\nBlockHash:\t0x%x\nChainId:\t%s\n", result, config.ChainId) + c.Printf("\nBlockHash:\t0x%x\nChainId:\t%s\n", result, configuration.ChainId) c.Println("===============================================================") }, - }) + })*/ //--------------------------------------------------------------------------------------------- // Trigger Specific Commands //--------------------------------------------------------------------------------------------- + /* shell.AddCmd(&ishell.Cmd{ Name: "triggerEvent", Help: "use: \ttriggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + config.AddrFrom) + c.Println("Connecting to: " + configuration.AddrFrom) tx := contract.Fire( ctx, ethclientFrom, keyFrom.PrivateKey, Trigger, - common.HexToAddress(config.Trigger), + common.HexToAddress(configuration.Trigger), ) c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) c.Println("===============================================================") }, }) +*/ //--------------------------------------------------------------------------------------------- // Function Specific Commands //--------------------------------------------------------------------------------------------- + /* shell.AddCmd(&ishell.Cmd{ Name: "verifyAndExecute", Help: "use: \tverifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", Func: func(c *ishell.Context) { - c.Println("Connecting to: " + config.AddrTo + " and " + config.AddrFrom) + c.Println("Connecting to: " + configuration.AddrTo + " and " + configuration.AddrFrom) c.ShowPrompt(false) defer c.ShowPrompt(true) // yes, revert after login. // Get the chainId - bytesChainId := common.HexToHash(config.ChainId) + bytesChainId := common.HexToHash(configuration.ChainId) // Get the transaction hash c.Print("Enter Transaction Hash: ") @@ -323,16 +450,16 @@ func Launch( ethclientTo, keyFrom.PrivateKey, Function, - common.HexToAddress(config.Function), + common.HexToAddress(configuration.Function), bytesChainId, bytesBlockHash, - common.HexToAddress(config.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, + common.HexToAddress(configuration.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, txPath, // TEST_PATH, txValue, // TEST_TX_VALUE, txNodes, // TEST_TX_NODES, receiptValue, // TEST_RECEIPT_VALUE, receiptNodes, // TEST_RECEIPT_NODES, - common.HexToAddress(config.AccountFrom), // TRIG_CALLED_BY, + common.HexToAddress(configuration.AccountFrom), // TRIG_CALLED_BY, nil, ) @@ -341,10 +468,29 @@ func Launch( }, }) + */ // run shell shell.Run() } +func getClient(url string) (client *EthClient) { + rpc := utils.ClientRPC(url) + eth := ethclient.NewClient(rpc) + + return &EthClient{client: eth, rpcClient: rpc, url: url} +} + +func parseMethodParameters(c *ishell.Context, abi *abi.ABI, methodName string) (args []interface{}) { + inputParameters := abi.Methods[methodName].Inputs + fmt.Printf("%s\n", inputParameters) + + for argument := range inputParameters { + fmt.Printf("%s\n", abi.UnmarshalJSON(argument)) + } + + return +} + func strToHex(input string) (output string) { val, err := strconv.Atoi(input) if err != nil { diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 7abffa1..8e5b949 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -10,8 +10,11 @@ import ( "reflect" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rlp" + "github.com/clearmatics/ion/ion-cli/utils" + "github.com/ethereum/go-ethereum/rpc" ) // Header used to marshall blocks into a string based struct @@ -33,9 +36,15 @@ type header struct { Nonce string `json:"nonce"` } -func latestBlock(client *ethclient.Client) (lastBlock *types.Header) { +type EthClient struct { + client *ethclient.Client + rpcClient *rpc.Client + url string +} + +func latestBlock(eth *EthClient) (lastBlock *types.Header) { // var lastBlock Block - lastBlock, err := client.HeaderByNumber(context.Background(), nil) + lastBlock, err := eth.client.HeaderByNumber(context.Background(), nil) if err != nil { fmt.Println("can't get latest block:", err) return nil @@ -44,12 +53,30 @@ func latestBlock(client *ethclient.Client) (lastBlock *types.Header) { return } -func getBlock(client *ethclient.Client, block string) { +func getBlockByNumber(eth *EthClient, block string) { // var blockHeader header blockNum := new(big.Int) blockNum.SetString(block, 10) - lastBlock, err := client.HeaderByNumber(context.Background(), blockNum) + lastBlock, err := eth.client.HeaderByNumber(context.Background(), blockNum) + if err != nil { + fmt.Println("can't get requested block:", err) + return + } + // Marshal into a JSON + b, err := json.MarshalIndent(lastBlock, "", " ") + if err != nil { + fmt.Printf("Error: %s", err) + return + } + fmt.Println("Block:", block) + fmt.Println(string(b)) +} + +func getBlockByHash(eth *EthClient, block string) { + blockHash := common.HexToHash(block) + + lastBlock, err := eth.client.HeaderByHash(context.Background(), blockHash) if err != nil { fmt.Println("can't get requested block:", err) return @@ -64,7 +91,24 @@ func getBlock(client *ethclient.Client, block string) { fmt.Println(string(b)) } -// func calculateRlpEncoding(client *ethclient.Client, block string) { +func getProof(eth *EthClient, transactionHash string) { + // Get the transaction hash + bytesTxHash := common.HexToHash(transactionHash) + + // Generate the proof + txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( + context.Background(), + eth.rpcClient, + bytesTxHash, + ) + + fmt.Printf( "Path: 0x%x\n" + + "TxValue: 0x%x\n" + + "TxNodes: 0x%x\n" + + "ReceiptValue: 0x%x\n" + + "ReceiptNodes: 0x%x\n", txPath, txValue, txNodes, receiptValue, receiptNodes) +} + func calculateRlpEncoding(client *ethclient.Client, block string) (rlpSignedBlock []byte, rlpUnsignedBlock []byte) { // var blockHeader header blockNum := new(big.Int) diff --git a/ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d deleted file mode 100644 index 0d2f3cc..0000000 --- a/ion-cli/config/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d +++ /dev/null @@ -1 +0,0 @@ -{"address":"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d","crypto":{"cipher":"aes-128-ctr","ciphertext":"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa","cipherparams":{"iv":"4aa66b789ee2d98cf77272a72eeeaa50"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e"},"mac":"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3"},"id":"a3cc1eae-3e36-4659-b759-6cf416216e72","version":3} \ No newline at end of file diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 280b0ec..8ca770e 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -30,6 +30,11 @@ type Setup struct { Function string `json:"function-addr"` } +type Account struct { + Auth *bind.TransactOpts + Key *keystore.Key +} + // Takes path to a JSON and returns a struct of the contents func ReadSetup(config string) (setup Setup) { raw, err := ioutil.ReadFile(config) diff --git a/ion-cli/config/test.json b/ion-cli/config/test.json index e682029..1446b0a 100644 --- a/ion-cli/config/test.json +++ b/ion-cli/config/test.json @@ -1,9 +1,10 @@ { - "rpc-to":"127.0.0.1:8545", - "account-to":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-to":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "ion-addr":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", - "rpc-from":"127.0.0.1:8501", - "account-from":"0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", - "keystore-from":"../poa-network/node1/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + "rpc-to":"http://127.0.0.1:8545", + "account-to":"0xb8844cf76df596e746f360957aa3af954ef51605", + "keystore-to":"keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605", + "password-to": "test", + "rpc-from":"https://rinkeby.infura.io", + "account-from":"0xb8844cf76df596e746f360957aa3af954ef51605", + "keystore-from":"keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605", + "password-from":"test" } diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index 7e317fa..895ef4b 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -23,11 +23,12 @@ import ( type ContractInstance struct { Contract *compiler.Contract Address common.Address + Abi *abi.ABI } // GENERIC UTIL FUNCTIONS -func getContractBytecodeAndABI(c *compiler.Contract) (string, string) { +func GetContractBytecodeAndABI(c *compiler.Contract) (string, string) { cABIBytes, err := json.Marshal(c.Info.AbiDefinition) if err != nil { log.Fatal("ERROR marshalling contract ABI:", err) @@ -199,3 +200,17 @@ func CompileContract(contract string) (compiledContract *compiler.Contract) { return } + +func CompileContractAt(contractPath string) (compiledContract *compiler.Contract) { + contract, err := compiler.CompileSolidity("", contractPath) + if err != nil { + log.Fatal("ERROR failed to compile contract:", err) + } + + path := strings.Split(contractPath, "/") + contractName := path[len(path)-1] + + compiledContract = contract[contractPath+":"+strings.Replace(contractName, ".sol", "", -1)] + + return +} diff --git a/ion-cli/contracts/function.go b/ion-cli/contracts/function.go index 084a0b0..43a7fa4 100644 --- a/ion-cli/contracts/function.go +++ b/ion-cli/contracts/function.go @@ -7,14 +7,15 @@ import ( "log" "math/big" "os" + "strings" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/core/types" ) -// CompileAndDeployTriggerVerifierAndConsumerFunction method func CompileAndDeployTriggerVerifierAndConsumerFunction( ctx context.Context, client bind.ContractBackend, @@ -34,9 +35,9 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( } triggerEventVerifierContract := contracts[triggerEventVerifierContractPath+":TriggerEventVerifier"] - triggerEventVerifierBinStr, triggerEventVerifierABIStr := getContractBytecodeAndABI(triggerEventVerifierContract) + triggerEventVerifierBinStr, triggerEventVerifierABIStr := GetContractBytecodeAndABI(triggerEventVerifierContract) consumerFunctionContract := contracts[consumerFunctionContractPath+":Function"] - consumerFunctionBinStr, consumerFunctionABIStr := getContractBytecodeAndABI(consumerFunctionContract) + consumerFunctionBinStr, consumerFunctionABIStr := GetContractBytecodeAndABI(consumerFunctionContract) // --------------------------------------------- // DEPLOY TRIGGER EVENT CONTRACT @@ -80,7 +81,11 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( triggerEventAddr, ) - resChan <- ContractInstance{triggerEventVerifierContract, triggerEventAddr} + triggerAbi, err := abi.JSON(strings.NewReader(triggerEventVerifierABIStr)) + if err != nil { + log.Fatal("ERROR failed to compile TriggerEventVerifier.sol:", err) + } + resChan <- ContractInstance{triggerEventVerifierContract, triggerEventAddr, &triggerAbi} // wait for consumer function contract to be deployed consumerFunctionAddr, err := bind.WaitDeployed(ctx, deployBackend, consumerFunctionSignedTx) @@ -88,7 +93,11 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( log.Fatal("ERROR while waiting for contract deployment") } - resChan <- ContractInstance{consumerFunctionContract, consumerFunctionAddr} + functionAbi, err := abi.JSON(strings.NewReader(consumerFunctionABIStr)) + if err != nil { + log.Fatal("ERROR failed to compile Function.sol:", err) + } + resChan <- ContractInstance{consumerFunctionContract, consumerFunctionAddr, &functionAbi} }() return resChan diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go index be180e9..6dd8e73 100644 --- a/ion-cli/contracts/ion.go +++ b/ion-cli/contracts/ion.go @@ -7,7 +7,9 @@ import ( "log" "os" "regexp" + "strings" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common/compiler" ) @@ -31,10 +33,10 @@ func CompileAndDeployIon( } patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] - patriciaTrieBinStr, patriciaTrieABIStr := getContractBytecodeAndABI(patriciaTrieContract) + patriciaTrieBinStr, patriciaTrieABIStr := GetContractBytecodeAndABI(patriciaTrieContract) ionContract := contracts[basePath+"Ion.sol:Ion"] - ionBinStr, ionABIStr := getContractBytecodeAndABI(ionContract) + ionBinStr, ionABIStr := GetContractBytecodeAndABI(ionContract) // --------------------------------------------- // DEPLOY PATRICIA LIB ADDRESS @@ -80,9 +82,13 @@ func CompileAndDeployIon( chainID, ) + patriciaAbi, err := abi.JSON(strings.NewReader(patriciaTrieABIStr)) + if err != nil { + log.Fatal("ERROR failed to compile PatriciaTrie.sol:", err) + } // only stop blocking the first result after the Ion contract as been deploy // this guarantees that it works well with the blockchain simulator Commit() - resChan <- ContractInstance{patriciaTrieContract, patriciaTrieAddr} + resChan <- ContractInstance{patriciaTrieContract, patriciaTrieAddr, &patriciaAbi} // wait for Ion to be deployed ionAddr, err := bind.WaitDeployed(ctx, deployBackend, ionSignedTx) @@ -90,7 +96,11 @@ func CompileAndDeployIon( log.Fatal("ERROR while waiting for contract deployment") } - resChan <- ContractInstance{ionContract, ionAddr} + ionAbi, err := abi.JSON(strings.NewReader(ionABIStr)) + if err != nil { + log.Fatal("ERROR failed to compile Ion.sol:", err) + } + resChan <- ContractInstance{ionContract, ionAddr, &ionAbi} }() return resChan diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index ec55e79..51a18bc 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -6,7 +6,9 @@ import ( "crypto/ecdsa" "log" "os" + "strings" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/compiler" @@ -33,7 +35,7 @@ func CompileAndDeployValidation( } validationContract := contracts[basePath+"Validation.sol:Validation"] - validationBinStr, validationABIStr := getContractBytecodeAndABI(validationContract) + validationBinStr, validationABIStr := GetContractBytecodeAndABI(validationContract) // --------------------------------------------- // DEPLOY VALIDATION CONTRACT @@ -63,7 +65,11 @@ func CompileAndDeployValidation( if err != nil { log.Fatal("ERROR while waiting for contract deployment") } - resChan <- ContractInstance{validationContract, validationAddr} + abistruct, err := abi.JSON(strings.NewReader(validationABIStr)) + if err != nil { + log.Fatal("ERROR failed to compile Validation.sol:", err) + } + resChan <- ContractInstance{validationContract, validationAddr, &abistruct} }() return resChan diff --git a/ion-cli/keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605 b/ion-cli/keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605 new file mode 100644 index 0000000..6df80dc --- /dev/null +++ b/ion-cli/keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605 @@ -0,0 +1 @@ +{"address":"b8844cf76df596e746f360957aa3af954ef51605","crypto":{"cipher":"aes-128-ctr","ciphertext":"069af615b268d9f5ef9d56e701998d9471d748ac5f1210218467a19c70b31df3","cipherparams":{"iv":"ddac56c5144c3e3a2a55f71014a5cdb4"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"111d76b0240de8d8bb726efaeee9da7b636f4e3070d28b774b7313bf538514a3"},"mac":"c62da59938d301f3678b21bf35a1f695e114c25623e9985434e4d54439d852eb"},"id":"bfd2fd4b-97f4-44f5-8631-a6b439494bcf","version":3} \ No newline at end of file diff --git a/ion-cli/main.go b/ion-cli/main.go index e71bb1e..156346d 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -9,7 +9,7 @@ import ( "github.com/clearmatics/ion/ion-cli/cli" "github.com/clearmatics/ion/ion-cli/config" - contract "github.com/clearmatics/ion/ion-cli/contracts" + // contract "github.com/clearmatics/ion/ion-cli/contracts" "github.com/clearmatics/ion/ion-cli/utils" ) @@ -25,9 +25,9 @@ func main() { clientFrom := utils.ClientRPC(setup.AddrFrom) // Compile contracts to use in sending transactions - Validation := contract.CompileContract("Validation") - Function := contract.CompileContract("Function") - Trigger := contract.CompileContract("Trigger") + // Validation := contract.CompileContract("Validation") + // Function := contract.CompileContract("Function") + // Trigger := contract.CompileContract("Trigger") printInfo(setup) // Launch the CLI @@ -35,9 +35,6 @@ func main() { setup, clientTo, clientFrom, - Validation, - Trigger, - Function, ) } else { @@ -55,12 +52,8 @@ func printInfo(setup config.Setup) { fmt.Println("\tListening on:\t\t" + setup.AddrTo) fmt.Println("\tUser Account:\t\t" + setup.AccountTo) fmt.Println("\tRPC ChainId:\t\t" + setup.ChainId) - fmt.Println("\tValidation Contract:\t" + setup.Validation) - fmt.Println("\tIon Contract:\t\t" + setup.Ion) - fmt.Println("\tFunction Contract:\t" + setup.Function) fmt.Println("\nRPC Client [FROM]:") fmt.Println("\tListening on:\t\t" + setup.AddrFrom) fmt.Println("\tUser Account:\t\t" + setup.AccountFrom) - fmt.Println("\tTrigger Contract:\t" + setup.Trigger) fmt.Println("===============================================================") } diff --git a/package-lock.json b/package-lock.json index c713787..e898222 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,31 +41,6 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" }, - "abi-decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/abi-decoder/-/abi-decoder-1.2.0.tgz", - "integrity": "sha512-y2OKSEW4gf2838Eavc56vQY9V46zaXkf3Jl1WpTfUBbzAVrXSr4JRZAAWv55Tv9s5WNz1rVgBgz5d2aJIL1QCg==", - "requires": { - "web3": "0.18.4" - }, - "dependencies": { - "bignumber.js": { - "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" - }, - "web3": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", - "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", - "requires": { - "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "crypto-js": "3.1.8", - "utf8": "2.1.2", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - } - } - } - }, "abstract-leveldown": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", @@ -187,20 +162,6 @@ "normalize-path": "2.1.1" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1268,11 +1229,6 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, - "bignumber.js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", - "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" - }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", @@ -1662,11 +1618,6 @@ "readdirp": "2.1.0" } }, - "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -1875,11 +1826,6 @@ "typedarray": "0.0.6" } }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -2229,11 +2175,6 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2266,11 +2207,6 @@ "repeating": "2.0.1" } }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" - }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -2398,46 +2334,6 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, - "encoding-down": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", - "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", - "requires": { - "abstract-leveldown": "5.0.0", - "inherits": "2.0.3", - "level-codec": "9.0.0", - "level-errors": "2.0.0", - "xtend": "4.0.1" - }, - "dependencies": { - "abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "requires": { - "xtend": "4.0.1" - } - }, - "level-codec": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz", - "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==" - }, - "level-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", - "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", - "requires": { - "errno": "0.1.7" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } - } - }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -2720,73 +2616,6 @@ "xhr-request-promise": "0.1.2" } }, - "eth-proof": { - "version": "git+https://github.com/Shirikatsu/eth-proof.git#9b7fdea64ec5810c9c8a74c67ab96dbf0f035567", - "requires": { - "ethereumjs-block": "1.7.1", - "ethereumjs-tx": "1.3.7", - "keccak": "1.4.0", - "leveldown": "1.9.0", - "levelup": "1.3.9", - "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", - "rlp": "2.1.0", - "web3": "0.19.1" - }, - "dependencies": { - "ethereumjs-block": { - "version": "1.7.1", - "resolved": "http://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "requires": { - "async": "2.6.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "1.3.7", - "ethereumjs-util": "5.2.0", - "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" - } - }, - "level-ws": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", - "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "xtend": "4.0.1" - } - }, - "merkle-patricia-tree": { - "version": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", - "integrity": "sha512-CSjgzZmkrQXg/DRwVPc1Icxw6WbOPkxAtPCz+ue8IkoYN6u9ZIPUmIEjpTQnXQgtB1kRajIR7L/rJ2KDl3+dUQ==", - "requires": { - "async": "1.5.2", - "ethereumjs-util": "5.2.0", - "level-mem": "3.0.1", - "level-ws": "1.0.0", - "readable-stream": "2.3.6", - "rlp": "2.1.0", - "semaphore": "1.1.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - } - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } - } - }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" - }, "ethereumjs-block": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.0.0.tgz", @@ -2966,11 +2795,6 @@ "fill-range": "2.2.4" } }, - "expand-template": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", - "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" - }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -3141,11 +2965,6 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, - "fast-future": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", - "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" - }, "fast-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", @@ -3622,7 +3441,7 @@ }, "fs-extra": { "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "requires": { "graceful-fs": "4.1.11", @@ -4219,21 +4038,6 @@ "source-map-support": "0.5.6" } }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.3" - } - }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -4321,11 +4125,6 @@ } } }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" - }, "github-username": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", @@ -4567,11 +4366,6 @@ "has-symbol-support-x": "1.4.2" } }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -5485,105 +5279,6 @@ } } }, - "level-mem": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", - "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", - "requires": { - "level-packager": "4.0.1", - "memdown": "3.0.0" - }, - "dependencies": { - "abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "requires": { - "xtend": "4.0.1" - } - }, - "memdown": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", - "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", - "requires": { - "abstract-leveldown": "5.0.0", - "functional-red-black-tree": "1.0.1", - "immediate": "3.2.3", - "inherits": "2.0.3", - "ltgt": "2.2.1", - "safe-buffer": "5.1.2" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } - } - }, - "level-packager": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", - "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", - "requires": { - "encoding-down": "5.0.4", - "levelup": "3.1.1" - }, - "dependencies": { - "abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "requires": { - "xtend": "4.0.1" - } - }, - "deferred-leveldown": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", - "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", - "requires": { - "abstract-leveldown": "5.0.0", - "inherits": "2.0.3" - } - }, - "level-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", - "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", - "requires": { - "errno": "0.1.7" - } - }, - "level-iterator-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", - "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "xtend": "4.0.1" - } - }, - "levelup": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", - "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", - "requires": { - "deferred-leveldown": "4.0.2", - "level-errors": "2.0.0", - "level-iterator-stream": "3.0.1", - "xtend": "4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } - } - }, "level-ws": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", @@ -5606,38 +5301,6 @@ } } }, - "leveldown": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-1.9.0.tgz", - "integrity": "sha512-3MwcrnCUIuFiKp/jSrG1UqDTV4k1yH8f5HH6T9dpqCKG+lRxcfo2KwAqbzTT+TTKfCbaATeHMy9mm1y6sI3ZvA==", - "requires": { - "abstract-leveldown": "2.7.2", - "bindings": "1.3.0", - "fast-future": "1.0.2", - "nan": "2.7.0", - "prebuild-install": "2.5.3" - }, - "dependencies": { - "abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "requires": { - "xtend": "4.0.1" - } - }, - "nan": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", - "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } - } - }, "levelup": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", @@ -6451,14 +6114,6 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" }, - "node-abi": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.5.0.tgz", - "integrity": "sha512-9g2twBGSP6wIR5PW7tXvAWnEWKJDH/VskdXp168xsw9VVxpEGov8K4jsP4/VeoC7b2ZAyzckvMCuQuQlw44lXg==", - "requires": { - "semver": "5.4.1" - } - }, "node-dir": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", @@ -6495,11 +6150,6 @@ } } }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -6545,17 +6195,6 @@ "path-key": "2.0.1" } }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "1.1.5", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -7036,28 +6675,6 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, - "prebuild-install": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", - "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", - "requires": { - "detect-libc": "1.0.3", - "expand-template": "1.1.1", - "github-from-package": "0.0.0", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "node-abi": "2.5.0", - "noop-logger": "0.1.1", - "npmlog": "4.1.2", - "os-homedir": "1.0.2", - "pump": "2.0.1", - "rc": "1.2.8", - "simple-get": "2.8.1", - "tar-fs": "1.16.3", - "tunnel-agent": "0.6.0", - "which-pm-runs": "1.0.0" - } - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -7134,15 +6751,6 @@ "randombytes": "2.0.6" } }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -7223,17 +6831,6 @@ "unpipe": "1.0.0" } }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "0.6.0", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - } - }, "read-chunk": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", @@ -8013,9 +7610,9 @@ "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=" }, "solc": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", - "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", + "version": "0.4.25", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.25.tgz", + "integrity": "sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg==", "requires": { "fs-extra": "0.30.0", "memorystream": "0.3.1", @@ -8462,28 +8059,6 @@ "inherits": "2.0.3" } }, - "tar-fs": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", - "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", - "requires": { - "chownr": "1.1.1", - "mkdirp": "0.5.1", - "pump": "1.0.3", - "tar-stream": "1.6.1" - }, - "dependencies": { - "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, "tar-stream": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", @@ -8680,6 +8255,21 @@ "mocha": "4.1.0", "original-require": "1.0.1", "solc": "0.4.24" + }, + "dependencies": { + "solc": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", + "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", + "dev": true, + "requires": { + "fs-extra": "0.30.0", + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "semver": "5.4.1", + "yargs": "4.8.1" + } + } } }, "truffle-assertions": { @@ -8852,14 +8442,6 @@ } } }, - "truffle-events": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/truffle-events/-/truffle-events-0.0.7.tgz", - "integrity": "sha1-K85JudQ6MZHHCBfpljwI3V7Ai9w=", - "requires": { - "abi-decoder": "1.2.0" - } - }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -9225,18 +8807,6 @@ "vinyl": "1.2.0" } }, - "web3": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", - "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", - "requires": { - "bignumber.js": "4.1.0", - "crypto-js": "3.1.8", - "utf8": "2.1.2", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - } - }, "web3-bzz": { "version": "1.0.0-beta.36", "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.0.0-beta.36.tgz", @@ -10846,19 +10416,6 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, - "which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "1.0.2" - } - }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", diff --git a/package.json b/package.json index c2aedbe..f41f2c2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", "rlp": "^2.0.0", - "solc": "^0.4.23", + "solc": "^0.4.25", "solhint": "^1.1.10", "solidity-coverage": "^0.5.0 ", "truffle-assertions": "^0.6.3", @@ -37,6 +37,7 @@ }, "scripts": { "testrpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFFFFFF --gasPrice 0 --defaultBalanceEther 99999999999 --networkId 1234", + "clirpc": "ganache-cli --port 8545 --gasLimit 0xFFFFFFFFFFF --gasPrice 0 --defaultBalanceEther 99999999999 --networkId 1234", "compile": "truffle compile", "deploy": "truffle deploy", "test": "truffle test", From b714618196baa2023270dd6d4ff15a1c9c72d4bf Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Tue, 20 Nov 2018 15:26:53 +0000 Subject: [PATCH 161/203] Current working type conversion for all but byte arrays. --- ion-cli/cli/cli.go | 268 +++++++++++++++++++++++++++++--- ion-cli/contracts/contract.go | 33 +++- ion-cli/contracts/function.go | 6 +- ion-cli/contracts/trigger.go | 7 +- ion-cli/contracts/validation.go | 14 +- ion-cli/utils/type.go | 105 +++++++++++++ 6 files changed, 403 insertions(+), 30 deletions(-) create mode 100644 ion-cli/utils/type.go diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 3ae03b4..3868605 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -5,11 +5,12 @@ import ( "context" "fmt" "log" - //"encoding/json" + "encoding/hex" "math/big" "strconv" "errors" "strings" + "reflect" "github.com/ethereum/go-ethereum/common" // "github.com/ethereum/go-ethereum/common/compiler" @@ -148,37 +149,68 @@ func Launch( if len(c.Args) != 5 { c.Println("Usage: \tmessageCallFunction [contract name] [function name] [from account name] [amount] [gasLimit] \n") } else { + if ethClient == nil { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + instance := contracts[c.Args[0]] + methodName := c.Args[1] account := accounts[c.Args[2]] + + if instance == nil { + errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) + c.Println(errStr) + return + } + if account == nil { + errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore] [password] \n", c.Args[2]) + c.Println(errStr) + return + } + amount := new(big.Int) amount, ok := amount.SetString(c.Args[3], 10) if !ok { c.Err(errors.New("Please enter an integer for ")) } - gasLimit := new(big.Int) - gasLimit, ok = amount.SetString(c.Args[4], 10) - if !ok { + gasLimit, err := strconv.ParseUint(c.Args[4], 10, 64) + if err != nil { c.Err(errors.New("Please enter an integer for ")) } - account = account - amount = amount - gasLimit = gasLimit + if instance.Abi.Methods[methodName].Name == "" { + c.Printf("Method name \"%s\" not found for contract \"%s\"\n", methodName, c.Args[0]) + return + } + + inputs, err := parseMethodParameters(c, instance.Abi, methodName) + if err != nil { + c.Printf("Error parsing parameters: %s\n", err) + return + } + //inputs := []interface{}{[]bool{true, false}, []bool{false,false,true}} - parseMethodParameters(c, instance.Abi, c.Args[1]) + c.Printf("Inputs = %s\n", inputs) + c.Printf("First index type: %s\n", reflect.TypeOf(inputs[0])) - /*contract.TransactionContract( + tx, err := contract.TransactionContract( ctx, - ethClient, + ethClient.client, account.Key.PrivateKey, + instance.Contract, instance.Address, - common.HexToHash(configuration.ChainId), amount, gasLimit, c.Args[1], - , - - )*/ + inputs... + ) + if err != nil { + c.Println(err) + return + } else { + c.Printf("Transaction hash: %s", tx) + } } c.Println("===============================================================") }, @@ -480,12 +512,208 @@ func getClient(url string) (client *EthClient) { return &EthClient{client: eth, rpcClient: rpc, url: url} } -func parseMethodParameters(c *ishell.Context, abi *abi.ABI, methodName string) (args []interface{}) { - inputParameters := abi.Methods[methodName].Inputs - fmt.Printf("%s\n", inputParameters) +func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName string) (args []interface{}, err error) { + inputParameters := abiStruct.Methods[methodName].Inputs + c.ShowPrompt(false) + defer c.ShowPrompt(true) + + for i := 0; i < len(inputParameters); i++ { + argument := inputParameters[i] + c.Printf("Enter input data for parameter %s:\n", argument.Name) + + input := c.ReadLine() + + c.Printf("Name: %s\n", argument.Name) + c.Printf("Type: %s\n", argument.Type) + c.Printf("Type: %s\n", argument.Type.Type) + c.Printf("Kind: %s\n", argument.Type.Kind) + c.Printf("Elem: %s\n", argument.Type.Elem) + if argument.Type.Elem != nil { + c.Printf("Elem Type: %s\n", argument.Type.Elem.Type) + c.Printf("Elem Kind: %s\n", argument.Type.Elem.Kind) + } + + c.Printf("Reflect byte type: %s\n", reflect.TypeOf([]byte{})) - for argument := range inputParameters { - fmt.Printf("%s\n", abi.UnmarshalJSON(argument)) + if argument.Type.Kind == reflect.Array || argument.Type.Kind == reflect.Slice { + c.Println("Argument is array\n") + + // Occurs if argument is address which resolves Kind to array with no element + if argument.Type.Type == reflect.TypeOf(common.Address{}) { + item, err := utils.ConvertToType(input, &argument.Type) + if err != nil { + c.Err(err) + } + args = append(args, item) + continue + } + + elementType := argument.Type.Elem + // bytes = []byte{} argument type = slice, no element, type equates to []uint8 + // byte[] = [][1]byte{} argument type = slice, element type = array, type equates to [][1]uint8 + // byte = bytes1 + // bytesn = [n]byte{} 0 < n < 33, argument type = array, no element, type equates to [n]uint8 + // bytesn[] = [][n]byte{} argument type = slice, element type = array, type equares to [][n]uint8 + // bytesn[m] = [m][n]byte{} argument type = array, element type = array, type equates to [m][n]uint8 + // Many annoying cases of byte arrays + + c.Printf("Argument type: %s\n", argument.Type.Type) + c.Printf("Byte array type: %s\n", reflect.TypeOf([]byte{})) + if argument.Type.Type == reflect.TypeOf([]byte{}) { + c.Printf("Element is byte\n") + bytes, err := hex.DecodeString(input) + if err != nil { + c.Err(err) + } + args = append(args, bytes) + } else { + c.Printf("Element type: %s\n", elementType.Type) + c.Printf("Element kind: %s\n", elementType.Kind) + c.Printf("Element size: %s\n", elementType.Size) + c.Printf("Element element: %s\n", elementType.Elem) + array := strings.Split(input, ",") + + argSize := argument.Type.Size + size := len(array) + if argSize != 0 { + for size != argSize { + c.Printf("Please enter %i comma-separated list of elements:\n", argSize) + input = c.ReadLine() + array = strings.Split(input, ",") + size = len(array) + } + } + + size = len(array) + + switch elementType.Type { + case reflect.TypeOf(bool(false)): + convertedArray := make([]bool, 0, size) + for _, item := range array { + b, err := utils.ConvertToBool(item) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, b) + } + args = append(args, convertedArray) + case reflect.TypeOf(int8(0)): + convertedArray := make([]int8, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 8) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int8(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(int16(0)): + convertedArray := make([]int16, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 16) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int16(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(int32(0)): + convertedArray := make([]int32, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 32) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int32(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(int64(0)): + convertedArray := make([]int64, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 64) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int64(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint8(0)): + convertedArray := make([]uint8, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 8) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint8(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint16(0)): + convertedArray := make([]uint16, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 16) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint16(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint32(0)): + convertedArray := make([]uint32, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 32) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint32(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint64(0)): + convertedArray := make([]uint64, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 64) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint64(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(&big.Int{}): + convertedArray := make([]*big.Int, 0, size) + for _, item := range array { + newInt := new(big.Int) + newInt, ok := newInt.SetString(item, 10) + if !ok { + return nil, errors.New("Could not convert string to big.int") + } + convertedArray = append(convertedArray, newInt) + } + args = append(args, convertedArray) + case reflect.TypeOf(common.Address{}): + convertedArray := make([]common.Address, 0, size) + for _, item := range array { + a := common.HexToAddress(item) + convertedArray = append(convertedArray, a) + } + args = append(args, convertedArray) + /*case reflect.TypeOf([]byte{}): + convertedArray := make([]common.Address, 0, size) + for _, item := range array { + a := common.HexToAddress(item) + convertedArray = append(convertedArray, a) + } + args = append(args, convertedArray)*/ + default: + errStr := fmt.Sprintf("Type %s not found", elementType.Type) + return nil, errors.New(errStr) + } + } + } else { + item, err := utils.ConvertToType(input, &argument.Type) + if err != nil { + c.Err(err) + } + args = append(args, item) + } } return @@ -500,4 +728,4 @@ func strToHex(input string) (output string) { output = strconv.FormatInt(int64(val), 16) return "0x" + output -} +} \ No newline at end of file diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index 895ef4b..c246e24 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -4,11 +4,13 @@ package contract import ( "context" "crypto/ecdsa" + "fmt" "encoding/json" "log" "math/big" "os" "strings" + "errors" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" @@ -160,31 +162,50 @@ func TransactionContract( gasLimit uint64, methodName string, args ...interface{}, -) *types.Transaction { +) (*types.Transaction, error) { + + fmt.Print("Marshalling ABI\n") abiStr, err := json.Marshal(contract.Info.AbiDefinition) if err != nil { - log.Fatal("ERROR marshalling abi to string", err) + errStr := fmt.Sprintf("ERROR marshalling abi to string: %s\n", err) + return nil, errors.New(errStr) + log.Fatal() } + + fmt.Print("JSONify ABI\n") abiContract, err := abi.JSON(strings.NewReader(string(abiStr))) if err != nil { - log.Fatal("ERROR reading contract ABI ", err) + errStr := fmt.Sprintf("ERROR reading contract ABI: %s\n", err) + return nil, errors.New(errStr) } + + fmt.Print("Packing Args to ABI\n") payload, err := abiContract.Pack(methodName, args...) if err != nil { - log.Fatal("ERROR packing the method name for the contract call: ", err) + errStr := fmt.Sprintf("ERROR packing the method name for the contract call: %s\n", err) + return nil, errors.New(errStr) } + + fmt.Print("Retrieving public key\n") from := crypto.PubkeyToAddress(userKey.PublicKey) + + fmt.Print("Creating transaction\n") tx := newTx(ctx, backend, &from, &to, amount, gasLimit, payload) + + fmt.Print("Signing transaction\n") signedTx := signTx(tx, userKey) + fmt.Print("SENDING TRANSACTION\n") + err = backend.SendTransaction(ctx, signedTx) if err != nil { - log.Fatal("ERROR sending transaction: ", err) + errStr := fmt.Sprintf("ERROR sending transaction: %s\n", err) + return nil, errors.New(errStr) } - return signedTx + return signedTx, nil } func CompileContract(contract string) (compiledContract *compiler.Contract) { diff --git a/ion-cli/contracts/function.go b/ion-cli/contracts/function.go index 43a7fa4..3aadea5 100644 --- a/ion-cli/contracts/function.go +++ b/ion-cli/contracts/function.go @@ -8,6 +8,7 @@ import ( "math/big" "os" "strings" + "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi" @@ -121,7 +122,7 @@ func VerifyExecute( amount *big.Int, ) (tx *types.Transaction) { - tx = TransactionContract( + tx, err := TransactionContract( ctx, backend, userKey, @@ -140,5 +141,8 @@ func VerifyExecute( receiptTriggerProofArr, // TEST_RECEIPT_NODES, triggerCalledBy, // TRIG_CALLED_BY, ) + if err != nil { + fmt.Println(err) + } return } diff --git a/ion-cli/contracts/trigger.go b/ion-cli/contracts/trigger.go index f960001..46e845a 100644 --- a/ion-cli/contracts/trigger.go +++ b/ion-cli/contracts/trigger.go @@ -4,6 +4,7 @@ package contract import ( "context" "crypto/ecdsa" + "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -19,7 +20,7 @@ func Fire( contract *compiler.Contract, toAddr common.Address, ) (tx *types.Transaction) { - tx = TransactionContract( + tx, err := TransactionContract( ctx, backend, userKey, @@ -30,5 +31,9 @@ func Fire( "fire", ) + if err != nil { + fmt.Println(err) + } + return } diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index 51a18bc..8658159 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -7,6 +7,7 @@ import ( "log" "os" "strings" + "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -86,7 +87,7 @@ func RegisterChain( validators []common.Address, registerHash common.Hash, ) (tx *types.Transaction) { - tx = TransactionContract( + tx, err := TransactionContract( ctx, backend, userKey, @@ -100,6 +101,10 @@ func RegisterChain( registerHash, ) + if err != nil { + fmt.Println(err) + } + return } @@ -114,7 +119,7 @@ func SubmitBlock( unsignedBlockHeaderRLP []byte, signedBlockHeaderRLP []byte, ) (tx *types.Transaction) { - tx = TransactionContract( + tx, err := TransactionContract( ctx, backend, userKey, @@ -127,6 +132,11 @@ func SubmitBlock( unsignedBlockHeaderRLP, signedBlockHeaderRLP, ) + + if err != nil { + fmt.Println(err) + } + return } diff --git a/ion-cli/utils/type.go b/ion-cli/utils/type.go new file mode 100644 index 0000000..f867a1c --- /dev/null +++ b/ion-cli/utils/type.go @@ -0,0 +1,105 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package utils + +import ( + "errors" + "fmt" + "math/big" + "strconv" + "reflect" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/accounts/abi" +) + +func ConvertToType(str string, typ *abi.Type) (interface{}, error) { + switch typ.Kind { + case reflect.String: + return str, nil + case reflect.Bool: + b, err := ConvertToBool(str) + return b, err + case reflect.Int8: + i, err := ConvertToInt(true, 8, str) + return i, err + case reflect.Int16: + i, err := ConvertToInt(true, 16, str) + return i, err + case reflect.Int32: + i, err := ConvertToInt(true, 32, str) + return i, err + case reflect.Int64: + i, err := ConvertToInt(true, 64, str) + return i, err + case reflect.Uint8: + u, err := ConvertToInt(false, 8, str) + return u, err + case reflect.Uint16: + u, err := ConvertToInt(false, 16, str) + return u, err + case reflect.Uint32: + u, err := ConvertToInt(false, 32, str) + return u, err + case reflect.Uint64: + u, err := ConvertToInt(false, 64, str) + return u, err + case reflect.Ptr: + i, err := ConvertToInt(false, typ.Size, str) + return i, err + case reflect.Array: + if typ.Type == reflect.TypeOf(common.Address{}) { + return common.HexToAddress(str), nil + } else { + return nil, errors.New("Conversion failed. Item is array type, cannot parse") + } + default: + errStr := fmt.Sprintf("Error, type not found: %s", typ.Kind) + return nil, errors.New(errStr) + } +} + +func ConvertToInt(signed bool, size int, value string) (interface{}, error) { + if size % 8 > 0 { + return nil, errors.New("Integer is not a multiple of 8") + } else if !isGoIntSize(size) { + newInt := new(big.Int) + newInt, ok := newInt.SetString(value, 10) + if !ok { + return nil, errors.New("Could not convert string to big.int") + } + + return newInt, nil + } else { + if signed { + i, err := strconv.ParseInt(value, 10, size) + if err != nil { + return nil, err + } + return i, nil + } else { + u, err := strconv.ParseUint(value, 10, size) + if err != nil { + return nil, err + } + return u, nil + } + } +} + +// MUST CHECK RETURNED ERROR ELSE WILL RETURN FALSE FOR ANY ERRONEOUS INPUT +func ConvertToBool(value string) (bool, error) { + b, err := strconv.ParseBool(value) + if err != nil { + return false, err + } + return b, nil +} + +func isGoIntSize(size int) (isGoPrimitive bool) { + switch size { + case 8, 16, 32, 64: + return true + default: + return false + } +} \ No newline at end of file From 0c1c957b30b11a79e66103fedaf7d479e5e1deb9 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Tue, 20 Nov 2018 18:15:21 +0000 Subject: [PATCH 162/203] Working type conversions. Abandoned 2d arrays. --- ion-cli/cli/cli.go | 350 ++++++++++++++++++++++++++++------- ion-cli/utils/type.go | 412 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 699 insertions(+), 63 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 3868605..a4c0231 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -523,69 +523,227 @@ func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName str input := c.ReadLine() - c.Printf("Name: %s\n", argument.Name) - c.Printf("Type: %s\n", argument.Type) - c.Printf("Type: %s\n", argument.Type.Type) - c.Printf("Kind: %s\n", argument.Type.Kind) - c.Printf("Elem: %s\n", argument.Type.Elem) - if argument.Type.Elem != nil { - c.Printf("Elem Type: %s\n", argument.Type.Elem.Type) - c.Printf("Elem Kind: %s\n", argument.Type.Elem.Kind) - } - - c.Printf("Reflect byte type: %s\n", reflect.TypeOf([]byte{})) + // bytes = []byte{} argument type = slice, no element, type equates to []uint8 + // byte[] = [][1]byte{} argument type = slice, element type = array, type equates to [][1]uint8 + // byte = bytes1 + // bytesn = [n]byte{} 0 < n < 33, argument type = array, no element, type equates to [n]uint8 + // bytesn[] = [][n]byte{} argument type = slice, element type = array, type equares to [][n]uint8 + // bytesn[m] = [m][n]byte{} argument type = array, element type = array, type equates to [m][n]uint8 + // Many annoying cases of byte arrays if argument.Type.Kind == reflect.Array || argument.Type.Kind == reflect.Slice { c.Println("Argument is array\n") - // Occurs if argument is address which resolves Kind to array with no element - if argument.Type.Type == reflect.TypeOf(common.Address{}) { - item, err := utils.ConvertToType(input, &argument.Type) - if err != nil { - c.Err(err) + // One dimensional byte array + // Accepts all byte arrays as hex string with pre-pended '0x' only + if argument.Type.Elem == nil { + if argument.Type.Type == reflect.TypeOf(common.Address{}) { + // address solidity type + item, err := utils.ConvertToType(input, &argument.Type) + if err != nil { + c.Err(err) + } + args = append(args, item) + continue + } else if argument.Type.Type == reflect.TypeOf([]byte{}) { + // bytes solidity type + bytes, err := hex.DecodeString(input[2:]) + if err != nil { + c.Err(err) + } + args = append(args, bytes) + continue + } else { + // Fixed byte array of size n; bytesn solidity type + // Any submitted bytes longer than the expected size will be truncated + + bytes, err := hex.DecodeString(input[2:]) + if err != nil { + c.Err(err) + } + + // Fixed sized arrays can't be created with variables as size + switch argument.Type.Size { + case 1: + var byteArray [1]byte + copy(byteArray[:], bytes[:1]) + args = append(args, byteArray) + case 2: + var byteArray [2]byte + copy(byteArray[:], bytes[:2]) + args = append(args, byteArray) + case 3: + var byteArray [3]byte + copy(byteArray[:], bytes[:3]) + args = append(args, byteArray) + case 4: + var byteArray [4]byte + copy(byteArray[:], bytes[:4]) + args = append(args, byteArray) + case 5: + var byteArray [5]byte + copy(byteArray[:], bytes[:5]) + args = append(args, byteArray) + case 6: + var byteArray [6]byte + copy(byteArray[:], bytes[:6]) + args = append(args, byteArray) + case 7: + var byteArray [7]byte + copy(byteArray[:], bytes[:7]) + args = append(args, byteArray) + case 8: + var byteArray [8]byte + copy(byteArray[:], bytes[:8]) + args = append(args, byteArray) + case 9: + var byteArray [9]byte + copy(byteArray[:], bytes[:9]) + args = append(args, byteArray) + case 10: + var byteArray [10]byte + copy(byteArray[:], bytes[:10]) + args = append(args, byteArray) + case 11: + var byteArray [11]byte + copy(byteArray[:], bytes[:11]) + args = append(args, byteArray) + case 12: + var byteArray [12]byte + copy(byteArray[:], bytes[:12]) + args = append(args, byteArray) + case 13: + var byteArray [13]byte + copy(byteArray[:], bytes[:13]) + args = append(args, byteArray) + case 14: + var byteArray [14]byte + copy(byteArray[:], bytes[:14]) + args = append(args, byteArray) + case 15: + var byteArray [15]byte + copy(byteArray[:], bytes[:15]) + args = append(args, byteArray) + case 16: + var byteArray [16]byte + copy(byteArray[:], bytes[:16]) + args = append(args, byteArray) + case 17: + var byteArray [17]byte + copy(byteArray[:], bytes[:17]) + args = append(args, byteArray) + case 18: + var byteArray [18]byte + copy(byteArray[:], bytes[:18]) + args = append(args, byteArray) + case 19: + var byteArray [19]byte + copy(byteArray[:], bytes[:19]) + args = append(args, byteArray) + case 20: + var byteArray [20]byte + copy(byteArray[:], bytes[:20]) + args = append(args, byteArray) + case 21: + var byteArray [21]byte + copy(byteArray[:], bytes[:21]) + args = append(args, byteArray) + case 22: + var byteArray [22]byte + copy(byteArray[:], bytes[:22]) + args = append(args, byteArray) + case 23: + var byteArray [23]byte + copy(byteArray[:], bytes[:23]) + args = append(args, byteArray) + case 24: + var byteArray [24]byte + copy(byteArray[:], bytes[:24]) + args = append(args, byteArray) + case 25: + var byteArray [25]byte + copy(byteArray[:], bytes[:25]) + args = append(args, byteArray) + case 26: + var byteArray [26]byte + copy(byteArray[:], bytes[:26]) + args = append(args, byteArray) + case 27: + var byteArray [27]byte + copy(byteArray[:], bytes[:27]) + args = append(args, byteArray) + case 28: + var byteArray [28]byte + copy(byteArray[:], bytes[:28]) + args = append(args, byteArray) + case 29: + var byteArray [29]byte + copy(byteArray[:], bytes[:29]) + args = append(args, byteArray) + case 30: + var byteArray [30]byte + copy(byteArray[:], bytes[:30]) + args = append(args, byteArray) + case 31: + var byteArray [31]byte + copy(byteArray[:], bytes[:31]) + args = append(args, byteArray) + case 32: + var byteArray [32]byte + copy(byteArray[:], bytes[:32]) + args = append(args, byteArray) + default: + errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %i incompatible", argument.Type.Size) + return nil, errors.New(errStr) + } + continue } - args = append(args, item) - continue + } + array := strings.Split(input, ",") + argSize := argument.Type.Size + size := len(array) + if argSize != 0 { + for size != argSize { + c.Printf("Please enter %i comma-separated list of elements:\n", argSize) + input = c.ReadLine() + array = strings.Split(input, ",") + size = len(array) + } + } + + size = len(array) + elementType := argument.Type.Elem - // bytes = []byte{} argument type = slice, no element, type equates to []uint8 - // byte[] = [][1]byte{} argument type = slice, element type = array, type equates to [][1]uint8 - // byte = bytes1 - // bytesn = [n]byte{} 0 < n < 33, argument type = array, no element, type equates to [n]uint8 - // bytesn[] = [][n]byte{} argument type = slice, element type = array, type equares to [][n]uint8 - // bytesn[m] = [m][n]byte{} argument type = array, element type = array, type equates to [m][n]uint8 - // Many annoying cases of byte arrays - - c.Printf("Argument type: %s\n", argument.Type.Type) - c.Printf("Byte array type: %s\n", reflect.TypeOf([]byte{})) - if argument.Type.Type == reflect.TypeOf([]byte{}) { - c.Printf("Element is byte\n") - bytes, err := hex.DecodeString(input) + + // Elements cannot be kind slice only mean slice + if elementType.Kind == reflect.Array { + // Is 2D byte array + /* Nightmare to implement, have to account for: + * Slice of fixed byte arrays; bytes32[] in solidity for example, generally bytesn[] + * Fixed array of fixed byte arrays; bytes32[10] in solidity for example bytesn[m] + + Since the upper bound of elements in an array in solidity is 2^256-1, and each fixed byte array + has a limit of bytes32 (bytes1, bytes2, ..., bytes31, bytes32), and Golang array creation takes + constant length values, we would have to paste the switch-case containing 1-32 fixed byte arrays + 2^256-1 times to handle every possibility. Since arrays of arrays in seldom used, we have not + implemented it. + */ + + return nil, errors.New("2D Arrays unsupported. Use \"bytes\" instead.") + + + /* + slice := make([]interface{}, 0, size) + err = addFixedByteArrays(array, elementType.Size, slice) if err != nil { - c.Err(err) + return nil, err } - args = append(args, bytes) + args = append(args, slice) + continue + */ } else { - c.Printf("Element type: %s\n", elementType.Type) - c.Printf("Element kind: %s\n", elementType.Kind) - c.Printf("Element size: %s\n", elementType.Size) - c.Printf("Element element: %s\n", elementType.Elem) - array := strings.Split(input, ",") - - argSize := argument.Type.Size - size := len(array) - if argSize != 0 { - for size != argSize { - c.Printf("Please enter %i comma-separated list of elements:\n", argSize) - input = c.ReadLine() - array = strings.Split(input, ",") - size = len(array) - } - } - - size = len(array) - switch elementType.Type { case reflect.TypeOf(bool(false)): convertedArray := make([]bool, 0, size) @@ -695,24 +853,90 @@ func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName str convertedArray = append(convertedArray, a) } args = append(args, convertedArray) - /*case reflect.TypeOf([]byte{}): - convertedArray := make([]common.Address, 0, size) - for _, item := range array { - a := common.HexToAddress(item) - convertedArray = append(convertedArray, a) - } - args = append(args, convertedArray)*/ default: errStr := fmt.Sprintf("Type %s not found", elementType.Type) return nil, errors.New(errStr) } } } else { - item, err := utils.ConvertToType(input, &argument.Type) - if err != nil { - c.Err(err) + switch argument.Type.Kind { + case reflect.String: + args = append(args, input) + case reflect.Bool: + b, err := utils.ConvertToBool(input) + if err != nil { + return nil, err + } + args = append(args, b) + case reflect.Int8: + i, err := strconv.ParseInt(input, 10, 8) + if err != nil { + return nil, err + } + args = append(args, int8(i)) + case reflect.Int16: + i, err := strconv.ParseInt(input, 10, 16) + if err != nil { + return nil, err + } + args = append(args, int16(i)) + case reflect.Int32: + i, err := strconv.ParseInt(input, 10, 32) + if err != nil { + return nil, err + } + args = append(args, int32(i)) + case reflect.Int64: + i, err := strconv.ParseInt(input, 10, 64) + if err != nil { + return nil, err + } + args = append(args, int64(i)) + case reflect.Uint8: + u, err := strconv.ParseUint(input, 10, 8) + if err != nil { + return nil, err + } + args = append(args, uint8(u)) + case reflect.Uint16: + u, err := strconv.ParseUint(input, 10, 16) + if err != nil { + return nil, err + } + args = append(args, uint16(u)) + case reflect.Uint32: + u, err := strconv.ParseUint(input, 10, 32) + if err != nil { + return nil, err + } + args = append(args, uint32(u)) + case reflect.Uint64: + u, err := strconv.ParseUint(input, 10, 64) + if err != nil { + return nil, err + } + args = append(args, uint64(u)) + case reflect.Ptr: + newInt := new(big.Int) + newInt, ok := newInt.SetString(input, 10) + if !ok { + return nil, errors.New("Could not convert string to big.int") + } + if err != nil { + return nil, err + } + args = append(args, newInt) + case reflect.Array: + if argument.Type.Type == reflect.TypeOf(common.Address{}) { + address := common.HexToAddress(input) + args = append(args, address) + } else { + return nil, errors.New("Conversion failed. Item is array type, cannot parse") + } + default: + errStr := fmt.Sprintf("Error, type not found: %s", argument.Type.Kind) + return nil, errors.New(errStr) } - args = append(args, item) } } diff --git a/ion-cli/utils/type.go b/ion-cli/utils/type.go index f867a1c..fe79707 100644 --- a/ion-cli/utils/type.go +++ b/ion-cli/utils/type.go @@ -7,11 +7,423 @@ import ( "math/big" "strconv" "reflect" + "encoding/hex" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/abiosoft/ishell" ) +func ConvertAndAppend(c *ishell.Context, input string, argument *abi.Argument, output []interface{}) ([]interface{}, error) { + if argument.Type.Kind == reflect.Array || argument.Type.Kind == reflect.Slice { + c.Println("Argument is array\n") + + // One dimensional byte array + // Accepts all byte arrays as hex string with pre-pended '0x' only + if argument.Type.Elem == nil { + if argument.Type.Type == reflect.TypeOf(common.Address{}) { + // address solidity type + item, err := ConvertToType(input, &argument.Type) + if err != nil { + return nil, err + } + output = append(output, item) + return output, nil + } else if argument.Type.Type == reflect.TypeOf([]byte{}) { + // bytes solidity type + bytes, err := hex.DecodeString(input[2:]) + if err != nil { + return nil, err + } + output = append(output, bytes) + return output, nil + } else { + // Fixed byte array of size n; bytesn solidity type + // Any submitted bytes longer than the expected size will be truncated + + bytes, err := hex.DecodeString(input[2:]) + if err != nil { + return nil, err + } + + // Fixed sized arrays can't be created with variables as size + switch argument.Type.Size { + case 1: + var byteArray [1]byte + copy(byteArray[:], bytes[:1]) + output = append(output, byteArray) + case 2: + var byteArray [2]byte + copy(byteArray[:], bytes[:2]) + output = append(output, byteArray) + case 3: + var byteArray [3]byte + copy(byteArray[:], bytes[:3]) + output = append(output, byteArray) + case 4: + var byteArray [4]byte + copy(byteArray[:], bytes[:4]) + output = append(output, byteArray) + case 5: + var byteArray [5]byte + copy(byteArray[:], bytes[:5]) + output = append(output, byteArray) + case 6: + var byteArray [6]byte + copy(byteArray[:], bytes[:6]) + output = append(output, byteArray) + case 7: + var byteArray [7]byte + copy(byteArray[:], bytes[:7]) + output = append(output, byteArray) + case 8: + var byteArray [8]byte + copy(byteArray[:], bytes[:8]) + output = append(output, byteArray) + case 9: + var byteArray [9]byte + copy(byteArray[:], bytes[:9]) + output = append(output, byteArray) + case 10: + var byteArray [10]byte + copy(byteArray[:], bytes[:10]) + output = append(output, byteArray) + case 11: + var byteArray [11]byte + copy(byteArray[:], bytes[:11]) + output = append(output, byteArray) + case 12: + var byteArray [12]byte + copy(byteArray[:], bytes[:12]) + output = append(output, byteArray) + case 13: + var byteArray [13]byte + copy(byteArray[:], bytes[:13]) + output = append(output, byteArray) + case 14: + var byteArray [14]byte + copy(byteArray[:], bytes[:14]) + output = append(output, byteArray) + case 15: + var byteArray [15]byte + copy(byteArray[:], bytes[:15]) + output = append(output, byteArray) + case 16: + var byteArray [16]byte + copy(byteArray[:], bytes[:16]) + output = append(output, byteArray) + case 17: + var byteArray [17]byte + copy(byteArray[:], bytes[:17]) + output = append(output, byteArray) + case 18: + var byteArray [18]byte + copy(byteArray[:], bytes[:18]) + output = append(output, byteArray) + case 19: + var byteArray [19]byte + copy(byteArray[:], bytes[:19]) + output = append(output, byteArray) + case 20: + var byteArray [20]byte + copy(byteArray[:], bytes[:20]) + output = append(output, byteArray) + case 21: + var byteArray [21]byte + copy(byteArray[:], bytes[:21]) + output = append(output, byteArray) + case 22: + var byteArray [22]byte + copy(byteArray[:], bytes[:22]) + output = append(output, byteArray) + case 23: + var byteArray [23]byte + copy(byteArray[:], bytes[:23]) + output = append(output, byteArray) + case 24: + var byteArray [24]byte + copy(byteArray[:], bytes[:24]) + output = append(output, byteArray) + case 25: + var byteArray [25]byte + copy(byteArray[:], bytes[:25]) + output = append(output, byteArray) + case 26: + var byteArray [26]byte + copy(byteArray[:], bytes[:26]) + output = append(output, byteArray) + case 27: + var byteArray [27]byte + copy(byteArray[:], bytes[:27]) + output = append(output, byteArray) + case 28: + var byteArray [28]byte + copy(byteArray[:], bytes[:28]) + output = append(output, byteArray) + case 29: + var byteArray [29]byte + copy(byteArray[:], bytes[:29]) + output = append(output, byteArray) + case 30: + var byteArray [30]byte + copy(byteArray[:], bytes[:30]) + output = append(output, byteArray) + case 31: + var byteArray [31]byte + copy(byteArray[:], bytes[:31]) + output = append(output, byteArray) + case 32: + var byteArray [32]byte + copy(byteArray[:], bytes[:32]) + output = append(output, byteArray) + default: + errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %i incompatible", argument.Type.Size) + return nil, errors.New(errStr) + } + return output, nil + } + + } + + array := strings.Split(input, ",") + argSize := argument.Type.Size + size := len(array) + if argSize != 0 { + for size != argSize { + c.Printf("Please enter %i comma-separated list of elements:\n", argSize) + input = c.ReadLine() + array = strings.Split(input, ",") + size = len(array) + } + } + + size = len(array) + + elementType := argument.Type.Elem + + // Elements cannot be kind slice only mean slice + if elementType.Kind == reflect.Array { + // Is 2D byte array + /* Nightmare to implement, have to account for: + * Slice of fixed byte arrays; bytes32[] in solidity for example, generally bytesn[] + * Fixed array of fixed byte arrays; bytes32[10] in solidity for example bytesn[m] + + Since the upper bound of elements in an array in solidity is 2^256-1, and each fixed byte array + has a limit of bytes32 (bytes1, bytes2, ..., bytes31, bytes32), and Golang array creation takes + constant length values, we would have to paste the switch-case containing 1-32 fixed byte arrays + 2^256-1 times to handle every possibility. Since arrays of arrays in seldom used, we have not + implemented it. + */ + + return nil, errors.New("2D Arrays unsupported. Use \"bytes\" instead.") + + + /* + slice := make([]interface{}, 0, size) + err = addFixedByteArrays(array, elementType.Size, slice) + if err != nil { + return nil, err + } + output = append(output, slice) + continue + */ + } else { + switch elementType.Type { + case reflect.TypeOf(bool(false)): + convertedArray := make([]bool, 0, size) + for _, item := range array { + b, err := ConvertToBool(item) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, b) + } + output = append(output, convertedArray) + case reflect.TypeOf(int8(0)): + convertedArray := make([]int8, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 8) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int8(i)) + } + output = append(output, convertedArray) + case reflect.TypeOf(int16(0)): + convertedArray := make([]int16, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 16) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int16(i)) + } + output = append(output, convertedArray) + case reflect.TypeOf(int32(0)): + convertedArray := make([]int32, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 32) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int32(i)) + } + output = append(output, convertedArray) + case reflect.TypeOf(int64(0)): + convertedArray := make([]int64, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 64) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int64(i)) + } + output = append(output, convertedArray) + case reflect.TypeOf(uint8(0)): + convertedArray := make([]uint8, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 8) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint8(u)) + } + output = append(output, convertedArray) + case reflect.TypeOf(uint16(0)): + convertedArray := make([]uint16, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 16) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint16(u)) + } + output = append(output, convertedArray) + case reflect.TypeOf(uint32(0)): + convertedArray := make([]uint32, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 32) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint32(u)) + } + output = append(output, convertedArray) + case reflect.TypeOf(uint64(0)): + convertedArray := make([]uint64, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 64) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint64(u)) + } + output = append(output, convertedArray) + case reflect.TypeOf(&big.Int{}): + convertedArray := make([]*big.Int, 0, size) + for _, item := range array { + newInt := new(big.Int) + newInt, ok := newInt.SetString(item, 10) + if !ok { + return nil, errors.New("Could not convert string to big.int") + } + convertedArray = append(convertedArray, newInt) + } + output = append(output, convertedArray) + case reflect.TypeOf(common.Address{}): + convertedArray := make([]common.Address, 0, size) + for _, item := range array { + a := common.HexToAddress(item) + convertedArray = append(convertedArray, a) + } + output = append(output, convertedArray) + default: + errStr := fmt.Sprintf("Type %s not found", elementType.Type) + return nil, errors.New(errStr) + } + } + } else { + switch argument.Type.Kind { + case reflect.String: + output = append(output, input) + case reflect.Bool: + b, err := ConvertToBool(input) + if err != nil { + return nil, err + } + output = append(output, b) + case reflect.Int8: + i, err := strconv.ParseInt(input, 10, 8) + if err != nil { + return nil, err + } + output = append(output, int8(i)) + case reflect.Int16: + i, err := strconv.ParseInt(input, 10, 16) + if err != nil { + return nil, err + } + output = append(output, int16(i)) + case reflect.Int32: + i, err := strconv.ParseInt(input, 10, 32) + if err != nil { + return nil, err + } + output = append(output, int32(i)) + case reflect.Int64: + i, err := strconv.ParseInt(input, 10, 64) + if err != nil { + return nil, err + } + output = append(output, int64(i)) + case reflect.Uint8: + u, err := strconv.ParseUint(input, 10, 8) + if err != nil { + return nil, err + } + output = append(output, uint8(u)) + case reflect.Uint16: + u, err := strconv.ParseUint(input, 10, 16) + if err != nil { + return nil, err + } + output = append(output, uint16(u)) + case reflect.Uint32: + u, err := strconv.ParseUint(input, 10, 32) + if err != nil { + return nil, err + } + output = append(output, uint32(u)) + case reflect.Uint64: + u, err := strconv.ParseUint(input, 10, 64) + if err != nil { + return nil, err + } + output = append(output, uint64(u)) + case reflect.Ptr: + newInt := new(big.Int) + newInt, ok := newInt.SetString(input, 10) + if !ok { + return nil, errors.New("Could not convert string to big.int") + } + output = append(output, newInt) + case reflect.Array: + if argument.Type.Type == reflect.TypeOf(common.Address{}) { + address := common.HexToAddress(input) + output = append(output, address) + } else { + return nil, errors.New("Conversion failed. Item is array type, cannot parse") + } + default: + errStr := fmt.Sprintf("Error, type not found: %s", argument.Type.Kind) + return nil, errors.New(errStr) + } + } + return output, nil +} + func ConvertToType(str string, typ *abi.Type) (interface{}, error) { switch typ.Kind { case reflect.String: From 8943cc240568c915b8807665e574f3aa83bde8ec Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 21 Nov 2018 16:16:26 +0000 Subject: [PATCH 163/203] Extended functions and cleaned code. CLI can deploy and call functions to any client. --- contracts/functional/Trigger.sol | 16 +++ ion-cli/cli/cli.go | 200 ++++++++++++++++++++----------- ion-cli/config/config.go | 9 +- ion-cli/contracts/contract.go | 15 ++- ion-cli/contracts/function.go | 10 +- ion-cli/contracts/ion.go | 10 +- ion-cli/contracts/validation.go | 6 +- 7 files changed, 169 insertions(+), 97 deletions(-) diff --git a/contracts/functional/Trigger.sol b/contracts/functional/Trigger.sol index dd06a4c..ed880ca 100644 --- a/contracts/functional/Trigger.sol +++ b/contracts/functional/Trigger.sol @@ -23,4 +23,20 @@ contract Trigger { function fire() public { emit Triggered(msg.sender); } + + event Boolean(bool b); + event Int256(int256 i); + event Int8(int8 i); + event Address(address a); + event Bytes(bytes b); + event Addresses(address[] a); + + function testTypes(bool b, int256 i256, int8 i8, address a, bytes by, address[] addresses) { + emit Boolean(b); + emit Int256(i256); + emit Int8(i8); + emit Address(a); + emit Bytes(by); + emit Addresses(addresses); + } } diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index a4c0231..8dd84b0 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -4,7 +4,6 @@ package cli import ( "context" "fmt" - "log" "encoding/hex" "math/big" "strconv" @@ -17,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/abiosoft/ishell" @@ -37,35 +37,9 @@ func Launch( // Create new context ctx := context.Background() - //ethclientTo := ethclient.NewClient(clientTo) - ethclientFrom := ethclient.NewClient(clientFrom) - var ethClient *EthClient = nil var contracts map[string]*contract.ContractInstance = make(map[string]*contract.ContractInstance) var accounts map[string]*config.Account = make(map[string]*config.Account) - contracts = contracts - accounts = accounts - - // Get a suggested gas price - gasPrice, err := ethclientFrom.SuggestGasPrice(ctx) - if err != nil { - log.Fatal(err) - } - - // Create an authorized transactor and corrsponding privateKey - authTo, keyTo := config.InitUser(configuration.KeystoreTo, configuration.PasswordTo) - authTo.Value = big.NewInt(0) // in wei - authTo.GasLimit = uint64(100000) // in units - authTo.GasPrice = gasPrice - - // Create an authorized transactor and spend 1 unicorn - authFrom, keyFrom := config.InitUser(configuration.KeystoreFrom, configuration.PasswordFrom) - authFrom.Value = big.NewInt(0) // in wei - authFrom.GasLimit = uint64(100000) // in units - authFrom.GasPrice = gasPrice - - keyTo = keyTo - keyFrom = keyFrom //--------------------------------------------------------------------------------------------- // RPC Client Specific Commands @@ -88,18 +62,16 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "addContractInstance", - Help: "use: \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n\t\t\t\tdescription: Compiles a contract for use", + Help: "use: \taddContractInstance [name] [path/to/solidity/contract]\n\t\t\t\tdescription: Compiles a contract for use", Func: func(c *ishell.Context) { - if len(c.Args) != 3 { - c.Println("Usage: \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n") + if len(c.Args) != 2 { + c.Println("Usage: \taddContractInstances [name] [path/to/solidity/contract]\n") } else { - compiledContract := contract.CompileContractAt(c.Args[1]) - _, Abi := contract.GetContractBytecodeAndABI(compiledContract) - abistruct, err := abi.JSON(strings.NewReader(Abi)) + err := addContractInstance(c.Args[1], c.Args[0], contracts) if err != nil { - c.Err(err) + c.Println(err) + return } - contracts[c.Args[0]] = &contract.ContractInstance{Contract: compiledContract, Address: common.HexToAddress(c.Args[2]), Abi: &abistruct} } c.Println("===============================================================") }, @@ -118,14 +90,24 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "addAccount", - Help: "use: \taddAccount [name] [path/to/keystore] [password] \n\t\t\t\tdescription: Add account to be used for transactions", + Help: "use: \taddAccount [name] [path/to/keystore]\n\t\t\t\tdescription: Add account to be used for transactions", Func: func(c *ishell.Context) { - if len(c.Args) != 3 { - c.Println("Usage: \taddAccount [name] [path/to/keystore] [password] \n") + if len(c.Args) != 2 { + c.Println("Usage: \taddAccount [name] [path/to/keystore]\n") } else { - auth, key := config.InitUser(c.Args[1], c.Args[2]) + c.ShowPrompt(false) + defer c.ShowPrompt(true) + c.Println("Please provide your key decryption password.") + input := c.ReadPassword() + auth, key, err := config.InitUser(c.Args[1], input) + if err != nil { + c.Println(err) + return + } account := &config.Account{Auth: auth, Key: key} accounts[c.Args[0]] = account + + c.Println("Account added succesfully.") } c.Println("===============================================================") }, @@ -142,12 +124,61 @@ func Launch( }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "deployContract", + Help: "use: \tdeployContract [contract name] [account name] \n\t\t\t\tdescription: Deploys specified contract instance to connected client", + Func: func(c *ishell.Context) { + if len(c.Args) != 2 { + c.Println("Usage: \tdeployContract [contract name] [account name] \n") + } else { + if ethClient == nil { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + contractInstance := contracts[c.Args[0]] + if contractInstance == nil { + errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) + c.Println(errStr) + return + } + + binStr, abiStr := contract.GetContractBytecodeAndABI(contractInstance.Contract) + + account := accounts[c.Args[1]] + if account == nil { + errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore] [password] \n", c.Args[1]) + c.Println(errStr) + return + } + + tx := contract.CompileAndDeployContract( + ctx, + ethClient.client, + account.Key.PrivateKey, + binStr, + abiStr, + nil, + uint64(3000000), + ) + + c.Println("Waiting for contract to be deployed") + addr, err := bind.WaitDeployed(ctx, ethClient.client, tx) + if err != nil { + c.Println(err) + return + } + c.Printf("Deployed contract at: %s\n", addr.String()) + } + c.Println("===============================================================") + }, + }) + shell.AddCmd(&ishell.Cmd{ Name: "messageCallFunction", - Help: "use: \tmessageCallFunction [contract name] [function name] [from account name] [amount] [gasLimit] \n\t\t\t\tdescription: Connects to an RPC client to be used", + Help: "use: \tmessageCallFunction [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n\t\t\t\tdescription: Connects to an RPC client to be used", Func: func(c *ishell.Context) { - if len(c.Args) != 5 { - c.Println("Usage: \tmessageCallFunction [contract name] [function name] [from account name] [amount] [gasLimit] \n") + if len(c.Args) != 6 { + c.Println("Usage: \tmessageCallFunction [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n") } else { if ethClient == nil { c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") @@ -157,6 +188,7 @@ func Launch( instance := contracts[c.Args[0]] methodName := c.Args[1] account := accounts[c.Args[2]] + contractDeployedAddress := common.HexToAddress(c.Args[3]) if instance == nil { errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) @@ -170,11 +202,11 @@ func Launch( } amount := new(big.Int) - amount, ok := amount.SetString(c.Args[3], 10) + amount, ok := amount.SetString(c.Args[4], 10) if !ok { c.Err(errors.New("Please enter an integer for ")) } - gasLimit, err := strconv.ParseUint(c.Args[4], 10, 64) + gasLimit, err := strconv.ParseUint(c.Args[5], 10, 64) if err != nil { c.Err(errors.New("Please enter an integer for ")) } @@ -189,17 +221,13 @@ func Launch( c.Printf("Error parsing parameters: %s\n", err) return } - //inputs := []interface{}{[]bool{true, false}, []bool{false,false,true}} - - c.Printf("Inputs = %s\n", inputs) - c.Printf("First index type: %s\n", reflect.TypeOf(inputs[0])) tx, err := contract.TransactionContract( ctx, ethClient.client, account.Key.PrivateKey, instance.Contract, - instance.Address, + contractDeployedAddress, amount, gasLimit, c.Args[1], @@ -209,7 +237,13 @@ func Launch( c.Println(err) return } else { - c.Printf("Transaction hash: %s", tx) + c.Println("Waiting for transaction to be mined...") + receipt, err := bind.WaitMined(ctx, ethClient.client, tx) + if err != nil { + c.Println(err) + return + } + c.Printf("Transaction hash: %s\n", receipt.TxHash.String()) } } c.Println("===============================================================") @@ -220,17 +254,18 @@ func Launch( Name: "getBlockByNumber", Help: "use: \tgetBlockByNumber [rpc url] [integer] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", Func: func(c *ishell.Context) { - if len(c.Args) != 2 { + if len(c.Args) == 1 { if ethClient != nil { getBlockByNumber(ethClient, c.Args[0]) } else { - c.Println("Usage: \tgetBlock [rpc url] [integer] \n") + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return } - } else { - c.Println("Connecting to client...\n") - newClient := getClient(c.Args[0]) - getBlockByNumber(newClient, c.Args[1]) - } + } else if len(c.Args) == 2 { + getBlockByNumber(getClient(c.Args[0]), c.Args[1]) + } else { + c.Println("Usage: \tgetBlock [rpc url] [integer] \n") + } c.Println("===============================================================") }, }) @@ -239,33 +274,37 @@ func Launch( Name: "getBlockByHash", Help: "use: \tgetBlockByNumber [rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", Func: func(c *ishell.Context) { - if len(c.Args) != 2 { - if (ethClient != nil) { + if len(c.Args) == 1 { + if ethClient != nil { getBlockByHash(ethClient, c.Args[0]) } else { - c.Println("Usage: \tgetBlock [rpc url] [hash] \n") + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return } - } else { - c.Println("Connecting to client...\n") - newClient := getClient(c.Args[0]) - getBlockByHash(newClient, c.Args[1]) - } + } else if len(c.Args) == 2 { + getBlockByHash(getClient(c.Args[0]), c.Args[1]) + } else { + c.Println("Usage: \tgetBlock [optional rpc url] [hash] \n") + } c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ Name: "getProof", - Help: "use: \tgetProof [rpc url] [Transaction Hash] \n\t\t\t\tdescription: Returns a merkle patricia proof of a specific transaction and its receipt in a block", + Help: "use: \tgetProof [optional rpc url] [Transaction Hash] \n\t\t\t\tdescription: Returns a merkle patricia proof of a specific transaction and its receipt in a block", Func: func(c *ishell.Context) { - if len(c.Args) != 2 { - if (ethClient != nil) { + if len(c.Args) == 1 { + if ethClient != nil { getProof(ethClient, c.Args[0]) } else { - c.Println("Usage: \tgetBlock [rpc url] [hash] \n") + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return } - } else { + } else if len(c.Args) == 2 { getProof(getClient(c.Args[0]), c.Args[1]) + } else { + c.Println("Usage: \tgetBlock [optional rpc url] [hash] \n") } c.Println("===============================================================") }, @@ -718,11 +757,12 @@ func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName str elementType := argument.Type.Elem // Elements cannot be kind slice only mean slice - if elementType.Kind == reflect.Array { + if elementType.Kind == reflect.Array && elementType.Type != reflect.TypeOf(common.Address{}) { // Is 2D byte array /* Nightmare to implement, have to account for: * Slice of fixed byte arrays; bytes32[] in solidity for example, generally bytesn[] * Fixed array of fixed byte arrays; bytes32[10] in solidity for example bytesn[m] + * Slice or fixed array of string; identical to above two cases as string in solidity is array of bytes Since the upper bound of elements in an array in solidity is 2^256-1, and each fixed byte array has a limit of bytes32 (bytes1, bytes2, ..., bytes31, bytes32), and Golang array creation takes @@ -943,6 +983,24 @@ func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName str return } +func checkClientExists(client *EthClient) bool { + return client != nil +} + +func addContractInstance(pathToContract string, contractName string, contracts map[string]*contract.ContractInstance) (error) { + compiledContract, err := contract.CompileContractAt(pathToContract) + if err != nil { + return err + } + _, Abi := contract.GetContractBytecodeAndABI(compiledContract) + abistruct, err := abi.JSON(strings.NewReader(Abi)) + if err != nil { + return err + } + contracts[contractName] = &contract.ContractInstance{Contract: compiledContract, Abi: &abistruct} + return nil +} + func strToHex(input string) (output string) { val, err := strconv.Atoi(input) if err != nil { diff --git a/ion-cli/config/config.go b/ion-cli/config/config.go index 8ca770e..34e3322 100644 --- a/ion-cli/config/config.go +++ b/ion-cli/config/config.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" "strings" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -60,23 +59,23 @@ func ReadString(path string) (contents string) { } -func InitUser(privkeystore string, password string) (auth *bind.TransactOpts, userkey *keystore.Key) { +func InitUser(privkeystore string, password string) (auth *bind.TransactOpts, userkey *keystore.Key, err error) { // retrieve private key keyjson, err := ioutil.ReadFile(privkeystore) if err != nil { - fmt.Println("Error failed to read keystore: %v", err) + return nil, nil, err } userkey, err = keystore.DecryptKey(keyjson, password) if err != nil { - fmt.Println("Error json key failed to decrypt: %v", err) + return nil, nil, err } // Create an authorized transactor key := ReadString(privkeystore) auth, err = bind.NewTransactor(strings.NewReader(key), password) if err != nil { - log.Fatalf("Error failed to create authorized transactor: %v", err) + return nil, nil, err } return diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index c246e24..0adf166 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -24,7 +24,6 @@ import ( // ContractInstance is just an util type to output contract and address type ContractInstance struct { Contract *compiler.Contract - Address common.Address Abi *abi.ABI } @@ -94,7 +93,7 @@ func signTx(tx *types.Transaction, userKey *ecdsa.PrivateKey) *types.Transaction return signedTx } -func compileAndDeployContract( +func CompileAndDeployContract( ctx context.Context, backend bind.ContractBackend, userKey *ecdsa.PrivateKey, @@ -208,24 +207,24 @@ func TransactionContract( return signedTx, nil } -func CompileContract(contract string) (compiledContract *compiler.Contract) { +func CompileContract(contract string) (compiledContract *compiler.Contract, err error) { basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" contractPath := basePath + contract + ".sol" contracts, err := compiler.CompileSolidity("", contractPath) if err != nil { - log.Fatal("ERROR failed to compile contract:", err) + return nil, err } compiledContract = contracts[basePath+contract+".sol:"+contract] - return + return compiledContract, nil } -func CompileContractAt(contractPath string) (compiledContract *compiler.Contract) { +func CompileContractAt(contractPath string) (compiledContract *compiler.Contract, err error) { contract, err := compiler.CompileSolidity("", contractPath) if err != nil { - log.Fatal("ERROR failed to compile contract:", err) + return nil, err } path := strings.Split(contractPath, "/") @@ -233,5 +232,5 @@ func CompileContractAt(contractPath string) (compiledContract *compiler.Contract compiledContract = contract[contractPath+":"+strings.Replace(contractName, ".sol", "", -1)] - return + return compiledContract, nil } diff --git a/ion-cli/contracts/function.go b/ion-cli/contracts/function.go index 3aadea5..23e4252 100644 --- a/ion-cli/contracts/function.go +++ b/ion-cli/contracts/function.go @@ -43,7 +43,7 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( // --------------------------------------------- // DEPLOY TRIGGER EVENT CONTRACT // --------------------------------------------- - triggerEventSignedTx := compileAndDeployContract( + triggerEventSignedTx := CompileAndDeployContract( ctx, client, userKey, @@ -70,7 +70,7 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( // --------------------------------------------- // DEPLOY CONSUMER FUNCTION CONTRACT // --------------------------------------------- - consumerFunctionSignedTx := compileAndDeployContract( + consumerFunctionSignedTx := CompileAndDeployContract( ctx, client, userKey, @@ -86,10 +86,10 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( if err != nil { log.Fatal("ERROR failed to compile TriggerEventVerifier.sol:", err) } - resChan <- ContractInstance{triggerEventVerifierContract, triggerEventAddr, &triggerAbi} + resChan <- ContractInstance{triggerEventVerifierContract, &triggerAbi} // wait for consumer function contract to be deployed - consumerFunctionAddr, err := bind.WaitDeployed(ctx, deployBackend, consumerFunctionSignedTx) + _, err = bind.WaitDeployed(ctx, deployBackend, consumerFunctionSignedTx) if err != nil { log.Fatal("ERROR while waiting for contract deployment") } @@ -98,7 +98,7 @@ func CompileAndDeployTriggerVerifierAndConsumerFunction( if err != nil { log.Fatal("ERROR failed to compile Function.sol:", err) } - resChan <- ContractInstance{consumerFunctionContract, consumerFunctionAddr, &functionAbi} + resChan <- ContractInstance{consumerFunctionContract, &functionAbi} }() return resChan diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go index 6dd8e73..c68dc70 100644 --- a/ion-cli/contracts/ion.go +++ b/ion-cli/contracts/ion.go @@ -41,7 +41,7 @@ func CompileAndDeployIon( // --------------------------------------------- // DEPLOY PATRICIA LIB ADDRESS // --------------------------------------------- - patriciaTrieSignedTx := compileAndDeployContract( + patriciaTrieSignedTx := CompileAndDeployContract( ctx, client, userKey, @@ -71,7 +71,7 @@ func CompileAndDeployIon( // replace palceholder with Prticia Trie Lib address var re = regexp.MustCompile(`__.*__`) ionBinStrWithLibAddr := re.ReplaceAllString(ionBinStr, patriciaTrieAddr.Hex()[2:]) - ionSignedTx := compileAndDeployContract( + ionSignedTx := CompileAndDeployContract( ctx, client, userKey, @@ -88,10 +88,10 @@ func CompileAndDeployIon( } // only stop blocking the first result after the Ion contract as been deploy // this guarantees that it works well with the blockchain simulator Commit() - resChan <- ContractInstance{patriciaTrieContract, patriciaTrieAddr, &patriciaAbi} + resChan <- ContractInstance{patriciaTrieContract, &patriciaAbi} // wait for Ion to be deployed - ionAddr, err := bind.WaitDeployed(ctx, deployBackend, ionSignedTx) + _, err = bind.WaitDeployed(ctx, deployBackend, ionSignedTx) if err != nil { log.Fatal("ERROR while waiting for contract deployment") } @@ -100,7 +100,7 @@ func CompileAndDeployIon( if err != nil { log.Fatal("ERROR failed to compile Ion.sol:", err) } - resChan <- ContractInstance{ionContract, ionAddr, &ionAbi} + resChan <- ContractInstance{ionContract, &ionAbi} }() return resChan diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go index 8658159..f092845 100644 --- a/ion-cli/contracts/validation.go +++ b/ion-cli/contracts/validation.go @@ -41,7 +41,7 @@ func CompileAndDeployValidation( // --------------------------------------------- // DEPLOY VALIDATION CONTRACT // --------------------------------------------- - validationSignedTx := compileAndDeployContract( + validationSignedTx := CompileAndDeployContract( ctx, client, userKey, @@ -62,7 +62,7 @@ func CompileAndDeployValidation( deployBackend := client.(bind.DeployBackend) // wait for PatriciaTrie library to be deployed - validationAddr, err := bind.WaitDeployed(ctx, deployBackend, validationSignedTx) + _, err := bind.WaitDeployed(ctx, deployBackend, validationSignedTx) if err != nil { log.Fatal("ERROR while waiting for contract deployment") } @@ -70,7 +70,7 @@ func CompileAndDeployValidation( if err != nil { log.Fatal("ERROR failed to compile Validation.sol:", err) } - resChan <- ContractInstance{validationContract, validationAddr, &abistruct} + resChan <- ContractInstance{validationContract, &abistruct} }() return resChan From 7a1fde09483cb838b5ca19c4d8bc820484c0166b Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Mon, 26 Nov 2018 17:24:58 +0000 Subject: [PATCH 164/203] Current version of CLI. Can deploy contracts and call functions but chain registration to clique fails. --- contracts/functional/Function.sol | 10 +- contracts/functional/Trigger.sol | 1 + contracts/functional/TriggerEventVerifier.sol | 8 +- ion-cli/Gopkg.toml | 4 + ion-cli/cli/cli.go | 334 +++++++++++++- ion-cli/cli/rpc.go | 69 ++- ion-cli/contracts/contract.go | 34 +- ion-cli/contracts/function.go | 148 ------ ion-cli/contracts/ion.go | 107 ----- ion-cli/contracts/trigger.go | 39 -- ion-cli/contracts/validation.go | 189 -------- package-lock.json | 427 +++++++++++++++++- test/integration-clique_ethereum.js | 24 + 13 files changed, 825 insertions(+), 569 deletions(-) delete mode 100644 ion-cli/contracts/function.go delete mode 100644 ion-cli/contracts/ion.go delete mode 100644 ion-cli/contracts/trigger.go delete mode 100644 ion-cli/contracts/validation.go diff --git a/contracts/functional/Function.sol b/contracts/functional/Function.sol index 591d370..9054b8e 100644 --- a/contracts/functional/Function.sol +++ b/contracts/functional/Function.sol @@ -31,7 +31,9 @@ contract Function { TriggerEventVerifier verifier; /* Custom event that fires when execution is performed successfully. */ - event Executed(); + event Executed(address caller); + event Another(address caller); + event Verify(bool result); /* Constructor. Requires Ion contract address and all used event verifier contract addresses. In this case we only use one verifier. */ @@ -42,7 +44,7 @@ contract Function { /* This is the function that is intended to be executed upon successful verification of proofs */ function execute() internal { - emit Executed(); + emit Executed(msg.sender); } /* @@ -92,8 +94,10 @@ contract Function { execute(); return true; } else { - return false; + emit Verify(false); } + emit Another(msg.sender); + return false; } } diff --git a/contracts/functional/Trigger.sol b/contracts/functional/Trigger.sol index ed880ca..44f2a28 100644 --- a/contracts/functional/Trigger.sol +++ b/contracts/functional/Trigger.sol @@ -12,6 +12,7 @@ pragma solidity ^0.4.23; Deployment Tx Hash: 0xc9500e84af2394e1d91b43e40c9c89f105636748f95ae05c11c73f2fd755795e Deployed Block Number: 2657325 `fire()` call Tx Hash 0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e + `fire()` call Tx Hash 0xf8a9a2f7e894f243fd12e5379c1dca2e139817f440e0ced7a8db42ec8dcf30ff The current tests are running against generated proofs from Rinkeby for the above data and consumes the event emitted in the transaction executed. diff --git a/contracts/functional/TriggerEventVerifier.sol b/contracts/functional/TriggerEventVerifier.sol index 3aef97a..33f0b78 100644 --- a/contracts/functional/TriggerEventVerifier.sol +++ b/contracts/functional/TriggerEventVerifier.sol @@ -41,13 +41,7 @@ contract TriggerEventVerifier is EventVerifier { the user expects. */ bytes20 b20_address = SolUtils.BytesToBytes20(data, data.length - 20); - assert( b20_address == _expectedAddress ); - - /* - Once verified, the logs of this specific event are proven as true and returns as such. Else, the execution - reverts. - */ - return true; + return b20_address == _expectedAddress; } } diff --git a/ion-cli/Gopkg.toml b/ion-cli/Gopkg.toml index abffbd1..1148bae 100644 --- a/ion-cli/Gopkg.toml +++ b/ion-cli/Gopkg.toml @@ -33,6 +33,10 @@ name = "github.com/ethereum/go-ethereum" version = "1.8.13" +[[constraint]] + branch = "solidity-compiler-addargs" + name = "github.com/clearmatics/autonity" + [[constraint]] name = "github.com/stretchr/testify" version = "1.2.2" diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 8dd84b0..9fc6bbf 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -53,7 +53,12 @@ func Launch( c.Println("Usage: \tconnectToClient [rpc url] \n") } else { c.Println("Connecting to client...\n") - ethClient = getClient(c.Args[0]) + client, err := getClient(c.Args[0]) + if err != nil { + c.Println("Could not connect to client.\n") + return + } + ethClient = client c.Println("Connected!") } c.Println("===============================================================") @@ -126,10 +131,10 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "deployContract", - Help: "use: \tdeployContract [contract name] [account name] \n\t\t\t\tdescription: Deploys specified contract instance to connected client", + Help: "use: \tdeployContract [contract name] [account name] [gas limit]\n\t\t\t\tdescription: Deploys specified contract instance to connected client", Func: func(c *ishell.Context) { - if len(c.Args) != 2 { - c.Println("Usage: \tdeployContract [contract name] [account name] \n") + if len(c.Args) != 3 { + c.Println("Usage: \tdeployContract [contract name] [account name] [gas limit] \n") } else { if ethClient == nil { c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") @@ -146,20 +151,37 @@ func Launch( account := accounts[c.Args[1]] if account == nil { - errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore] [password] \n", c.Args[1]) + errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore] \n", c.Args[1]) c.Println(errStr) return } - tx := contract.CompileAndDeployContract( + gasLimit, err := strconv.ParseUint(c.Args[2], 10, 64) + if err != nil { + c.Println(err) + return + } + + constructorInputs, err := parseMethodParameters(c, contractInstance.Abi, "") + if err != nil { + c.Printf("Error parsing constructor parameters: %s\n", err) + return + } + + tx, err := contract.CompileAndDeployContract( ctx, ethClient.client, account.Key.PrivateKey, binStr, abiStr, nil, - uint64(3000000), + gasLimit, + constructorInputs... ) + if err != nil { + c.Println(err) + return + } c.Println("Waiting for contract to be deployed") addr, err := bind.WaitDeployed(ctx, ethClient.client, tx) @@ -174,11 +196,11 @@ func Launch( }) shell.AddCmd(&ishell.Cmd{ - Name: "messageCallFunction", - Help: "use: \tmessageCallFunction [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n\t\t\t\tdescription: Connects to an RPC client to be used", + Name: "transactionMessage", + Help: "use: \ttransactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n\t\t\t\tdescription: Connects to an RPC client to be used", Func: func(c *ishell.Context) { if len(c.Args) != 6 { - c.Println("Usage: \tmessageCallFunction [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n") + c.Println("Usage: \ttransactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n") } else { if ethClient == nil { c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") @@ -196,7 +218,7 @@ func Launch( return } if account == nil { - errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore] [password] \n", c.Args[2]) + errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore]\n", c.Args[2]) c.Println(errStr) return } @@ -244,48 +266,173 @@ func Launch( return } c.Printf("Transaction hash: %s\n", receipt.TxHash.String()) + c.Printf("Mined in block: %s\n", receipt.TxHash.String()) } } c.Println("===============================================================") }, }) + /*shell.AddCmd(&ishell.Cmd{ + Name: "callMessage", + Help: "use: \tcallMessage [contract name] [function name] [from account name] [deployed contract address] \n\t\t\t\tdescription: Connects to an RPC client to be used", + Func: func(c *ishell.Context) { + if len(c.Args) != 4 { + c.Println("Usage: \tcallMessage [contract name] [function name] [from account name] [deployed contract address] \n") + } else { + if ethClient == nil { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + + instance := contracts[c.Args[0]] + methodName := c.Args[1] + account := accounts[c.Args[2]] + contractDeployedAddress := common.HexToAddress(c.Args[3]) + + if instance == nil { + errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) + c.Println(errStr) + return + } + if account == nil { + errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore]\n", c.Args[2]) + c.Println(errStr) + return + } + + if instance.Abi.Methods[methodName].Name == "" { + c.Printf("Method name \"%s\" not found for contract \"%s\"\n", methodName, c.Args[0]) + return + } + + inputs, err := parseMethodParameters(c, instance.Abi, methodName) + if err != nil { + c.Printf("Error parsing parameters: %s\n", err) + return + } + + var out interface{} + + out, err = contract.CallContract( + ctx, + ethClient.client, + instance.Contract, + account.Key.Address, + contractDeployedAddress, + c.Args[1], + out, + inputs... + ) + if err != nil { + c.Println(err) + return + } else { + c.Printf("Result: %s\n", out) + } + } + c.Println("===============================================================") + }, + })*/ + + shell.AddCmd(&ishell.Cmd{ + Name: "getTransactionByHash", + Help: "use: \tgetTransactionByHash [optional rpc url] [hash]\n\t\t\t\tdescription: Returns transaction specified by hash", + Func: func(c *ishell.Context) { + var json []byte + var err error + + if len(c.Args) == 1 { + if ethClient != nil { + _, json, err = getTransactionByHash(ethClient, c.Args[0]) + } else { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + } else if len(c.Args) == 2 { + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + _, json, err = getTransactionByHash(client, c.Args[1]) + } else { + c.Println("Usage: \tgetTransactionByHash [optional rpc url] [hash]\n") + return + } + if err != nil { + c.Println(err) + return + } + c.Printf("Transaction: %s\n", json) + c.Println("===============================================================") + }, + }) + shell.AddCmd(&ishell.Cmd{ Name: "getBlockByNumber", - Help: "use: \tgetBlockByNumber [rpc url] [integer] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Help: "use: \tgetBlockByNumber [optional rpc url] [integer]\n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", Func: func(c *ishell.Context) { + var json []byte + var err error + if len(c.Args) == 1 { if ethClient != nil { - getBlockByNumber(ethClient, c.Args[0]) + _, json, err = getBlockByNumber(ethClient, c.Args[0]) } else { c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") return } } else if len(c.Args) == 2 { - getBlockByNumber(getClient(c.Args[0]), c.Args[1]) + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + _, json, err = getBlockByNumber(client, c.Args[1]) } else { - c.Println("Usage: \tgetBlock [rpc url] [integer] \n") + c.Println("Usage: \tgetBlockByNumber [optional rpc url] [integer]\n") + return } + if err != nil { + c.Println(err) + return + } + c.Printf("Block: %s\n", json) c.Println("===============================================================") }, }) shell.AddCmd(&ishell.Cmd{ Name: "getBlockByHash", - Help: "use: \tgetBlockByNumber [rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Help: "use: \tgetBlockByNumber [optional rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", Func: func(c *ishell.Context) { + var json []byte + var err error + if len(c.Args) == 1 { if ethClient != nil { - getBlockByHash(ethClient, c.Args[0]) + _, json, err = getBlockByHash(ethClient, c.Args[0]) } else { c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") return } } else if len(c.Args) == 2 { - getBlockByHash(getClient(c.Args[0]), c.Args[1]) + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + _, json, err = getBlockByHash(client, c.Args[1]) } else { - c.Println("Usage: \tgetBlock [optional rpc url] [hash] \n") + c.Println("Usage: \tgetBlockByNumber [optional rpc url] [hash] \n") + return + } + if err != nil { + c.Println(err) + return } + c.Printf("Block: %s\n", json) c.Println("===============================================================") }, }) @@ -302,17 +449,144 @@ func Launch( return } } else if len(c.Args) == 2 { - getProof(getClient(c.Args[0]), c.Args[1]) + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + getProof(client, c.Args[1]) } else { - c.Println("Usage: \tgetBlock [optional rpc url] [hash] \n") + c.Println("Usage: \tgetProof [optional rpc url] [Transaction hash] \n") + return } c.Println("===============================================================") }, }) //--------------------------------------------------------------------------------------------- - // Validation Specific Commands + // Clique Specific Commands //--------------------------------------------------------------------------------------------- + + shell.AddCmd(&ishell.Cmd{ + Name: "getBlockByNumber_Clique", + Help: "use: \tgetBlockByNumber_Clique [optional rpc url] [integer]\n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Func: func(c *ishell.Context) { + if len(c.Args) == 1 { + if ethClient != nil { + block, _, err := getBlockByNumber(ethClient, c.Args[0]) + if err != nil { + c.Println(err) + return + } + signedBlock, unsignedBlock := RlpEncode(block) + c.Printf("Signed Block: %+x\n", signedBlock) + c.Printf("Unsigned Block: %+x\n", unsignedBlock) + } else { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + } else if len(c.Args) == 2 { + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + block, _, err := getBlockByNumber(client, c.Args[1]) + if err != nil { + c.Println(err) + return + } + signedBlock, unsignedBlock := RlpEncode(block) + c.Printf("Signed Block:\n %+x\n", signedBlock) + c.Printf("Unsigned Block:\n %+x\n", unsignedBlock) + } else { + c.Println("Usage: \tgetBlockByNumber_Clique [optional rpc url] [integer]\n") + return + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "getBlockByHash_Clique", + Help: "use: \tgetBlockByHash_Clique [optional rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Func: func(c *ishell.Context) { + if len(c.Args) == 1 { + if ethClient != nil { + block, _, err := getBlockByHash(ethClient, c.Args[0]) + if err != nil { + c.Println(err) + return + } + signedBlock, unsignedBlock := RlpEncode(block) + c.Printf("Signed Block: 0x%+x\n", signedBlock) + c.Printf("Unsigned Block: 0x%+x\n", unsignedBlock) + } else { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + } else if len(c.Args) == 2 { + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + block, _, err := getBlockByHash(client, c.Args[1]) + if err != nil { + c.Println(err) + return + } + signedBlock, unsignedBlock := RlpEncode(block) + c.Printf("Signed Block:\n %+x\n", signedBlock) + c.Printf("Unsigned Block:\n %+x\n", unsignedBlock) + } else { + c.Println("Usage: \tgetBlockByHash_Clique [optional rpc url] [hash]\n") + return + } + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "getBlockByHash_Clique", + Help: "use: \tgetBlockByHash_Clique [optional rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Func: func(c *ishell.Context) { + if len(c.Args) == 1 { + if ethClient != nil { + block, _, err := getBlockByHash(ethClient, c.Args[0]) + if err != nil { + c.Println(err) + return + } + signedBlock, unsignedBlock := RlpEncode(block) + c.Printf("Signed Block: 0x%+x\n", signedBlock) + c.Printf("Unsigned Block: 0x%+x\n", unsignedBlock) + } else { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + } else if len(c.Args) == 2 { + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + block, _, err := getBlockByHash(client, c.Args[1]) + if err != nil { + c.Println(err) + return + } + signedBlock, unsignedBlock := RlpEncode(block) + c.Printf("Signed Block:\n %+x\n", signedBlock) + c.Printf("Unsigned Block:\n %+x\n", unsignedBlock) + } else { + c.Println("Usage: \tgetBlockByHash_Clique [optional rpc url] [hash]\n") + return + } + c.Println("===============================================================") + }, + }) + /* shell.AddCmd(&ishell.Cmd{ Name: "registerChainValidation", @@ -544,15 +818,25 @@ func Launch( shell.Run() } -func getClient(url string) (client *EthClient) { +func getClient(url string) (*EthClient, error) { rpc := utils.ClientRPC(url) eth := ethclient.NewClient(rpc) - return &EthClient{client: eth, rpcClient: rpc, url: url} + client := EthClient{client: eth, rpcClient: rpc, url: url} + + _, _, err := getBlockByNumber(&client, "0") + + return &client, err } func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName string) (args []interface{}, err error) { - inputParameters := abiStruct.Methods[methodName].Inputs + var inputParameters abi.Arguments + if methodName != "" { + inputParameters = abiStruct.Methods[methodName].Inputs + } else { + inputParameters = abiStruct.Constructor.Inputs + } + c.ShowPrompt(false) defer c.ShowPrompt(true) diff --git a/ion-cli/cli/rpc.go b/ion-cli/cli/rpc.go index 8e5b949..1cf14c9 100644 --- a/ion-cli/cli/rpc.go +++ b/ion-cli/cli/rpc.go @@ -53,42 +53,51 @@ func latestBlock(eth *EthClient) (lastBlock *types.Header) { return } -func getBlockByNumber(eth *EthClient, block string) { +func getBlockByNumber(eth *EthClient, number string) (*types.Header, []byte, error) { // var blockHeader header blockNum := new(big.Int) - blockNum.SetString(block, 10) + blockNum.SetString(number, 10) - lastBlock, err := eth.client.HeaderByNumber(context.Background(), blockNum) + block, err := eth.client.HeaderByNumber(context.Background(), blockNum) if err != nil { - fmt.Println("can't get requested block:", err) - return + return nil, nil, err } // Marshal into a JSON - b, err := json.MarshalIndent(lastBlock, "", " ") + b, err := json.MarshalIndent(block, "", " ") if err != nil { - fmt.Printf("Error: %s", err) - return + return nil, nil, err } - fmt.Println("Block:", block) - fmt.Println(string(b)) + return block, b, nil } -func getBlockByHash(eth *EthClient, block string) { - blockHash := common.HexToHash(block) +func getBlockByHash(eth *EthClient, hash string) (*types.Header, []byte, error) { + blockHash := common.HexToHash(hash) - lastBlock, err := eth.client.HeaderByHash(context.Background(), blockHash) + block, err := eth.client.HeaderByHash(context.Background(), blockHash) if err != nil { - fmt.Println("can't get requested block:", err) - return + return nil, nil, err } // Marshal into a JSON - b, err := json.MarshalIndent(lastBlock, "", " ") + b, err := json.MarshalIndent(block, "", " ") if err != nil { - fmt.Printf("Error: %s", err) - return + return nil, nil, err } - fmt.Println("Block:", block) - fmt.Println(string(b)) + return block, b, nil +} + +func getTransactionByHash(eth *EthClient, hash string) (*types.Transaction, []byte, error) { + txHash := common.HexToHash(hash) + + tx, _, err := eth.client.TransactionByHash(context.Background(), txHash) + if err != nil { + return nil, nil, err + } + // Marshal into a JSON + t, err := json.MarshalIndent(tx, "", " ") + if err != nil { + return nil, nil, err + } + return tx, t, nil } func getProof(eth *EthClient, transactionHash string) { @@ -109,29 +118,17 @@ func getProof(eth *EthClient, transactionHash string) { "ReceiptNodes: 0x%x\n", txPath, txValue, txNodes, receiptValue, receiptNodes) } -func calculateRlpEncoding(client *ethclient.Client, block string) (rlpSignedBlock []byte, rlpUnsignedBlock []byte) { - // var blockHeader header - blockNum := new(big.Int) - blockNum.SetString(block, 10) - - lastBlock, err := client.HeaderByNumber(context.Background(), blockNum) - if err != nil { - fmt.Println("can't get requested block:", err) - return - } - +func RlpEncode(blockHeader *types.Header) (rlpSignedBlock []byte, rlpUnsignedBlock []byte) { // Encode the orginal block header - _, err = rlp.EncodeToBytes(&lastBlock) + _, err := rlp.EncodeToBytes(&blockHeader) if err != nil { fmt.Println("can't RLP encode requested block:", err) return } // Generate an interface to encode the blockheader without the signature in the extraData - rlpSignedBlock = encodeSignedBlock(lastBlock) - fmt.Printf("\nSigned Block Header Prefix:\n%+x\n", rlpSignedBlock) - rlpUnsignedBlock = encodeUnsignedBlock(lastBlock) - fmt.Printf("\nUnsigned Block Header Prefix:\n%+x\n", rlpUnsignedBlock) + rlpSignedBlock = encodeSignedBlock(blockHeader) + rlpUnsignedBlock = encodeUnsignedBlock(blockHeader) return rlpSignedBlock, rlpUnsignedBlock diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index 0adf166..bc1e310 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -16,7 +16,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/compiler" + "github.com/clearmatics/autonity/common/compiler" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" ) @@ -102,7 +102,7 @@ func CompileAndDeployContract( amount *big.Int, gasLimit uint64, constructorArgs ...interface{}, -) *types.Transaction { +) (*types.Transaction, error){ payload := generateContractPayload(binStr, abiStr, constructorArgs...) userAddr := crypto.PubkeyToAddress(userKey.PublicKey) tx := newTx(ctx, backend, &userAddr, nil, amount, gasLimit, payload) @@ -110,9 +110,9 @@ func CompileAndDeployContract( err := backend.SendTransaction(ctx, signedTx) if err != nil { - log.Fatal("ERROR sending contract deployment transaction") + return nil, err } - return signedTx + return signedTx, nil } // CallContract without changing the state @@ -124,30 +124,32 @@ func CallContract( methodName string, out interface{}, args ...interface{}, -) { +) (res interface{}, err error) { abiStr, err := json.Marshal(contract.Info.AbiDefinition) if err != nil { - log.Fatal("ERROR marshalling abi to string", err) + return nil, err } abiContract, err := abi.JSON(strings.NewReader(string(abiStr))) if err != nil { - log.Fatal("ERROR reading contract ABI ", err) + return nil, err } input, err := abiContract.Pack(methodName, args...) if err != nil { - log.Fatal("ERROR packing the method name for the contract call: ", err) + return nil, err } msg := ethereum.CallMsg{From: from, To: &to, Data: input} output, err := client.CallContract(ctx, msg, nil) if err != nil { - log.Fatal("ERROR calling the Ion Contract", err) + return nil, err } err = abiContract.Unpack(out, methodName, output) if err != nil { - log.Fatal("ERROR upacking the call: ", err) + return nil, err } + + return out, nil } // TransactionContract execute function in contract @@ -222,14 +224,18 @@ func CompileContract(contract string) (compiledContract *compiler.Contract, err } func CompileContractAt(contractPath string) (compiledContract *compiler.Contract, err error) { - contract, err := compiler.CompileSolidity("", contractPath) + path := strings.Split(contractPath, "/") + contractName := path[len(path)-1] + contractFolder := path[len(path)-2] + + i := strings.Index(contractPath, contractFolder) + remapping := fmt.Sprintf("../=%s", contractPath[:i]) + + contract, err := compiler.CompileSolidity("", remapping, contractPath) if err != nil { return nil, err } - path := strings.Split(contractPath, "/") - contractName := path[len(path)-1] - compiledContract = contract[contractPath+":"+strings.Replace(contractName, ".sol", "", -1)] return compiledContract, nil diff --git a/ion-cli/contracts/function.go b/ion-cli/contracts/function.go deleted file mode 100644 index 23e4252..0000000 --- a/ion-cli/contracts/function.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd -package contract - -import ( - "context" - "crypto/ecdsa" - "log" - "math/big" - "os" - "strings" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/compiler" - "github.com/ethereum/go-ethereum/core/types" -) - -func CompileAndDeployTriggerVerifierAndConsumerFunction( - ctx context.Context, - client bind.ContractBackend, - userKey *ecdsa.PrivateKey, - ionContractAddress common.Address, -) <-chan ContractInstance { - // --------------------------------------------- - // COMPILE VALIDATION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - triggerEventVerifierContractPath := basePath + "TriggerEventVerifier.sol" - consumerFunctionContractPath := basePath + "Function.sol" - - contracts, err := compiler.CompileSolidity("", consumerFunctionContractPath, triggerEventVerifierContractPath) - if err != nil { - log.Fatal("ERROR failed to compile TriggerEventVerifier.sol:", err) - } - - triggerEventVerifierContract := contracts[triggerEventVerifierContractPath+":TriggerEventVerifier"] - triggerEventVerifierBinStr, triggerEventVerifierABIStr := GetContractBytecodeAndABI(triggerEventVerifierContract) - consumerFunctionContract := contracts[consumerFunctionContractPath+":Function"] - consumerFunctionBinStr, consumerFunctionABIStr := GetContractBytecodeAndABI(consumerFunctionContract) - - // --------------------------------------------- - // DEPLOY TRIGGER EVENT CONTRACT - // --------------------------------------------- - triggerEventSignedTx := CompileAndDeployContract( - ctx, - client, - userKey, - triggerEventVerifierBinStr, - triggerEventVerifierABIStr, - nil, - uint64(3000000), - ) - - resChan := make(chan ContractInstance) - - // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed - // Ion depends on PatriciaTrie library - go func() { - defer close(resChan) - deployBackend := client.(bind.DeployBackend) - - // wait for trigger event contract to be deployed - triggerEventAddr, err := bind.WaitDeployed(ctx, deployBackend, triggerEventSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // DEPLOY CONSUMER FUNCTION CONTRACT - // --------------------------------------------- - consumerFunctionSignedTx := CompileAndDeployContract( - ctx, - client, - userKey, - consumerFunctionBinStr, - consumerFunctionABIStr, - nil, - uint64(3000000), - ionContractAddress, - triggerEventAddr, - ) - - triggerAbi, err := abi.JSON(strings.NewReader(triggerEventVerifierABIStr)) - if err != nil { - log.Fatal("ERROR failed to compile TriggerEventVerifier.sol:", err) - } - resChan <- ContractInstance{triggerEventVerifierContract, &triggerAbi} - - // wait for consumer function contract to be deployed - _, err = bind.WaitDeployed(ctx, deployBackend, consumerFunctionSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - functionAbi, err := abi.JSON(strings.NewReader(consumerFunctionABIStr)) - if err != nil { - log.Fatal("ERROR failed to compile Function.sol:", err) - } - resChan <- ContractInstance{consumerFunctionContract, &functionAbi} - }() - - return resChan -} - -func VerifyExecute( - ctx context.Context, - backend bind.ContractBackend, - userKey *ecdsa.PrivateKey, - contract *compiler.Contract, - toAddr common.Address, - chainId common.Hash, - blockHash common.Hash, - txTriggerTo common.Address, - txTriggerPath []byte, - txTriggerRLP []byte, - txTriggerProofArr []byte, - receiptTrigger []byte, - receiptTriggerProofArr []byte, - triggerCalledBy common.Address, - amount *big.Int, - -) (tx *types.Transaction) { - tx, err := TransactionContract( - ctx, - backend, - userKey, - contract, - toAddr, - amount, - uint64(3000000), - "verifyAndExecute", - chainId, - blockHash, - txTriggerTo, // TRIG_DEPLOYED_RINKEBY_ADDR, - txTriggerPath, // TEST_PATH, - txTriggerRLP, // TEST_TX_VALUE, - txTriggerProofArr, // TEST_TX_NODES, - receiptTrigger, // TEST_RECEIPT_VALUE, - receiptTriggerProofArr, // TEST_RECEIPT_NODES, - triggerCalledBy, // TRIG_CALLED_BY, - ) - if err != nil { - fmt.Println(err) - } - return -} diff --git a/ion-cli/contracts/ion.go b/ion-cli/contracts/ion.go deleted file mode 100644 index c68dc70..0000000 --- a/ion-cli/contracts/ion.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd -package contract - -import ( - "context" - "crypto/ecdsa" - "log" - "os" - "regexp" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common/compiler" -) - -// CompileAndDeployIon specific compile and deploy ion contract -func CompileAndDeployIon( - ctx context.Context, - client bind.ContractBackend, - userKey *ecdsa.PrivateKey, - chainID interface{}, -) <-chan ContractInstance { - // --------------------------------------------- - // COMPILE ION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - ionContractPath := basePath + "Ion.sol" - - contracts, err := compiler.CompileSolidity("", ionContractPath) - if err != nil { - log.Fatal("ERROR failed to compile Ion.sol:", err) - } - - patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] - patriciaTrieBinStr, patriciaTrieABIStr := GetContractBytecodeAndABI(patriciaTrieContract) - - ionContract := contracts[basePath+"Ion.sol:Ion"] - ionBinStr, ionABIStr := GetContractBytecodeAndABI(ionContract) - - // --------------------------------------------- - // DEPLOY PATRICIA LIB ADDRESS - // --------------------------------------------- - patriciaTrieSignedTx := CompileAndDeployContract( - ctx, - client, - userKey, - patriciaTrieBinStr, - patriciaTrieABIStr, - nil, - uint64(3000000), - ) - - resChan := make(chan ContractInstance) - - // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed - // Ion depends on PatriciaTrie library - go func() { - defer close(resChan) - deployBackend := client.(bind.DeployBackend) - - // wait for PatriciaTrie library to be deployed - patriciaTrieAddr, err := bind.WaitDeployed(ctx, deployBackend, patriciaTrieSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // DEPLOY ION CONTRACT WITH PATRICIA LIB ADDRESS - // --------------------------------------------- - // replace palceholder with Prticia Trie Lib address - var re = regexp.MustCompile(`__.*__`) - ionBinStrWithLibAddr := re.ReplaceAllString(ionBinStr, patriciaTrieAddr.Hex()[2:]) - ionSignedTx := CompileAndDeployContract( - ctx, - client, - userKey, - ionBinStrWithLibAddr, - ionABIStr, - nil, - uint64(3000000), - chainID, - ) - - patriciaAbi, err := abi.JSON(strings.NewReader(patriciaTrieABIStr)) - if err != nil { - log.Fatal("ERROR failed to compile PatriciaTrie.sol:", err) - } - // only stop blocking the first result after the Ion contract as been deploy - // this guarantees that it works well with the blockchain simulator Commit() - resChan <- ContractInstance{patriciaTrieContract, &patriciaAbi} - - // wait for Ion to be deployed - _, err = bind.WaitDeployed(ctx, deployBackend, ionSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - - ionAbi, err := abi.JSON(strings.NewReader(ionABIStr)) - if err != nil { - log.Fatal("ERROR failed to compile Ion.sol:", err) - } - resChan <- ContractInstance{ionContract, &ionAbi} - }() - - return resChan -} diff --git a/ion-cli/contracts/trigger.go b/ion-cli/contracts/trigger.go deleted file mode 100644 index 46e845a..0000000 --- a/ion-cli/contracts/trigger.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd -package contract - -import ( - "context" - "crypto/ecdsa" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/compiler" - "github.com/ethereum/go-ethereum/core/types" -) - -// Registers chain with Validation contract specified -func Fire( - ctx context.Context, - backend bind.ContractBackend, - userKey *ecdsa.PrivateKey, - contract *compiler.Contract, - toAddr common.Address, -) (tx *types.Transaction) { - tx, err := TransactionContract( - ctx, - backend, - userKey, - contract, - toAddr, - nil, - uint64(3000000), - "fire", - ) - - if err != nil { - fmt.Println(err) - } - - return -} diff --git a/ion-cli/contracts/validation.go b/ion-cli/contracts/validation.go deleted file mode 100644 index f092845..0000000 --- a/ion-cli/contracts/validation.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd -package contract - -import ( - "context" - "crypto/ecdsa" - "log" - "os" - "strings" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/compiler" - "github.com/ethereum/go-ethereum/core/types" -) - -// CompileAndDeployValidation method -func CompileAndDeployValidation( - ctx context.Context, - client bind.ContractBackend, - userKey *ecdsa.PrivateKey, - chainID interface{}, - ionContractAddress common.Address, -) <-chan ContractInstance { - // --------------------------------------------- - // COMPILE VALIDATION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - validationContractPath := basePath + "Validation.sol" - - contracts, err := compiler.CompileSolidity("", validationContractPath) - if err != nil { - log.Fatal("ERROR failed to compile Validation.sol:", err) - } - - validationContract := contracts[basePath+"Validation.sol:Validation"] - validationBinStr, validationABIStr := GetContractBytecodeAndABI(validationContract) - - // --------------------------------------------- - // DEPLOY VALIDATION CONTRACT - // --------------------------------------------- - validationSignedTx := CompileAndDeployContract( - ctx, - client, - userKey, - validationBinStr, - validationABIStr, - nil, - uint64(3000000), - chainID, - ionContractAddress, - ) - - resChan := make(chan ContractInstance) - - // Go-Routine that waits for PatriciaTrie Library and Ion Contract to be deployed - // Ion depends on PatriciaTrie library - go func() { - defer close(resChan) - deployBackend := client.(bind.DeployBackend) - - // wait for PatriciaTrie library to be deployed - _, err := bind.WaitDeployed(ctx, deployBackend, validationSignedTx) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - abistruct, err := abi.JSON(strings.NewReader(validationABIStr)) - if err != nil { - log.Fatal("ERROR failed to compile Validation.sol:", err) - } - resChan <- ContractInstance{validationContract, &abistruct} - }() - - return resChan -} - -// RegisterChain with Validation contract specified -func RegisterChain( - ctx context.Context, - backend bind.ContractBackend, - userKey *ecdsa.PrivateKey, - contract *compiler.Contract, - toAddr common.Address, - chainID common.Hash, - validators []common.Address, - registerHash common.Hash, -) (tx *types.Transaction) { - tx, err := TransactionContract( - ctx, - backend, - userKey, - contract, - toAddr, - nil, - uint64(3000000), - "RegisterChain", - chainID, - validators, - registerHash, - ) - - if err != nil { - fmt.Println(err) - } - - return -} - -// SubmitBlock Submits block to Validation contract specified -func SubmitBlock( - ctx context.Context, - backend bind.ContractBackend, - userKey *ecdsa.PrivateKey, - contract *compiler.Contract, - toAddr common.Address, - chainID common.Hash, - unsignedBlockHeaderRLP []byte, - signedBlockHeaderRLP []byte, -) (tx *types.Transaction) { - tx, err := TransactionContract( - ctx, - backend, - userKey, - contract, - toAddr, - nil, - uint64(3000000), - "SubmitBlock", - chainID, - unsignedBlockHeaderRLP, - signedBlockHeaderRLP, - ) - - if err != nil { - fmt.Println(err) - } - - return -} - -// ValidBlock Queries validation contract to see is block is valid -func ValidBlock( - ctx context.Context, - backend bind.ContractBackend, - contract *compiler.Contract, - userAddr common.Address, - toAddr common.Address, - chainID common.Hash, - blockHash common.Hash, -) (isBlockValid bool) { - methodName := "m_blockhashes" - CallContract( - ctx, - backend, - contract, - userAddr, - toAddr, - methodName, - &isBlockValid, - chainID, - blockHash, - ) - return -} - -// LatestValidBlock Queries validation contract to see is block is valid -func LatestValidBlock( - ctx context.Context, - backend bind.ContractBackend, - contract *compiler.Contract, - userAddr common.Address, - toAddr common.Address, - chainID common.Hash, -) (latestBlock common.Hash) { - methodName := "m_latestblock" - CallContract( - ctx, - backend, - contract, - userAddr, - toAddr, - methodName, - &latestBlock, - chainID, - ) - return -} diff --git a/package-lock.json b/package-lock.json index e898222..09dce8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -162,6 +162,20 @@ "normalize-path": "2.1.1" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1229,6 +1243,11 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, + "bignumber.js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" + }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", @@ -1618,6 +1637,11 @@ "readdirp": "2.1.0" } }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -1826,6 +1850,11 @@ "typedarray": "0.0.6" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -2175,6 +2204,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2207,6 +2241,11 @@ "repeating": "2.0.1" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -2334,6 +2373,46 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "requires": { + "abstract-leveldown": "5.0.0", + "inherits": "2.0.3", + "level-codec": "9.0.0", + "level-errors": "2.0.0", + "xtend": "4.0.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "4.0.1" + } + }, + "level-codec": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz", + "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==" + }, + "level-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", + "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", + "requires": { + "errno": "0.1.7" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -2616,6 +2695,73 @@ "xhr-request-promise": "0.1.2" } }, + "eth-proof": { + "version": "git+https://github.com/Shirikatsu/eth-proof.git#9b7fdea64ec5810c9c8a74c67ab96dbf0f035567", + "requires": { + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.7", + "keccak": "1.4.0", + "leveldown": "1.9.0", + "levelup": "1.3.9", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "rlp": "2.1.0", + "web3": "0.19.1" + }, + "dependencies": { + "ethereumjs-block": { + "version": "1.7.1", + "resolved": "http://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "requires": { + "async": "2.6.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "1.3.7", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master" + } + }, + "level-ws": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", + "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "merkle-patricia-tree": { + "version": "https://github.com/ethereumjs/merkle-patricia-tree/tarball/master", + "integrity": "sha512-lTMwnjErlvg4pOgKUo7PJdIPsKgTzUA580xpxi6eoJEW7bIjDl2eK2/wN1ld09F1RHOCpMxPoWYSYpoprMZ6Qg==", + "requires": { + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-mem": "3.0.1", + "level-ws": "1.0.0", + "readable-stream": "2.3.6", + "rlp": "2.1.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, "ethereumjs-block": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.0.0.tgz", @@ -2795,6 +2941,11 @@ "fill-range": "2.2.4" } }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -2965,6 +3116,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, + "fast-future": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", + "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" + }, "fast-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", @@ -3441,7 +3597,7 @@ }, "fs-extra": { "version": "0.30.0", - "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "requires": { "graceful-fs": "4.1.11", @@ -4038,6 +4194,21 @@ "source-map-support": "0.5.6" } }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -4125,6 +4296,11 @@ } } }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, "github-username": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", @@ -4366,6 +4542,11 @@ "has-symbol-support-x": "1.4.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -5279,6 +5460,105 @@ } } }, + "level-mem": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", + "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", + "requires": { + "level-packager": "4.0.1", + "memdown": "3.0.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "4.0.1" + } + }, + "memdown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", + "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", + "requires": { + "abstract-leveldown": "5.0.0", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.2" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "level-packager": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", + "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", + "requires": { + "encoding-down": "5.0.4", + "levelup": "3.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "4.0.1" + } + }, + "deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "requires": { + "abstract-leveldown": "5.0.0", + "inherits": "2.0.3" + } + }, + "level-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", + "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", + "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "levelup": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", + "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "requires": { + "deferred-leveldown": "4.0.2", + "level-errors": "2.0.0", + "level-iterator-stream": "3.0.1", + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, "level-ws": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", @@ -5301,6 +5581,38 @@ } } }, + "leveldown": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-1.9.0.tgz", + "integrity": "sha512-3MwcrnCUIuFiKp/jSrG1UqDTV4k1yH8f5HH6T9dpqCKG+lRxcfo2KwAqbzTT+TTKfCbaATeHMy9mm1y6sI3ZvA==", + "requires": { + "abstract-leveldown": "2.7.2", + "bindings": "1.3.0", + "fast-future": "1.0.2", + "nan": "2.7.0", + "prebuild-install": "2.5.3" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, "levelup": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", @@ -6114,6 +6426,14 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" }, + "node-abi": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.5.0.tgz", + "integrity": "sha512-9g2twBGSP6wIR5PW7tXvAWnEWKJDH/VskdXp168xsw9VVxpEGov8K4jsP4/VeoC7b2ZAyzckvMCuQuQlw44lXg==", + "requires": { + "semver": "5.4.1" + } + }, "node-dir": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", @@ -6150,6 +6470,11 @@ } } }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -6195,6 +6520,17 @@ "path-key": "2.0.1" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -6675,6 +7011,28 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.5.0", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -6751,6 +7109,15 @@ "randombytes": "2.0.6" } }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -6831,6 +7198,17 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, "read-chunk": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", @@ -8059,6 +8437,28 @@ "inherits": "2.0.3" } }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "1.1.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.6.1" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, "tar-stream": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", @@ -8807,6 +9207,18 @@ "vinyl": "1.2.0" } }, + "web3": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.19.1.tgz", + "integrity": "sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE=", + "requires": { + "bignumber.js": "4.1.0", + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" + } + }, "web3-bzz": { "version": "1.0.0-beta.36", "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.0.0-beta.36.tgz", @@ -10416,6 +10828,19 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "1.0.2" + } + }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", diff --git a/test/integration-clique_ethereum.js b/test/integration-clique_ethereum.js index c685d05..4fd2560 100644 --- a/test/integration-clique_ethereum.js +++ b/test/integration-clique_ethereum.js @@ -679,6 +679,30 @@ contract('Clique-Ethereum Integration', (accounts) => { await functionContract.verifyAndExecute(TESTCHAINID, TESTBLOCK.hash, TRIG_DEPLOYED_RINKEBY_ADDR, TEST_PATH, TEST_TX_VALUE, TEST_TX_NODES, TEST_RECEIPT_VALUE, TEST_RECEIPT_NODES, TRIG_DEPLOYED_RINKEBY_ADDR).should.be.rejected; }) }) + + +// The below succeeds but manual registering with the same values fail +// const testid = "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; +// const testval = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"]; +// const testgen = "0x3f09591cb976beecd52d7dbe5fb869bbfc76b9022883c0cfbd5813a6eeec973e"; +// const teststore = "0xec7601E406A998898DE9A784a634f68E038E19D2" +// +// it('Rinkeby Register Chain', async () => { +// // Successfully add id of another chain +// +// await clique.register(); +// let tx = await clique.RegisterChain(testid, testval, testgen, storage.address); +// console.log("\tGas used to register chain = " + tx.receipt.gasUsed.toString() + " gas"); +// let chainExists = await clique.chains(testid); +// +// assert(chainExists); +// +// // Fail adding id of this chain +// await clique.RegisterChain(DEPLOYEDCHAINID, testval, testgen, teststore).should.be.rejected; +// +// // Fail adding id of chain already initialised +// await clique.RegisterChain(testid, testval, testgen, teststore).should.be.rejected; +// }) }) async function verifyReceipts(eP, txHash) { From b9c530be92a6da923ddd2569029758d1064448a7 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Mon, 26 Nov 2018 17:48:26 +0000 Subject: [PATCH 165/203] Simplified Function.sol --- contracts/functional/Function.sol | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/contracts/functional/Function.sol b/contracts/functional/Function.sol index 9054b8e..9eac1c6 100644 --- a/contracts/functional/Function.sol +++ b/contracts/functional/Function.sol @@ -31,9 +31,7 @@ contract Function { TriggerEventVerifier verifier; /* Custom event that fires when execution is performed successfully. */ - event Executed(address caller); - event Another(address caller); - event Verify(bool result); + event Executed(); /* Constructor. Requires Ion contract address and all used event verifier contract addresses. In this case we only use one verifier. */ @@ -44,7 +42,7 @@ contract Function { /* This is the function that is intended to be executed upon successful verification of proofs */ function execute() internal { - emit Executed(msg.sender); + emit Executed(); } /* @@ -85,19 +83,13 @@ contract Function { bytes _receipt, bytes _receiptNodes, bytes20 _expectedAddress - ) public returns (bool) { + ) public { assert( blockStore.CheckRootsProof(_chainId, _blockHash, _txNodes, _receiptNodes) ); assert( blockStore.CheckTxProof(_chainId, _blockHash, _tx, _txNodes, _path) ); assert( blockStore.CheckReceiptProof(_chainId, _blockHash, _receipt, _receiptNodes, _path) ); - if (verifier.verify(_contractEmittedAddress, _receipt, _expectedAddress)) { - execute(); - return true; - } else { - emit Verify(false); - } - emit Another(msg.sender); - return false; + require( verifier.verify(_contractEmittedAddress, _receipt, _expectedAddress), "Event verification failed." ); + execute(); } } From a9de2ea3dc9492fd8d1b745edbd6a986f830cf34 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 28 Nov 2018 12:56:28 +0000 Subject: [PATCH 166/203] Found exec method to solc compile with libraries linked --- ion-cli/cli/cli.go | 144 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 6 deletions(-) diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 9fc6bbf..785090a 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -10,9 +10,11 @@ import ( "errors" "strings" "reflect" + "os/exec" + "bytes" "github.com/ethereum/go-ethereum/common" - // "github.com/ethereum/go-ethereum/common/compiler" + //"github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/accounts/abi" @@ -168,15 +170,34 @@ func Launch( return } - tx, err := contract.CompileAndDeployContract( + /*gasLimit = gasLimit + constructorInputs = constructorInputs + + c.Printf("Contract Info: %s\n\n", contractInstance.Contract.Info) + contractInfo := make(map[string]*compiler.ContractInfo) + str, err := json.Marshal(contractInstance.Contract.Info) + if err != nil { + c.Println(err) + return + } + err = json.Unmarshal([]byte(str), &contractInfo) + + if err != nil { + c.Println(err) + return + } + c.Printf("Unmarshalled: %+v\n\n", contractInfo)*/ + + + payload := contract.CompilePayload(binStr, abiStr, constructorInputs...) + + tx, err := contract.DeployContract( ctx, ethClient.client, account.Key.PrivateKey, - binStr, - abiStr, + payload, nil, gasLimit, - constructorInputs... ) if err != nil { c.Println(err) @@ -195,6 +216,99 @@ func Launch( }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "linkAndDeployContract", + Help: "use: \tdeployContract [contract name] [account name] [gas limit]\n\t\t\t\tdescription: Deploys specified contract instance to connected client", + Func: func(c *ishell.Context) { + if len(c.Args) != 3 { + c.Println("Usage: \tdeployContract [contract name] [account name] [gas limit] \n") + } else { + if ethClient == nil { + c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") + return + } + contractInstance := contracts[c.Args[0]] + if contractInstance == nil { + errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) + c.Println(errStr) + return + } + + c.ShowPrompt(false) + defer c.ShowPrompt(true) + c.Println("Please provide comma separated list of libraries to link in the form : e.g. RLP:0x123456789") + input := c.ReadLine() + libraries := strings.Split(input, ",") + library := make(map[string]common.Address) + + for _, lib := range libraries { + name := strings.Split(lib, ":")[0] + address := common.HexToAddress(strings.Split(lib, ":")[1]) + library[name] = address + } + + fmt.Printf("Library data: %s\n", library) + + compiledContract, err := contract.CompileContractWithLibraries(contractInstance.Path, library) + if err != nil { + c.Println(err) + return + } + + c.Printf("Compiled Contract: %s\n", compiledContract) + + /* + binStr, abiStr := contract.GetContractBytecodeAndABI(compiledContract) + + c.Printf("Binary string: %s\n", binStr) + + account := accounts[c.Args[1]] + if account == nil { + errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore] \n", c.Args[1]) + c.Println(errStr) + return + } + + gasLimit, err := strconv.ParseUint(c.Args[2], 10, 64) + if err != nil { + c.Println(err) + return + } + + constructorInputs, err := parseMethodParameters(c, contractInstance.Abi, "") + if err != nil { + c.Printf("Error parsing constructor parameters: %s\n", err) + return + } + + + payload := contract.CompilePayload(binStr, abiStr, constructorInputs...) + + tx, err := contract.DeployContract( + ctx, + ethClient.client, + account.Key.PrivateKey, + payload, + nil, + gasLimit, + ) + if err != nil { + c.Println(err) + return + } + + c.Println("Waiting for contract to be deployed") + addr, err := bind.WaitDeployed(ctx, ethClient.client, tx) + if err != nil { + c.Println(err) + return + } + c.Printf("Deployed contract at: %s\n", addr.String())*/ + } + c.Println("===============================================================") + }, + }) + shell.AddCmd(&ishell.Cmd{ Name: "transactionMessage", Help: "use: \ttransactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n\t\t\t\tdescription: Connects to an RPC client to be used", @@ -273,6 +387,24 @@ func Launch( }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "test", + Help: "use: \ttest \n\t\t\t\tdescription: Connects to an RPC client to be used", + Func: func(c *ishell.Context) { + var stderr, stdout bytes.Buffer + + args := []string{"--combined-json", "bin,abi,userdoc,devdoc,metadata", "--optimize", "--libraries=ReallyExtremelyVeryIncrediblyObnoxiouslySurprisinglyLongLibraryName:0xe9215b0d0A66CeBd1A50F468dFACF748cB065165", "--libraries=EvenMoreReallyExtremelyVeryIncrediblyObnoxiouslySurprisinglyLongLibraryName:0xe9215b0d0A66CeBd1A50F468dFACF748cB065165", "../=/home/cc/go/src/github.com/clearmatics/ion/contracts/", "/home/cc/go/src/github.com/clearmatics/ion/contracts/test/test.sol"} + //cmd := exec.Command("solc", "--combined-json", "bin,abi,userdoc,devdoc,metadata", "--optimize", "--libraries=PatriciaTrie:0xe9215b0d0A66CeBd1A50F468dFACF748cB065165", "../=/home/cc/go/src/github.com/clearmatics/ion/contracts/", "/home/cc/go/src/github.com/clearmatics/ion/contracts/storage/EthereumStore.sol") + cmd := exec.Command("solc", args...) + cmd.Stderr = &stderr + cmd.Stdout = &stdout + err := cmd.Run() + c.Println(err) + c.Printf("%s\n", stderr.Bytes()) + c.Printf("%s\n", stdout.Bytes()) + }, + }) + /*shell.AddCmd(&ishell.Cmd{ Name: "callMessage", Help: "use: \tcallMessage [contract name] [function name] [from account name] [deployed contract address] \n\t\t\t\tdescription: Connects to an RPC client to be used", @@ -1281,7 +1413,7 @@ func addContractInstance(pathToContract string, contractName string, contracts m if err != nil { return err } - contracts[contractName] = &contract.ContractInstance{Contract: compiledContract, Abi: &abistruct} + contracts[contractName] = &contract.ContractInstance{Contract: compiledContract, Abi: &abistruct, Path: pathToContract} return nil } From d6c5e5b5d9f9bae8db2609ac192ffe5517069fd3 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 28 Nov 2018 12:56:36 +0000 Subject: [PATCH 167/203] Found exec method to solc compile with libraries linked --- README.md | 39 ++++++++++++++++++++++- ion-cli/contracts/contract.go | 48 ++++++++++++++++++++++++----- test/integration-clique_ethereum.js | 2 ++ 3 files changed, 81 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 994968b..54370d9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,47 @@ # Ion Interoperability Framework +The Ion Interoperability Framework is a library that provides an interface for the development of general cross-chain smart contracts. + +## Getting Started + +Clone the repository + +## Interoperate with Rinkeby! + +We've already deployed some contracts to the Rinkeby test network for you to play around with! + +Trigger: 0xA2e4a61a3D2ce626Ba9B3e927cfFDB0e4E0bd06d + +Procedure: +./ion-cli +>>> addContractInstance ion /path/to/Ion.sol +>>> addContractInstance ethstore /path/to/EthereumStore.sol +>>> addContractInstance clique /path/to/Clique.sol +>>> addAccount name_of_your_account /path/to/keystore.json +>>> connectToClient https://your.endpoint:port +>>> deployContract ion name_of_your_account gaslimit +>>> deployContract ethstore name_of_your_account gaslimit +>>> deployContract clique name_of_your_account gaslimit + +## Develop on Ion + + +## CLI + + +## How it works + + +# Contribute! + + + + The Ion Interoperability Framework provides a interface to perform interoperability across multiple turing-complete blockchains. Using the generalised framework specific use cases, such as atomic swaps, can be developed. In order to perform cross-chain interop the Ion framework verifies specific transactions executed on one blockchain A on another blockchain B. Being able to verify these transactions cross-chain requires submission of valid block headers, to the blockchain where a transaction is to be proven, and then performing a number of Patricia trie proofs of the transaction, receipts and logs. Smart contracts can then be built to execute only if the proof is verified, this is known as continuous execution. To facilitate this Ion has three main components: - * Ion Hub Contract + * Block Storage Contracts * Modular Validation Scheme * Ion Framework Contracts diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index bc1e310..2551d4a 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -25,6 +25,7 @@ import ( type ContractInstance struct { Contract *compiler.Contract Abi *abi.ABI + Path string } // GENERIC UTIL FUNCTIONS @@ -93,17 +94,14 @@ func signTx(tx *types.Transaction, userKey *ecdsa.PrivateKey) *types.Transaction return signedTx } -func CompileAndDeployContract( +func DeployContract( ctx context.Context, backend bind.ContractBackend, userKey *ecdsa.PrivateKey, - binStr string, - abiStr string, + payload []byte, amount *big.Int, gasLimit uint64, - constructorArgs ...interface{}, ) (*types.Transaction, error){ - payload := generateContractPayload(binStr, abiStr, constructorArgs...) userAddr := crypto.PubkeyToAddress(userKey.PublicKey) tx := newTx(ctx, backend, &userAddr, nil, amount, gasLimit, payload) signedTx := signTx(tx, userKey) @@ -115,6 +113,14 @@ func CompileAndDeployContract( return signedTx, nil } +func CompilePayload( + binStr string, + abiStr string, + constructorArgs ...interface{}, +) ([]byte){ + return generateContractPayload(binStr, abiStr, constructorArgs...) +} + // CallContract without changing the state func CallContract( ctx context.Context, @@ -213,7 +219,7 @@ func CompileContract(contract string) (compiledContract *compiler.Contract, err basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" contractPath := basePath + contract + ".sol" - contracts, err := compiler.CompileSolidity("", contractPath) + contracts, err := compiler.CompileSolidity("", []string{}, contractPath) if err != nil { return nil, err } @@ -231,7 +237,35 @@ func CompileContractAt(contractPath string) (compiledContract *compiler.Contract i := strings.Index(contractPath, contractFolder) remapping := fmt.Sprintf("../=%s", contractPath[:i]) - contract, err := compiler.CompileSolidity("", remapping, contractPath) + contract, err := compiler.CompileSolidity("", []string{remapping}, contractPath) + if err != nil { + return nil, err + } + + compiledContract = contract[contractPath+":"+strings.Replace(contractName, ".sol", "", -1)] + + return compiledContract, nil +} + +func CompileContractWithLibraries(contractPath string, libraries map[string]common.Address) (compiledContract *compiler.Contract, err error) { + path := strings.Split(contractPath, "/") + contractName := path[len(path)-1] + contractFolder := path[len(path)-2] + + args := []string{} + + for name := range libraries { + address := libraries[name] + + libraryArg := name + ":" + address.String() + args = append(args, fmt.Sprintf("--libraries=\"%s\"", libraryArg)) + } + + i := strings.Index(contractPath, contractFolder) + args = append(args, fmt.Sprintf("../=%s ", contractPath[:i])) + fmt.Println(args) + + contract, err := compiler.CompileSolidity("", args, contractPath) if err != nil { return nil, err } diff --git a/test/integration-clique_ethereum.js b/test/integration-clique_ethereum.js index 4fd2560..eb54b45 100644 --- a/test/integration-clique_ethereum.js +++ b/test/integration-clique_ethereum.js @@ -682,6 +682,8 @@ contract('Clique-Ethereum Integration', (accounts) => { // The below succeeds but manual registering with the same values fail +// const DEPLOYEDCHAINID = "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075" +// // const testid = "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; // const testval = ["0x42eb768f2244c8811c63729a21a3569731535f06", "0x6635f83421bf059cd8111f180f0727128685bae4", "0x7ffc57839b00206d1ad20c69a1981b489f772031", "0xb279182d99e65703f0076e4812653aab85fca0f0", "0xd6ae8250b8348c94847280928c79fb3b63ca453e", "0xda35dee8eddeaa556e4c26268463e26fb91ff74f", "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"]; // const testgen = "0x3f09591cb976beecd52d7dbe5fb869bbfc76b9022883c0cfbd5813a6eeec973e"; From 954ff7117ae50490565d3f21032248d14ec2257a Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 28 Nov 2018 15:43:58 +0000 Subject: [PATCH 168/203] PatriciaTrie library now can be imported without requiring prior deployment. Fixed CLI to be able to link libraries and deploy. --- contracts/functional/Trigger.sol | 16 ---------------- contracts/libraries/PatriciaTrie.sol | 2 +- ion-cli/cli/cli.go | 13 ++++--------- ion-cli/contracts/contract.go | 3 +-- migrations/2_deploy_contracts.js | 6 +----- 5 files changed, 7 insertions(+), 33 deletions(-) diff --git a/contracts/functional/Trigger.sol b/contracts/functional/Trigger.sol index 44f2a28..3536d72 100644 --- a/contracts/functional/Trigger.sol +++ b/contracts/functional/Trigger.sol @@ -24,20 +24,4 @@ contract Trigger { function fire() public { emit Triggered(msg.sender); } - - event Boolean(bool b); - event Int256(int256 i); - event Int8(int8 i); - event Address(address a); - event Bytes(bytes b); - event Addresses(address[] a); - - function testTypes(bool b, int256 i256, int8 i8, address a, bytes by, address[] addresses) { - emit Boolean(b); - emit Int256(i256); - emit Int8(i8); - emit Address(a); - emit Bytes(by); - emit Addresses(addresses); - } } diff --git a/contracts/libraries/PatriciaTrie.sol b/contracts/libraries/PatriciaTrie.sol index 160a72e..09200d5 100644 --- a/contracts/libraries/PatriciaTrie.sol +++ b/contracts/libraries/PatriciaTrie.sol @@ -6,7 +6,7 @@ import "./RLP.sol"; library PatriciaTrie { - function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) public returns (bool) { + function verifyProof(bytes _value, bytes _parentNodes, bytes _path, bytes32 _root) internal returns (bool) { RLP.RLPItem memory nodes = RLP.toRLPItem(_parentNodes); RLP.RLPItem[] memory parentNodes = RLP.toList(nodes); diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 785090a..8e29bbe 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -79,6 +79,7 @@ func Launch( c.Println(err) return } + c.Println("Added!") } c.Println("===============================================================") }, @@ -247,21 +248,14 @@ func Launch( library[name] = address } - fmt.Printf("Library data: %s\n", library) - compiledContract, err := contract.CompileContractWithLibraries(contractInstance.Path, library) if err != nil { c.Println(err) return } - c.Printf("Compiled Contract: %s\n", compiledContract) - - /* binStr, abiStr := contract.GetContractBytecodeAndABI(compiledContract) - c.Printf("Binary string: %s\n", binStr) - account := accounts[c.Args[1]] if account == nil { errStr := fmt.Sprintf("Account %s not found.\nUse \taddAccount [name] [path/to/keystore] \n", c.Args[1]) @@ -281,7 +275,6 @@ func Launch( return } - payload := contract.CompilePayload(binStr, abiStr, constructorInputs...) tx, err := contract.DeployContract( @@ -303,7 +296,7 @@ func Launch( c.Println(err) return } - c.Printf("Deployed contract at: %s\n", addr.String())*/ + c.Printf("Deployed contract at: %s\n", addr.String()) } c.Println("===============================================================") }, @@ -1404,6 +1397,7 @@ func checkClientExists(client *EthClient) bool { } func addContractInstance(pathToContract string, contractName string, contracts map[string]*contract.ContractInstance) (error) { + fmt.Println("Compiling contract...") compiledContract, err := contract.CompileContractAt(pathToContract) if err != nil { return err @@ -1413,6 +1407,7 @@ func addContractInstance(pathToContract string, contractName string, contracts m if err != nil { return err } + fmt.Println("Creating contract instance...") contracts[contractName] = &contract.ContractInstance{Contract: compiledContract, Abi: &abistruct, Path: pathToContract} return nil } diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index 2551d4a..e4ab925 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -258,12 +258,11 @@ func CompileContractWithLibraries(contractPath string, libraries map[string]comm address := libraries[name] libraryArg := name + ":" + address.String() - args = append(args, fmt.Sprintf("--libraries=\"%s\"", libraryArg)) + args = append(args, fmt.Sprintf("--libraries=%s", libraryArg)) } i := strings.Index(contractPath, contractFolder) args = append(args, fmt.Sprintf("../=%s ", contractPath[:i])) - fmt.Println(args) contract, err := compiler.CompileSolidity("", args, contractPath) if err != nil { diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 39ca2b1..df0499d 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,16 +1,12 @@ const Ion = artifacts.require("Ion"); const Clique = artifacts.require("Clique"); const EthereumStore = artifacts.require("EthereumStore"); -const PatriciaTrie = artifacts.require("PatriciaTrie"); const EventFunction = artifacts.require("Function"); const EventVerifier = artifacts.require("TriggerEventVerifier"); module.exports = async (deployer) => { try { - deployer.deploy(PatriciaTrie) - .then(() => PatriciaTrie.deployed) - .then(() => deployer.link(PatriciaTrie, EthereumStore)) - .then(() => deployer.deploy(Ion, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")) + deployer.deploy(Ion, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") .then(() => Ion.deployed) .then(() => deployer.deploy(EthereumStore, Ion.address)) .then(() => EthereumStore.deployed) From 9aca02c057b509e0adf6def170b3d7a915715978 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 28 Nov 2018 18:50:09 +0000 Subject: [PATCH 169/203] First draft of new README. Cleaned up code. --- README.md | 406 ++++++++++----------------------------------- ion-cli/README.md | 117 +++++++++++++ ion-cli/cli/cli.go | 319 ++--------------------------------- ion-cli/main.go | 49 +----- 4 files changed, 223 insertions(+), 668 deletions(-) create mode 100644 ion-cli/README.md diff --git a/README.md b/README.md index 54370d9..6b2a487 100644 --- a/README.md +++ b/README.md @@ -1,366 +1,136 @@ # Ion Interoperability Framework The Ion Interoperability Framework is a library that provides an interface for the development of general cross-chain smart contracts. -## Getting Started +We strive towards a more interconnected fabric of systems, and to this end, methods for inter-system and cross-chain communications become paramount in facilitating this connected ecosystem. Ion is a system and function-agnostic framework for building cross-interacting smart contracts between blockchains and/or systems. It does not restrict itself to certain methods of interoperation and is not opinionated on what specific functions it should be built for and as such is an open protocol. -Clone the repository +Atomic swaps and decentralised exchanges can be built on Ion and facilitate the free movement of value across different blockchains. These are just two of the possible use-cases that can be developed on top of the Ion framework. -## Interoperate with Rinkeby! +Ideally we envision Ion to evolve to become a library of tools that developers can use on any system to build cross-chain smart contracts to interoperate with any other system. -We've already deployed some contracts to the Rinkeby test network for you to play around with! +### Contents +* [Getting Started](#getting-started) +* [Interoperate with Rinkeby!](#interoperate-with-rinkeby-) +* [Develop on Ion](#develop-on-ion) +* [Ion CLI](#ion-cli) +* [Contribute!](#contribute-) -Trigger: 0xA2e4a61a3D2ce626Ba9B3e927cfFDB0e4E0bd06d +## Getting Started -Procedure: -./ion-cli ->>> addContractInstance ion /path/to/Ion.sol ->>> addContractInstance ethstore /path/to/EthereumStore.sol ->>> addContractInstance clique /path/to/Clique.sol ->>> addAccount name_of_your_account /path/to/keystore.json ->>> connectToClient https://your.endpoint:port ->>> deployContract ion name_of_your_account gaslimit ->>> deployContract ethstore name_of_your_account gaslimit ->>> deployContract clique name_of_your_account gaslimit +Clone the repository and ensure that all the components work out of the box. -## Develop on Ion +Run: +``` +$ npm install``` +``` +$ npm run testrpc``` +``` +$ npm run test``` -## CLI +to test the full stack of contracts including our example flow. +The tests should pass nicely. With that you've just interoperated your test RPC client with the Rinkeby testnet! Our repository includes some example contracts that show you how to build smart contracts that interoperate with another chain and what mechanism that looks like. -## How it works +We'll now use these example contracts to show you exactly how interoperation with Rinkeby looks like. +## Interoperate with Rinkeby! -# Contribute! +This is a quick tutorial using our example contracts included to be able to verify a state transition in a block and call a function that depends on it. We'll demonstrate that you can use the following instructions below to interoperate from any Ethereum chain with Rinkeby. +We've already deployed some contracts to the Rinkeby test network for you to play around with! +Ion: `0xFEA947D9979c96d65CE7a514B3FeBbA67E54CD18` +Clique: `0x9D94343187a5Fcd4e4552060874d4B1ad25c8c3D` -The Ion Interoperability Framework provides a interface to perform interoperability across multiple turing-complete blockchains. Using the generalised framework specific use cases, such as atomic swaps, can be developed. +Ethereum Block Store: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` -In order to perform cross-chain interop the Ion framework verifies specific transactions executed on one blockchain A on another blockchain B. Being able to verify these transactions cross-chain requires submission of valid block headers, to the blockchain where a transaction is to be proven, and then performing a number of Patricia trie proofs of the transaction, receipts and logs. Smart contracts can then be built to execute only if the proof is verified, this is known as continuous execution. +We will deploy our own instance of the `Function.sol` contract and pass proofs to verify a transaction that we will depend on in order to execute a function in the contract. If the proofs verify correctly then the function should emit an event to indicate that it has been executed. -To facilitate this Ion has three main components: - * Block Storage Contracts - * Modular Validation Scheme - * Ion Framework Contracts +Procedure: +1. `./ion-cli` Starts the CLI +2. `>>> connectToClient https://rinkeby.infura.io` Connect to the Rinkeby Testnet +3. `>>> addAccount me /keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. +4. `>>> addContractInstance function ../contracts/functional/Function.sol` Add your functional contract instance which compiles your contract +5. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: + * `_storeAddr`: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` + * `_verifierAddr`: `0xf973eB920fDB5897d79394F2e49430dCB9aA4ea1` +6. `>>> transactionMessage function verifyAndExecute me 0 gaslimit` Call the function. This requires you to supply the deployed contract instance address. Here you will need to supply the following data as an input to the function when prompted: + * `_chainId`: `0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177` + * `_blockHash`: `0xf88ef06bc1a9c60457d8a4b65c4020dae2ef7f3287076a4d2d481a1bcb8e3148` + * `_contractEmittedAddress`: `0x5dF43D6eaDc3EE940eCbf66a114486f3eF853da3` + * `_path`: `0x04` + * `_tx`: `0xf86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5` + * `_txNodes`: `0xf90236f851a0c478a441c408d00ad410c89a76a635913325eb62a8650ccbc96e8998d50e36dc80808080808080a0edb4c44cbd3957a9226f30b982449d487ff09ff0e933a25f1c005d9df93289c38080808080808080f9017180a07ad13782edc2465b8d6c914d6a18368597b6c906b420d5e3a3dd5dbc408166fba0600296a0213fdce5c37d0520f8e23c32c90bad0e8d9163edb6357fe794546e09a05e5cdcbc193fe8a2966f8d5ecc6d94bd527c37b3f6ae0a3530c9f22cd8efc1b4a09fcfbbffd3fc9b6d7bfc57ec78811f425a24c3828d2ac203c06c7540dd382514a0a0b78e007d6cbcd9fd048ebc6397ca0d067397fb5d61f32fdc118377eaf1039ba032a122caf55ecfa596d4671830e058d6116902ada20591c72f43b299d6b0cb95a06c1f1b6f656336723110875d56d38470520fc82eea9939956ea7c77cd98de7e4a0bb2cffa7c59f46bfadcb40f32a8294ed45c991e6b6e858fc1a81c1ae8e546800a0916fe7ee83eed2a2864dcb5989522af36983674b9a89b8ab856f0e92236383a7a0fa44c96e10751887a97d8855c941805d5de5a7bbb31dfbcdb7100144d35ac4cca0c43a7ef5f5eb44ddd864b3fb9e7be9953e49c5ca089c034175d98b80e5f461718080808080f86d20b86af86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5` + * `_receipt`: `0xf90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605` + * `_receiptNodes`: `0xf90335f851a08fbb95708b2169b98ca70955d2280ea41a4490918c7097b9fbb0dc02b6c1021d80808080808080a07e520e72a52d285315cad163ae68ff5f5b9d7b2efb8bf38488428249580b8aee8080808080808080f9017180a03f63d06b509ff798f0c456e58402326006f83b1dfbddf00ee61810754489817ca05f0c69a424cccf549fa2a1e460cab220f18238fac997214049480a1c48f320eaa0faee39d4012a0db36c610ac5f41306041dee4488d47bc41242afb40582e2b8ffa0d298be00622dc72ef2d1a2df8a259bcf769d36e4502ef8b1b2dbde2d19736c3ba04f78ffe7b29e2192dee6197eeeb19f56801dfe092c3fc485f8e2ca0141dddb1ca0e1c200d90941dbf37ac5d0f37e40479de4b2fe1a0a1b398c9f64cf80d6010eb0a034d7af644f909a94dc41bfa08ae9d0ea1c0d053e0c520378e8a5f2efd6422b62a068858e77fadd9ae975d9aff2e23e40b0f50dab934654a261930a40101ce370a0a068be4c01c98beead34d05516b5236e6196d85125b89e2632f23bdf16e7b16fe4a09f0c3ad7917f3f28a66d151270d2cd4ece50fecb2bd769c38512f1e9c5f9355ea05e1856c7908a4428edb582898261e563b2356fa3d1134357b47799a3e470bcc18080808080f9016b20b90167f90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605` + * `_expectedAddress`: `0xb8844cf76df596e746f360957aa3af954ef51605` +7. Success! The transaction should have been created and sent. Check on [Etherscan](https://rinkeby.etherscan.io/address/0xb8844cf76df596e746f360957aa3af954ef51605) (or any other method) whether the transaction was successful or not. It should have succeeded! + +### Try out your own functions! + +Take a look at `Function.sol` and you'll find a very simple `execute()` function. Try adding your own logic or event emissions here and follow the same procedure above and you'll be able to execute your own arbitrary code with a dependence on a particular state transition. + +You can now also attempt to write your own functional smart contracts using the similar skeleton to the `Function.sol` contract. + +Note that all the data submitted as a proof to the function call is generated merkle patricia proofs for a particular transaction at `0xcd68852f99928ab11adbc72ec473ec6526dac3b1b976c852745c47900f6b8e30` that was also executed on the Rinkeby Testnet. This transaction emits a `Triggered` event which contains the address of the caller when emitted. The `Function.sol` contract simply consumes events of this type, verifies that the transaction occurred in a block, that the event parameters are as expected and then executes a function. -The Ion hub contract is the core component of the framework, the contract persists key data of all valid blocks submitted to the validation contracts required to verify a state transition. To prove a transaction has occurred on an external blockchain the Ion framework contract require (for EVM-based chains): +## Develop on Ion -* Block Header: - * Tx root hash - * Receipt root hash -* Block Hash +Develop your own cross-chain smart contracts using the Ion interface! -For other blockchains, different data will be required to prove state transitions and as such contracts must be written that adhere to those system-specific mechanisms. +### Core Concept -For each block submitted to the validation contracts this information is appended to the Ion hub contract, thus creating a generic interface for Ion framework contracts to receive valid block data. Ion provides a generalised interoperability framework and thus block validation is designed to be modular, in order to allow for interop between chains with any consensus mechanism. +The core of Ion revolves around the concept of dependence on state. As such, to create functional cross-chain smart contracts, the idea is to be able to make the execution of a smart contract function be dependent on some state transition to have occurred. Thus we create smart contracts that perform verification of state transitions before allowing the execution of code and this can be done many ways depending on the systems that intend to interoperate. -When external blockchains are registered with a specific validation contract, having its own consensus specific validation mechanism, the validation contract adds the chain to the Ion hub. Subsequently all blocks successfully submitted to the validation contract are added to the Ion hub. +### Ethereum-Ethereum -More details can be found in the [Ion Wiki](https://github.com/clearmatics/ion/wiki). +With Ethereum, this is done via event consumption. Using the presence of an event in a transaction, we can verify if the expected computation was done and to only do something if the verification succeeds. -## Running the Project -A Clique PoA chain is launched and then the block headers are taken and updated to the validation contract which is deployed on a ganache chain. However in the javascript tests the contract is deployed on the PoA chain itself for sake of simplicity, this has no bearing on the functionality of the project. +To write a smart contract that depends on particular state transitions there are pre-requisites: +* Event Verifier contracts -Running the project requires initialisation of the following components: - * Validation smart contract and tests - * Two separate blockchain: Clique _proof of authority_ network, Ganache test network - * Golang Ion CLI used to interact with the smart contract(s) +For any event signature, a corresponding Event Verifier contract must be written which encodes the mechanism that extracts the relevant event to check expected parameters as part of the verification. -In order to use the smart contracts and run the tests it is necessary to first initialise the test networks. +`TriggerEventVerifier.sol` is a very simple event verifier: +* Holds the event signature it decodes +* Encodes a verification function that takes expected fields as input to check against that included in the event -**Note:** that as the contract searches for specific parts of the block header that only exist in Clique and IBFT, Ganache or Ethash chains cannot be used for the _root_ blockchain from which headers are extracted. +All Event Verifier contracts should perform the same way. The differences will simply be in the event signature and parameters checks of the event. -### Requirements -* golang version: 1.9.x +`Function.sol` provides a very simple example of how an event-consuming contract is written. Changing the event to be consumed by referencing a different Event Verifier allows you to draw dependence on a different state transition. -### Installing Ion -Having cloned and entered the repo: -``` -$ git clone git@github.com:clearmatics/ion.git -$ cd /path/to/ion -``` +### Testing -Now run the command: -``` -$ tree -L 1 -``` +Test-driven development and unit-testing all individual components of your smart contracts are extremely important in developing cross-chain contracts. There are two main steps to testing: -Which hopefully returns this: -``` -. -├── CODE_OF_CONDUCT.md -├── contracts -├── CONTRIBUTING.md -├── docs -├── ion-cli -├── LICENSE -├── Makefile -├── migrations -├── package.json -├── package-lock.json -├── README.md -├── test -└── truffle.js -``` +* Core functionality of smart contracts +* Integration with Ion Interface -### Testing Contracts -In order to test the Solidity contracts using the Javascript tests a testrpc must be run. As the validation contract relies upon receiving signatures in the `extraData` field of the block header it is not sufficient to run an instance of ganache-cli, rather a Clique PoA chain must be initialised. +Traditional tests that ensure that your smart contract is operating in the way that you intended is always required. However with the added use of the Ion interface, you'll need to write tests that make sure they both integrate well with the verification mechanisms and still behave in the expected way. -Having launched a Clique PoA chain, hosted on `127.0.0.1:8501` (the first account on the `eth.accounts` array should be unlocked in the node), run the tests as follows: -``` -$ npm install -$ npm run test -``` +Study the tests in the repository to discover how we've unit-tested the entire integrated stack of smart contracts. -### Ion Command Line Interface -The Ion CLI is a tool for handling the passing of block headers between to blockchains written in Golang to leverage the extensive ethereum libraries. It is not a critical part of the Ion infrastructure rather is just an open utility that people can extend and use as they see fit. +## Ion CLI -In its current form the Ion CLI allows the user to connect to two separate blockchains, via RPC, and submit block headers to a validation contract. +The Command-Line Interface reference can be found [here]() -#### Testing Ion CLI -``` -$ cd ion-cli -$ make build -``` -In order to run the basic unit tests for the Ion CLI run, -``` -$ make test -``` -If the tests pass successfully then the CLI can be run. +## How Ion works -Additional integration tests can be run however it requires launching a Clique PoA chain as above. To run the integration tests launch command, -``` -$ make integration-test -``` +Please see our Wiki for more detailed information about the design philosophy of Ion. -#### Running Ion CLI -As mentioned in the project description this simple implementation of the validation contract is active only on a single blockchain, however the CLI is simulating the passing of the headers to and from as if it were between separate chains. - -Having followed the instructions on how to setup a Clique blockchain, which is hosted on `127.0.0.1:8501`, we run a ganache-cli in another terminal on `127.0.0.1:8545` and deploy the contract to the ganache blockchain, -``` -$ npm run testrpc -$ npm run deploy -``` - -Following this we can attach to the Ion Command Line Interface, -``` -$ cd /path/to/ion/ion-cli -$ make build -$ make test -``` -Assuming a successful build and passing of the tests a setup file which contains the connection of the separate blockchains, user accounts, account keystores, and the address of the deployed validation contract should be created. Change the default values in the example setup.json then run the `ion-cli` poiinting to the modified setup file. -``` -$ ./ion-cli --config [/path/to/setup.json] -=============================================================== -Ion Command Line Interface - -RPC Client [to]: - Listening on: http://127.0.0.1:8501 - User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d - RPC ChainId: 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 - Validation Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f - Ion Contract: 0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613 - Function Contract: 0x49e71afdcaf62d7384f0b801c9e3c6e18d4a2597 - -RPC Client [from]: - Listening on: https://127.0.0.1:8545 - User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d - Trigger Contract: 0x61621bcf02914668f8404c1f860e92fc1893f74c -=============================================================== ->>> -``` -running help displays the available commands. -``` ->>> help -Commands: - checkBlockValidation use: checkBlockValidation - Enter Blockhash: [HASH] - description: Returns true for validated blocks - clear clear the screen - exit exit the program - getBlock use: getBlock [TO/FROM] [integer] - description: Returns block header specified from chain [TO/FROM] - help display help - latestBlock use: latestBlock [TO/FROM] - description: Returns number of latest block mined/sealed from chain [TO/FROM] - latestValidatedBlock use: latestValidatedBlock - description: Returns hash of the last block submitted to the validation contract - registerChainValidation use: registerChainValidation - Enter Validators: [ADDRESS ADDRESS] - Enter Genesis Hash: [HASH] - description: Register new chain with validation contract - submitBlockValidation use: submitBlockValidation - Enter Block Number: [INTEGER] - description: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract - triggerEvent use: triggerEvent - description: Returns hash of the last block submitted to the validation contract - verifyAndExecute use: verifyAndExecute [Transaction Hash] - description: Returns the proof of a specific transaction held within a Patricia trie -``` - -#### Ion CLI Walkthrough -A simple walkthrough of the Ion framework between a local testrpc and the Rinkeby test network is detailed. Users can trigger an event on Rinkeby with the account `0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d` and verify the transaction on the local testrpc where they deploy the event consuming contracts. - -A brief overview of the steps required are: -* Launch Ion CLI -* Register rinkeby with the validation contract -* Trigger event on rinkeby test network - this tutorial will use the transaction `0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098` - [check etherscan](https://rinkeby.etherscan.io/tx/0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098) -* Submit relevant rinkeby blocks to the validation contract -* Verify event happened on testrpc and execute function - -##### Step 1. Launch Ion CLI -Having followed the instructions to run and build the Ion CLI and testrpc, see [here](https://github.com/clearmatics/ion/tree/ion-stage-2#running-ion-cli), launch the CLI with the setup file `rinkeby.json`. -``` -$ ./ion-cli --config rinkeby.json -=============================================================== -Ion Command Line Interface - -RPC Client [to]: - Listening on: http://127.0.0.1:8545 - User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d - RPC ChainId: 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 - Validation Contract: 0xb9fd43a71c076f02d1dbbf473c389f0eacec559f - Ion Contract: 0x6aa4444974f60bf3a0bf074d3c194f88ae4d4613 - Function Contract: 0x49e71afdcaf62d7384f0b801c9e3c6e18d4a2597 - -RPC Client [from]: - Listening on: https://rinkeby.infura.io - User Account: 0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d - Trigger Contract: 0x61621bcf02914668f8404c1f860e92fc1893f74c -=============================================================== ->>> -``` +# Contribute! -##### Step 2. Register Chain -In order to validate blocks first the chain must be registered in the validation contract on the testrpc: -``` ->>> registerChainValidation -Connecting to: http://127.0.0.1:8545 -Enter Validators: 0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91 -Enter Genesis Hash: 0x100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c - -Returns: -Transaction: 0xcd5f4405260a6935b048e9136d211df99e594359abe04dcf975c730e5cf0d708 -=============================================================== -``` +Ion is not a finished project! We would love contributors to help evolve Ion into a universal framework for interoperability. -To see if it has successfully been registered we can check the the contract if this is a valid block: -``` ->>> checkBlockValidation -Connecting to: http://127.0.0.1:8545 -Enter BlockHash: 0x100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c -Checking for valid block: -ChainId: ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 -BlockHash: 100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c - -Returns: -Valid: true -=============================================================== -``` +Functional use-case smart contracts should not live in this repository. Please create use-cases in your own repositories and we'll include a link to them in our Ion-based contract catalogue. -##### Step 3. Submit Block to Validation -As our event happened in block 2776659 this block must be submitted to the validation contract prior to verification of our transaction. -``` ->>> submitBlockValidation -Connecting to: http://127.0.0.1:8545 -Enter Block Number: 2776659 -RLP encode block: -Number: 2776659 -Signed Block Header Prefix: -f9025ca0100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ad9b6d8c20a0631e2513968cdf3667dffabf9d2f6c1bf22a5990861192e1d266a053413d0e5fd5854665fab663ad8ffb0f5d06bf1907a5a0a3e45300de1ce23fcda0997750d465d96422e7692e281d16db709e6ff9c11c1d8229410340cf1598a8b6b9010000000000c0000010000000000000000000000000000000008000000000000000000000040000000000002004000000000000000002000000000000000004000000010000000008000000002800000002000000000004000000000001000001400000000002000000040000000000080080000000000000000000001000008000000000002000000000000000000000000000000000000000000002000000000000000000010000000010004000000000000020000000000000000000000000000200010300000000000005000040000000000004000000000000000042006000000000200000008000000000000000800000020400000000001080020080000001832a5e53836b33668349d003845b6ab5b9b861d68301080d846765746886676f312e3130856c696e75780000000000000000000cd4835e13d2204ad1fbc94d18a1a0373e92ffc63a021f8212a72dd1cff2e2057bded7534ed90df2492e60c7050db528715e3bc7734bef0a4c97542886cbc57c01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000 - -Unsigned Block Header Prefix: -f9021aa0100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ad9b6d8c20a0631e2513968cdf3667dffabf9d2f6c1bf22a5990861192e1d266a053413d0e5fd5854665fab663ad8ffb0f5d06bf1907a5a0a3e45300de1ce23fcda0997750d465d96422e7692e281d16db709e6ff9c11c1d8229410340cf1598a8b6b9010000000000c0000010000000000000000000000000000000008000000000000000000000040000000000002004000000000000000002000000000000000004000000010000000008000000002800000002000000000004000000000001000001400000000002000000040000000000080080000000000000000000001000008000000000002000000000000000000000000000000000000000000002000000000000000000010000000010004000000000000020000000000000000000000000000200010300000000000005000040000000000004000000000000000042006000000000200000008000000000000000800000020400000000001080020080000001832a5e53836b33668349d003845b6ab5b9a0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000 - -Returns: -Transaction Hash: 0x965da7ac02d7ef58417e32b427b33ff2717d3cd6bb213fd05853a2c8d0fd092e -=============================================================== -``` +The repository is segmented into two main sections that require work: +* Validation +* Storage -Again check that the block has successfully been validated: -``` ->>> checkBlockValidation -Connecting to: http://127.0.0.1:8545 -Enter BlockHash: 0x74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046 -Checking for valid block: -ChainId: ab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 -BlockHash: 74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046 - -Returns: -Valid: true -=============================================================== -``` +Each system requires a mechanism to be able to prove the correctness/validity of any data it holds, and this mechanism must be encoded by a Validation contract. Thus each method by which data could be validated must have its own contract that describes it. For example, to validate blocks from a proof-of-authority chain, we must replicate the verification mechanism of that specific implementation. -##### Step 4. Verify and Execute Event Consuming Contract -Now the block that contains our event has been successfully submitted to the validation contract we can execute the contract which consumes the event: -``` ->>> verifyAndExecute -Connecting to: http://127.0.0.1:8545 -Enter Transaction Hash: 0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098 -Enter Block Hash: 0x74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046 - -Returns: -Transaction Hash: 0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb -=============================================================== -``` +Each system holds its data in different formats, and subsequently proving that the data exists would be different. Thus a different storage contracts must be written that decode and store any arbitrary data formats for use on any other system. For example, proving a transaction exists in an Ethereum block is different from proving a UTXO in a Bitcoin block. -##### Step 5. Check Transaction Successfully Executed -Attach to the geth client of the RPC TO chain and run: -``` -> eth.getTransactionReceipt("0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15") -{ - blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", - blockNumber: 11, - contractAddress: null, - cumulativeGasUsed: 352099, - gasUsed: 352099, - logs: [{ - address: "0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", - blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", - blockNumber: 11, - data: "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac807574d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b0460000000000000000000000000000000000000000000000000000000000000002", - logIndex: 0, - topics: ["0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046"], - transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", - transactionIndex: 0, - type: "mined" - }, { - address: "0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", - blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", - blockNumber: 11, - data: "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac807574d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b0460000000000000000000000000000000000000000000000000000000000000000", - logIndex: 1, - topics: ["0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046"], - transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", - transactionIndex: 0, - type: "mined" - }, { - address: "0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", - blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", - blockNumber: 11, - data: "0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac807574d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b0460000000000000000000000000000000000000000000000000000000000000001", - logIndex: 2, - topics: ["0xf0bc00f5b90f382e1bbca216713ca9e2e8e298f9d7717d30847905395f287046"], - transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", - transactionIndex: 0, - type: "mined" - }, { - address: "0x93981af8db02c7ef40d0ed61caef2726a79eb903", - blockHash: "0x9da94ab127a05a81c5a8ec159e5e103efe44403c57685d53da1b0126880a47fb", - blockNumber: 11, - data: "0x00", - logIndex: 3, - topics: ["0x68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e"], - transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", - transactionIndex: 0, - type: "mined" - }], - logsBloom: "0x00000000000000000000000000000000000000000001000000080000000000000000000800000000000000000000000000000000000000010000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000100080000000000000000000000040000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000", - status: "0x1", - transactionHash: "0x40538002f640c647bcf4feb922e31523c0cd2b46b38791dd7368e8cbe5bbba15", - transactionIndex: 0 -} -``` -`status: "0x1"` shows the transaction executed successfully! +With the above, we aim to expand our system-specific implementations for verification of both data validity and state transitions to allow the easier development of smart contracts using these interfaces. \ No newline at end of file diff --git a/ion-cli/README.md b/ion-cli/README.md new file mode 100644 index 0000000..eacd918 --- /dev/null +++ b/ion-cli/README.md @@ -0,0 +1,117 @@ +# Ion CLI + +The Command-Line Interface reference. + +## Building the CLI + +Run `make build` to fetch sources and compile the binary. + +## Usage + +Run `./ion-cli` to launch the interface. + +``` +addAccount use: addAccount [name] [path/to/keystore] + description: Add account to be used for transactions + +Adds an account to be referenced by given name that can be used to sign transactions from. Takes a name +(string) that can be any chosen name, and a path to a keystore file containing an encrypted private key. + +Accounts are not persisted between sessions.``` +``` +addContractInstance use: addContractInstance [name] [path/to/solidity/contract] + description: Compiles a contract for use + +Adds a compiled contract instance. This contract instance can be deployed to a connected chain or used +to make function calls to deployed contracts. Takes any chosen name (string) and a path to the Solidity +contract to be compiled. + +Contracts are not persisted between sessions.``` +``` +clear clear the screen``` +``` +connectToClient use: connectToClient [rpc url] + description: Connects to an RPC client to be used + +Connects to an Ethereum blockchain specified by a given url. This chain will be used for contract +deployment, calls, chain data etc. unless specified otherwise. + +Only one client can be connected at a time.``` +``` +deployContract use: deployContract [contract name] [account name] [gas limit] + description: Deploys specified contract instance to connected client + +Deploys a specified compiled contract instance by name from the specified account name to the connected +client. Requires gas limit to be provided.``` +``` +exit exit the program``` +``` +getBlockByHash use: getBlockByHash [optional rpc url] [hash] + description: Returns block header specified by hash from connected client + or from specific endpoint + +Retrieves the block header from the connected or specified endpoint at given block hash.``` +``` +getBlockByHash_Clique use: getBlockByHash_Clique [optional rpc url] [hash] + description: Returns signed and unsigned RLP-encoded block headers by + block hash required for submission to Clique validation connected + client or specified endpoint + +Retrieves RLP-encoded block headers that have been signed and unsigned by validators of the Clique +mechanism specified by block hash. This is used to be submitted to the Clique validation contract +scheme for interoperation with Clique proof-of-authority chains.``` +``` +getBlockByNumber use: getBlockByNumber [optional rpc url] [integer] + description: Returns block header specified by height from connected + client or from specified endpoint + +Retrieves the block header from the connected or specified endpoint at given block number.``` +``` +getBlockByNumber_Clique use: getBlockByNumber_Clique [optional rpc url] [integer] + description: Returns signed and unsigned RLP-encoded block headers by + block number required for submission to Clique validation from connected + client or specified endpoint + +Retrieves RLP-encoded block headers that have been signed and unsigned by validators of the Clique +mechanism specified by block number. This is used to be submitted to the Clique validation contract +scheme for interoperation with Clique proof-of-authority chains.``` +``` +getProof use: getProof [optional rpc url] [Transaction Hash] + description: Returns a merkle patricia proof of a specific transaction + and its receipt in a block + +Retrieves a merkle patricia trie proof of a transaction in a block. It checks against the Transaction +Trie and the Receipt Trie in a block, reconstructs the trie and generates a proof that the specified +transaction exists in the trie and returns the data to verify the proof.``` +``` +getTransactionByHash use: getTransactionByHash [optional rpc url] [hash] + description: Returns transaction specified by hash from connected + client or specified endpoint + +Retrieves the transaction data of a specified transaction by hash.``` +``` +help display help``` +``` +linkAndDeployContract use: deployContract [contract name] [account name] [gas limit] + description: Deploys specified contract instance to connected client + +Links any required libraries to a contract instance before deploying to the connect client.``` +``` +listAccounts use: listAccounts + description: List all added accounts + +Lists all added accounts.``` +``` +listContracts use: listContracts + description: List compiled contract instances + +Lists all added contract instances.``` +``` +transactionMessage use: transactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] + description: Calls a contract function as a transaction. + +Calls a contract instance function that has been deployed to the connected client as a transaction. This +will mutate the world state of the destination chain if the transaction is accepted into a block. +Requires gas. + +Will be prompted to provide function input parameters.``` \ No newline at end of file diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 8e29bbe..87378f4 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -10,13 +10,9 @@ import ( "errors" "strings" "reflect" - "os/exec" - "bytes" "github.com/ethereum/go-ethereum/common" - //"github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -28,11 +24,7 @@ import ( ) // Launch - definition of commands and creates the interface -func Launch( - configuration config.Setup, - clientTo *rpc.Client, - clientFrom *rpc.Client, -) { +func Launch() { // by default, new shell includes 'exit', 'help' and 'clear' commands. shell := ishell.New() @@ -72,7 +64,7 @@ func Launch( Help: "use: \taddContractInstance [name] [path/to/solidity/contract]\n\t\t\t\tdescription: Compiles a contract for use", Func: func(c *ishell.Context) { if len(c.Args) != 2 { - c.Println("Usage: \taddContractInstances [name] [path/to/solidity/contract]\n") + c.Println("Usage: \taddContractInstance [name] [path/to/solidity/contract]\n") } else { err := addContractInstance(c.Args[1], c.Args[0], contracts) if err != nil { @@ -145,7 +137,7 @@ func Launch( } contractInstance := contracts[c.Args[0]] if contractInstance == nil { - errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) + errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstance [name] [path/to/solidity/contract]\n", c.Args[0]) c.Println(errStr) return } @@ -230,7 +222,7 @@ func Launch( } contractInstance := contracts[c.Args[0]] if contractInstance == nil { - errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) + errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstance [name] [path/to/solidity/contract] \n", c.Args[0]) c.Println(errStr) return } @@ -304,7 +296,7 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "transactionMessage", - Help: "use: \ttransactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n\t\t\t\tdescription: Connects to an RPC client to be used", + Help: "use: \ttransactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n\t\t\t\tdescription: Calls a contract function as a transaction.", Func: func(c *ishell.Context) { if len(c.Args) != 6 { c.Println("Usage: \ttransactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] \n") @@ -320,7 +312,7 @@ func Launch( contractDeployedAddress := common.HexToAddress(c.Args[3]) if instance == nil { - errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstances [name] [path/to/solidity/contract] [deployed address] \n", c.Args[0]) + errStr := fmt.Sprintf("Contract instance %s not found.\nUse \taddContractInstance [name] [path/to/solidity/contract] \n", c.Args[0]) c.Println(errStr) return } @@ -373,31 +365,12 @@ func Launch( return } c.Printf("Transaction hash: %s\n", receipt.TxHash.String()) - c.Printf("Mined in block: %s\n", receipt.TxHash.String()) } } c.Println("===============================================================") }, }) - shell.AddCmd(&ishell.Cmd{ - Name: "test", - Help: "use: \ttest \n\t\t\t\tdescription: Connects to an RPC client to be used", - Func: func(c *ishell.Context) { - var stderr, stdout bytes.Buffer - - args := []string{"--combined-json", "bin,abi,userdoc,devdoc,metadata", "--optimize", "--libraries=ReallyExtremelyVeryIncrediblyObnoxiouslySurprisinglyLongLibraryName:0xe9215b0d0A66CeBd1A50F468dFACF748cB065165", "--libraries=EvenMoreReallyExtremelyVeryIncrediblyObnoxiouslySurprisinglyLongLibraryName:0xe9215b0d0A66CeBd1A50F468dFACF748cB065165", "../=/home/cc/go/src/github.com/clearmatics/ion/contracts/", "/home/cc/go/src/github.com/clearmatics/ion/contracts/test/test.sol"} - //cmd := exec.Command("solc", "--combined-json", "bin,abi,userdoc,devdoc,metadata", "--optimize", "--libraries=PatriciaTrie:0xe9215b0d0A66CeBd1A50F468dFACF748cB065165", "../=/home/cc/go/src/github.com/clearmatics/ion/contracts/", "/home/cc/go/src/github.com/clearmatics/ion/contracts/storage/EthereumStore.sol") - cmd := exec.Command("solc", args...) - cmd.Stderr = &stderr - cmd.Stdout = &stdout - err := cmd.Run() - c.Println(err) - c.Printf("%s\n", stderr.Bytes()) - c.Printf("%s\n", stdout.Bytes()) - }, - }) - /*shell.AddCmd(&ishell.Cmd{ Name: "callMessage", Help: "use: \tcallMessage [contract name] [function name] [from account name] [deployed contract address] \n\t\t\t\tdescription: Connects to an RPC client to be used", @@ -462,7 +435,7 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "getTransactionByHash", - Help: "use: \tgetTransactionByHash [optional rpc url] [hash]\n\t\t\t\tdescription: Returns transaction specified by hash", + Help: "use: \tgetTransactionByHash [optional rpc url] [hash]\n\t\t\t\tdescription: Returns transaction specified by hash from connected client or specified endpoint", Func: func(c *ishell.Context) { var json []byte var err error @@ -496,7 +469,7 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "getBlockByNumber", - Help: "use: \tgetBlockByNumber [optional rpc url] [integer]\n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Help: "use: \tgetBlockByNumber [optional rpc url] [integer]\n\t\t\t\tdescription: Returns block header specified by height from connected client or from specified endpoint", Func: func(c *ishell.Context) { var json []byte var err error @@ -530,7 +503,7 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "getBlockByHash", - Help: "use: \tgetBlockByNumber [optional rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Help: "use: \tgetBlockByHash [optional rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified by hash from connected client or from specific endpoint", Func: func(c *ishell.Context) { var json []byte var err error @@ -550,7 +523,7 @@ func Launch( } _, json, err = getBlockByHash(client, c.Args[1]) } else { - c.Println("Usage: \tgetBlockByNumber [optional rpc url] [hash] \n") + c.Println("Usage: \tgetBlockByHash [optional rpc url] [hash] \n") return } if err != nil { @@ -594,7 +567,7 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "getBlockByNumber_Clique", - Help: "use: \tgetBlockByNumber_Clique [optional rpc url] [integer]\n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Help: "use: \tgetBlockByNumber_Clique [optional rpc url] [integer]\n\t\t\t\tdescription: Returns signed and unsigned RLP-encoded block headers by block number required for submission to Clique validation from connected client or specified endpoint", Func: func(c *ishell.Context) { if len(c.Args) == 1 { if ethClient != nil { @@ -634,7 +607,7 @@ func Launch( shell.AddCmd(&ishell.Cmd{ Name: "getBlockByHash_Clique", - Help: "use: \tgetBlockByHash_Clique [optional rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", + Help: "use: \tgetBlockByHash_Clique [optional rpc url] [hash] \n\t\t\t\tdescription: Returns signed and unsigned RLP-encoded block headers by block hash required for submission to Clique validation from connected client or specified endpoint", Func: func(c *ishell.Context) { if len(c.Args) == 1 { if ethClient != nil { @@ -672,274 +645,6 @@ func Launch( }, }) - shell.AddCmd(&ishell.Cmd{ - Name: "getBlockByHash_Clique", - Help: "use: \tgetBlockByHash_Clique [optional rpc url] [hash] \n\t\t\t\tdescription: Returns block header specified from chain [TO/FROM]", - Func: func(c *ishell.Context) { - if len(c.Args) == 1 { - if ethClient != nil { - block, _, err := getBlockByHash(ethClient, c.Args[0]) - if err != nil { - c.Println(err) - return - } - signedBlock, unsignedBlock := RlpEncode(block) - c.Printf("Signed Block: 0x%+x\n", signedBlock) - c.Printf("Unsigned Block: 0x%+x\n", unsignedBlock) - } else { - c.Println("Please connect to a Client before invoking this function.\nUse \tconnectToClient [rpc url] \n") - return - } - } else if len(c.Args) == 2 { - client, err := getClient(c.Args[0]) - if err != nil { - c.Println(err) - return - } - block, _, err := getBlockByHash(client, c.Args[1]) - if err != nil { - c.Println(err) - return - } - signedBlock, unsignedBlock := RlpEncode(block) - c.Printf("Signed Block:\n %+x\n", signedBlock) - c.Printf("Unsigned Block:\n %+x\n", unsignedBlock) - } else { - c.Println("Usage: \tgetBlockByHash_Clique [optional rpc url] [hash]\n") - return - } - c.Println("===============================================================") - }, - }) - - /* - shell.AddCmd(&ishell.Cmd{ - Name: "registerChainValidation", - Help: "use: \tregisterChainValidation\n \t\t\t\t\tEnter Validators: [ADDRESS ADDRESS]\n \t\t\t\t\tEnter Genesis Hash: [HASH] \n\t\t\t\tdescription: Register new chain with validation contract", - Func: func(c *ishell.Context) { - c.Println("Connecting to: " + configuration.AddrTo) - c.ShowPrompt(false) - defer c.ShowPrompt(true) - - // Get the chainId - bytesChainId := common.HexToHash(configuration.ChainId) - - // Get the validators array - c.Print("Enter Validators: ") - validatorString := c.ReadLine() - valArray := strings.Fields(validatorString) - // valArray := strings.Fields("0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91") - var validators []common.Address - for _, val := range valArray { - validators = append(validators, common.HexToAddress(val)) - } - - // Get genesis hash - c.Print("Enter Genesis Hash: ") - genesis := c.ReadLine() - bytesGenesis := common.HexToHash(genesis) - // bytesGenesis := common.HexToHash("0x100dc525cdcb7933e09f10d4019c38d342253a0aa32889fbbdbc5f2406c7546c") - - tx := contract.RegisterChain( - ctx, - ethclientTo, - keyTo.PrivateKey, - Validation, - common.HexToAddress(configuration.Validation), - bytesChainId, - validators, - bytesGenesis, - ) - - c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) - c.Println("===============================================================") - }, - }) - - shell.AddCmd(&ishell.Cmd{ - Name: "submitBlockValidation", - Help: "use: \tsubmitBlockValidation\n \t\t\t\t\tEnter Block Number: [INTEGER]\n\t\t\t\tdescription: Returns the RLP block header, signed block prefix, extra data prefix and submits to validation contract", - Func: func(c *ishell.Context) { - c.Println("Connecting to: " + configuration.AddrTo) - c.ShowPrompt(false) - defer c.ShowPrompt(true) // yes, revert after login. - - // Get the chainId - bytesChainId, err := utils.StringToBytes32(configuration.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } - - // Get the block number - c.Print("Enter Block Number: ") - blockNum := c.ReadLine() - c.Printf("RLP encode block:\nNumber:\t\t%s", blockNum) - - signedBlock, unsignedBlock := calculateRlpEncoding(ethclientFrom, blockNum) - tx := contract.SubmitBlock( - ctx, - ethclientTo, - keyTo.PrivateKey, - Validation, - common.HexToAddress(configuration.Validation), - bytesChainId, - unsignedBlock, - signedBlock, - ) - - c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) - c.Println("===============================================================") - }, - }) - - shell.AddCmd(&ishell.Cmd{ - Name: "checkBlockValidation", - Help: "use: \tcheckBlockValidation\n \t\t\t\t\tEnter Blockhash: [HASH]\n\t\t\t\tdescription: Returns true for validated blocks", - Func: func(c *ishell.Context) { - c.Println("Connecting to: " + configuration.AddrTo) - c.ShowPrompt(false) - defer c.ShowPrompt(true) // yes, revert after login. - - // Get the chainId - bytesChainId, err := utils.StringToBytes32(configuration.ChainId) - if err != nil { - c.Printf("Error: %s", err) - return - } - - // Get the blockHash - c.Print("Enter BlockHash: ") - blockHash := c.ReadLine() - bytesBlockHash, err := utils.StringToBytes32(blockHash) - if err != nil { - c.Printf("Error: %s", err) - return - } - - result := contract.ValidBlock( - ctx, - ethclientTo, - Validation, - common.HexToAddress(configuration.AddrTo), - common.HexToAddress(configuration.Validation), - bytesChainId, - bytesBlockHash, - ) - - c.Println("Checking for valid block:") - c.Printf("ChainId:\t%x\nBlockHash:\t%x\nValid:\t\t%v\n", bytesChainId, bytesBlockHash, result) - c.Println("===============================================================") - }, - }) - - shell.AddCmd(&ishell.Cmd{ - Name: "latestValidatedBlock", - Help: "use: \tlatestValidatedBlock \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - Func: func(c *ishell.Context) { - c.Println("Connecting to: " + configuration.AddrTo) - // Get the chainId - bytesChainId := common.HexToHash(configuration.ChainId) - - result := contract.LatestValidBlock( - ctx, - ethclientTo, - Validation, - common.HexToAddress(configuration.AddrTo), - common.HexToAddress(configuration.Validation), - bytesChainId, - ) - - c.Println("Checking for latest valid block:") - c.Printf("\nBlockHash:\t0x%x\nChainId:\t%s\n", result, configuration.ChainId) - c.Println("===============================================================") - }, - })*/ - - //--------------------------------------------------------------------------------------------- - // Trigger Specific Commands - //--------------------------------------------------------------------------------------------- - /* - shell.AddCmd(&ishell.Cmd{ - Name: "triggerEvent", - Help: "use: \ttriggerEvent \n\t\t\t\tdescription: Returns hash of the last block submitted to the validation contract", - Func: func(c *ishell.Context) { - c.Println("Connecting to: " + configuration.AddrFrom) - - tx := contract.Fire( - ctx, - ethclientFrom, - keyFrom.PrivateKey, - Trigger, - common.HexToAddress(configuration.Trigger), - ) - - c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) - c.Println("===============================================================") - }, - }) -*/ - - //--------------------------------------------------------------------------------------------- - // Function Specific Commands - //--------------------------------------------------------------------------------------------- - /* - shell.AddCmd(&ishell.Cmd{ - Name: "verifyAndExecute", - Help: "use: \tverifyAndExecute [Transaction Hash] \n\t\t\t\tdescription: Returns the proof of a specific transaction held within a Patricia trie", - Func: func(c *ishell.Context) { - c.Println("Connecting to: " + configuration.AddrTo + " and " + configuration.AddrFrom) - c.ShowPrompt(false) - defer c.ShowPrompt(true) // yes, revert after login. - - // Get the chainId - bytesChainId := common.HexToHash(configuration.ChainId) - - // Get the transaction hash - c.Print("Enter Transaction Hash: ") - txHash := c.ReadLine() - bytesTxHash := common.HexToHash(txHash) - // bytesTxHash := common.HexToHash("0x5da684940b4fd9dec708cc159dc504aa01e90d40bb76a2b73299aee13aa72098") - - // Get the blockHash - c.Print("Enter Block Hash: ") - blockHash := c.ReadLine() - bytesBlockHash := common.HexToHash(blockHash) - // bytesBlockHash := common.HexToHash("0x74d37aa3c96bc98903451d0baf051b87550191aa0d92032f7406a4984610b046") - - // Generate the proof - txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( - ctx, - clientFrom, - bytesTxHash, - ) - - // Execute - tx := contract.VerifyExecute( - ctx, - ethclientTo, - keyFrom.PrivateKey, - Function, - common.HexToAddress(configuration.Function), - bytesChainId, - bytesBlockHash, - common.HexToAddress(configuration.Trigger), // TRIG_DEPLOYED_RINKEBY_ADDR, - txPath, // TEST_PATH, - txValue, // TEST_TX_VALUE, - txNodes, // TEST_TX_NODES, - receiptValue, // TEST_RECEIPT_VALUE, - receiptNodes, // TEST_RECEIPT_NODES, - common.HexToAddress(configuration.AccountFrom), // TRIG_CALLED_BY, - nil, - ) - - c.Printf("Transaction Hash:\n0x%x\n", tx.Hash()) - c.Println("===============================================================") - }, - }) - - */ - // run shell shell.Run() } diff --git a/ion-cli/main.go b/ion-cli/main.go index 156346d..70ee901 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -3,57 +3,20 @@ package main import ( - "flag" - "fmt" - "os" - + "fmt" "github.com/clearmatics/ion/ion-cli/cli" - "github.com/clearmatics/ion/ion-cli/config" - // contract "github.com/clearmatics/ion/ion-cli/contracts" - "github.com/clearmatics/ion/ion-cli/utils" ) -var configFile = flag.String("config", "", "Description:\n path to the configuration file") - func main() { - flag.Parse() - - if *configFile != "" { - setup := config.ReadSetup(*configFile) - - clientTo := utils.ClientRPC(setup.AddrTo) - clientFrom := utils.ClientRPC(setup.AddrFrom) - - // Compile contracts to use in sending transactions - // Validation := contract.CompileContract("Validation") - // Function := contract.CompileContract("Function") - // Trigger := contract.CompileContract("Trigger") - printInfo(setup) - - // Launch the CLI - cli.Launch( - setup, - clientTo, - clientFrom, - ) - - } else { - fmt.Print("Error: empty config!\n") - os.Exit(3) - } - + // Launch the CLI + printWelcome() + cli.Launch() } -func printInfo(setup config.Setup) { +func printWelcome() { // display welcome info. fmt.Println("===============================================================") fmt.Println("Ion Command Line Interface\n") - fmt.Println("RPC Client [TO]:") - fmt.Println("\tListening on:\t\t" + setup.AddrTo) - fmt.Println("\tUser Account:\t\t" + setup.AccountTo) - fmt.Println("\tRPC ChainId:\t\t" + setup.ChainId) - fmt.Println("\nRPC Client [FROM]:") - fmt.Println("\tListening on:\t\t" + setup.AddrFrom) - fmt.Println("\tUser Account:\t\t" + setup.AccountFrom) + fmt.Println("Use 'help' to list commands") fmt.Println("===============================================================") } From a4ece81f0c0573e4126ac662210306c7da6f7625 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 28 Nov 2018 18:51:41 +0000 Subject: [PATCH 170/203] Fixed formatting --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6b2a487..22fbe17 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,14 @@ Clone the repository and ensure that all the components work out of the box. Run: ``` -$ npm install``` +$ npm install ``` -$ npm run testrpc``` ``` -$ npm run test``` +$ npm run testrpc +``` +``` +$ npm run test +``` to test the full stack of contracts including our example flow. @@ -133,4 +136,4 @@ Each system requires a mechanism to be able to prove the correctness/validity of Each system holds its data in different formats, and subsequently proving that the data exists would be different. Thus a different storage contracts must be written that decode and store any arbitrary data formats for use on any other system. For example, proving a transaction exists in an Ethereum block is different from proving a UTXO in a Bitcoin block. -With the above, we aim to expand our system-specific implementations for verification of both data validity and state transitions to allow the easier development of smart contracts using these interfaces. \ No newline at end of file +With the above, we aim to expand our system-specific implementations for verification of both data validity and state transitions to allow the easier development of smart contracts using these interfaces. From 42e005f6568ab4cdf0c07fd9c16757cd9e6a30fa Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 28 Nov 2018 18:54:00 +0000 Subject: [PATCH 171/203] Formatting --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 22fbe17..6a1ff36 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ Ideally we envision Ion to evolve to become a library of tools that developers c ### Contents * [Getting Started](#getting-started) -* [Interoperate with Rinkeby!](#interoperate-with-rinkeby-) +* [Interoperate with Rinkeby!](#interoperate-with-rinkeby) * [Develop on Ion](#develop-on-ion) * [Ion CLI](#ion-cli) -* [Contribute!](#contribute-) +* [Contribute!](#contribute) ## Getting Started @@ -116,7 +116,7 @@ Study the tests in the repository to discover how we've unit-tested the entire i ## Ion CLI -The Command-Line Interface reference can be found [here]() +The Command-Line Interface reference can be found [here](./ion-cli) ## How Ion works From 691b2a81819756e348bfd3f4574027831c10f996 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 28 Nov 2018 18:55:12 +0000 Subject: [PATCH 172/203] Formatting --- ion-cli/README.md | 51 +++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/ion-cli/README.md b/ion-cli/README.md index eacd918..6f28a66 100644 --- a/ion-cli/README.md +++ b/ion-cli/README.md @@ -17,7 +17,8 @@ addAccount use: addAccount [name] [path/to/keystore] Adds an account to be referenced by given name that can be used to sign transactions from. Takes a name (string) that can be any chosen name, and a path to a keystore file containing an encrypted private key. -Accounts are not persisted between sessions.``` +Accounts are not persisted between sessions. +``` ``` addContractInstance use: addContractInstance [name] [path/to/solidity/contract] description: Compiles a contract for use @@ -26,9 +27,11 @@ Adds a compiled contract instance. This contract instance can be deployed to a c to make function calls to deployed contracts. Takes any chosen name (string) and a path to the Solidity contract to be compiled. -Contracts are not persisted between sessions.``` +Contracts are not persisted between sessions. +``` +``` +clear clear the screen ``` -clear clear the screen``` ``` connectToClient use: connectToClient [rpc url] description: Connects to an RPC client to be used @@ -36,21 +39,25 @@ connectToClient use: connectToClient [rpc url] Connects to an Ethereum blockchain specified by a given url. This chain will be used for contract deployment, calls, chain data etc. unless specified otherwise. -Only one client can be connected at a time.``` +Only one client can be connected at a time. +``` ``` deployContract use: deployContract [contract name] [account name] [gas limit] description: Deploys specified contract instance to connected client Deploys a specified compiled contract instance by name from the specified account name to the connected -client. Requires gas limit to be provided.``` +client. Requires gas limit to be provided. +``` +``` +exit exit the program ``` -exit exit the program``` ``` getBlockByHash use: getBlockByHash [optional rpc url] [hash] description: Returns block header specified by hash from connected client or from specific endpoint -Retrieves the block header from the connected or specified endpoint at given block hash.``` +Retrieves the block header from the connected or specified endpoint at given block hash. +``` ``` getBlockByHash_Clique use: getBlockByHash_Clique [optional rpc url] [hash] description: Returns signed and unsigned RLP-encoded block headers by @@ -59,13 +66,15 @@ getBlockByHash_Clique use: getBlockByHash_Clique [optional rpc url] [has Retrieves RLP-encoded block headers that have been signed and unsigned by validators of the Clique mechanism specified by block hash. This is used to be submitted to the Clique validation contract -scheme for interoperation with Clique proof-of-authority chains.``` +scheme for interoperation with Clique proof-of-authority chains. +``` ``` getBlockByNumber use: getBlockByNumber [optional rpc url] [integer] description: Returns block header specified by height from connected client or from specified endpoint -Retrieves the block header from the connected or specified endpoint at given block number.``` +Retrieves the block header from the connected or specified endpoint at given block number. +``` ``` getBlockByNumber_Clique use: getBlockByNumber_Clique [optional rpc url] [integer] description: Returns signed and unsigned RLP-encoded block headers by @@ -74,7 +83,8 @@ getBlockByNumber_Clique use: getBlockByNumber_Clique [optional rpc url] [i Retrieves RLP-encoded block headers that have been signed and unsigned by validators of the Clique mechanism specified by block number. This is used to be submitted to the Clique validation contract -scheme for interoperation with Clique proof-of-authority chains.``` +scheme for interoperation with Clique proof-of-authority chains. +``` ``` getProof use: getProof [optional rpc url] [Transaction Hash] description: Returns a merkle patricia proof of a specific transaction @@ -82,30 +92,36 @@ getProof use: getProof [optional rpc url] [Transaction Hash Retrieves a merkle patricia trie proof of a transaction in a block. It checks against the Transaction Trie and the Receipt Trie in a block, reconstructs the trie and generates a proof that the specified -transaction exists in the trie and returns the data to verify the proof.``` +transaction exists in the trie and returns the data to verify the proof. +``` ``` getTransactionByHash use: getTransactionByHash [optional rpc url] [hash] description: Returns transaction specified by hash from connected client or specified endpoint -Retrieves the transaction data of a specified transaction by hash.``` +Retrieves the transaction data of a specified transaction by hash. +``` +``` +help display help ``` -help display help``` ``` linkAndDeployContract use: deployContract [contract name] [account name] [gas limit] description: Deploys specified contract instance to connected client -Links any required libraries to a contract instance before deploying to the connect client.``` +Links any required libraries to a contract instance before deploying to the connect client. +``` ``` listAccounts use: listAccounts description: List all added accounts -Lists all added accounts.``` +Lists all added accounts. +``` ``` listContracts use: listContracts description: List compiled contract instances -Lists all added contract instances.``` +Lists all added contract instances. +``` ``` transactionMessage use: transactionMessage [contract name] [function name] [from account name] [deployed contract address] [amount] [gasLimit] description: Calls a contract function as a transaction. @@ -114,4 +130,5 @@ Calls a contract instance function that has been deployed to the connected clien will mutate the world state of the destination chain if the transaction is accepted into a block. Requires gas. -Will be prompted to provide function input parameters.``` \ No newline at end of file +Will be prompted to provide function input parameters. +``` From bc12a4e7c10ca359cd3cc820b5514d94bb84ec3b Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 29 Nov 2018 11:25:24 +0000 Subject: [PATCH 173/203] Updated README --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6a1ff36..6361899 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ # Ion Interoperability Framework The Ion Interoperability Framework is a library that provides an interface for the development of general cross-chain smart contracts. -We strive towards a more interconnected fabric of systems, and to this end, methods for inter-system and cross-chain communications become paramount in facilitating this connected ecosystem. Ion is a system and function-agnostic framework for building cross-interacting smart contracts between blockchains and/or systems. It does not restrict itself to certain methods of interoperation and is not opinionated on what specific functions it should be built for and as such is an open protocol. +## Introduction +We strive towards a more interconnected fabric of systems, and to this end, methods for inter-system and cross-chain communications become paramount in facilitating this fluid ecosystem. + +Ion is a system and function-agnostic framework for building cross-interacting smart contracts between blockchains and/or systems. It does not restrict itself to certain methods of interoperation and is not opinionated on what specific functions it should be built for and as such is an open protocol. Atomic swaps and decentralised exchanges can be built on Ion and facilitate the free movement of value across different blockchains. These are just two of the possible use-cases that can be developed on top of the Ion framework. -Ideally we envision Ion to evolve to become a library of tools that developers can use on any system to build cross-chain smart contracts to interoperate with any other system. +We envision Ion to evolve to become a library of tools that developers can use on any system to build cross-chain smart contracts to interoperate with any other system. ### Contents * [Getting Started](#getting-started) @@ -86,9 +89,27 @@ Develop your own cross-chain smart contracts using the Ion interface! The core of Ion revolves around the concept of dependence on state. As such, to create functional cross-chain smart contracts, the idea is to be able to make the execution of a smart contract function be dependent on some state transition to have occurred. Thus we create smart contracts that perform verification of state transitions before allowing the execution of code and this can be done many ways depending on the systems that intend to interoperate. +This results in a framework that should provide a simple interface to make proofs of state and as such is comprised of two core components: +* State Validation +* State Transition Verification + +#### State Validation + +In order for two systems or chains to interoperate there must be some notion of the passing of state between the systems. The passing of this state ideally must be trustless and thus the State Validation layer handles this. It's purpose is to provide a mechanism by which passed state is checked for validity and correctness. Since we draw dependence on the state of another system to trigger arbitrary code execution we must ensure that any state that is passed is indeed correct. + +#### State Transition Verification + +Once state has been passed from one system to another it can be used as a dependency for code execution. This code execution should have conditions to be contingent on a certain piece of data from another system/chain. In practice this could be checking the balance of an account on another chain or asserting that some transaction has been fulfilled. + +The State Transition Verification layer should provide a mechanism to allow checks to be made against the stored state from another system. These checks should involve discerning and/or confirming a certain piece of data or event in the state of another chain and using the successful verification to trigger the execution of code. + +
      + +The two core layers of the Ion framework will need different implementations for each method/mechanism by which validation and verification can be achieved across two interoperating systems. The two layers, validation and state verification, are analogous to the functions of current systems, consensus and state transition respectively. Thus the Ion framework aims to provide interfaces to make interoperation between any ledger governed by any consensus mechanism with another through the development of such interfaces. + ### Ethereum-Ethereum -With Ethereum, this is done via event consumption. Using the presence of an event in a transaction, we can verify if the expected computation was done and to only do something if the verification succeeds. +With Ethereum, interoperation between chains is mainly a question of validation as they share the EVM. We currently have made an implementation of the Clique proof-of-authority consensus mechanism used by the Rinkeby Testnet for validation. We achieve state verifications via event consumption. Using the presence of an event in a transaction, we can verify if the expected computation was done and to only do something if the verification succeeds. To write a smart contract that depends on particular state transitions there are pre-requisites: * Event Verifier contracts @@ -116,6 +137,8 @@ Study the tests in the repository to discover how we've unit-tested the entire i ## Ion CLI +The Ion Command-Line Interface is a tool built in Golang to provide functions to facilitate the use of the Ion framework. + The Command-Line Interface reference can be found [here](./ion-cli) ## How Ion works @@ -128,12 +151,31 @@ Ion is not a finished project! We would love contributors to help evolve Ion int Functional use-case smart contracts should not live in this repository. Please create use-cases in your own repositories and we'll include a link to them in our Ion-based contract catalogue. -The repository is segmented into two main sections that require work: +The repository is segmented into three main sections that require work: * Validation * Storage +* CLI + +#### Validation Each system requires a mechanism to be able to prove the correctness/validity of any data it holds, and this mechanism must be encoded by a Validation contract. Thus each method by which data could be validated must have its own contract that describes it. For example, to validate blocks from a proof-of-authority chain, we must replicate the verification mechanism of that specific implementation. +Validation contracts for the consensus mechanism of an interoperating chain would be required in order to interact with it. + +These should live in the `contracts/validation/` directory. + +#### Storage + Each system holds its data in different formats, and subsequently proving that the data exists would be different. Thus a different storage contracts must be written that decode and store any arbitrary data formats for use on any other system. For example, proving a transaction exists in an Ethereum block is different from proving a UTXO in a Bitcoin block. -With the above, we aim to expand our system-specific implementations for verification of both data validity and state transitions to allow the easier development of smart contracts using these interfaces. +Storage contracts for the data format and state verification mechanisms of an interoperating chain would be required in order to interact with it. + +These should live in the `contracts/storage/` directory. + +#### CLI + +As the developments of the above two layers progress, there may be requirements to extend the CLI to ease the use of those functions i.e. block retrieval methods, data formatting etc. With that we encourage that the CLI is extended in tandem with additions contributed to the validation or storage sections for processes that may be more cumbersome to perform manually. + + + +With the above, we aim to expand our system-specific implementations for verification of both data validity and state transitions to allow the easier development of smart contracts using these interfaces. \ No newline at end of file From 88b02f5a20bd6b91df8a0bfce35969bee35cd465 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 29 Nov 2018 11:35:33 +0000 Subject: [PATCH 174/203] Removed redundant files --- IonCliScript.txt | 7 ------- Makefile | 1 - 2 files changed, 8 deletions(-) delete mode 100644 IonCliScript.txt delete mode 100644 Makefile diff --git a/IonCliScript.txt b/IonCliScript.txt deleted file mode 100644 index 776b934..0000000 --- a/IonCliScript.txt +++ /dev/null @@ -1,7 +0,0 @@ -registerValidationChain: - chainId: - 0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075 - validators: - 0x42eb768f2244c8811c63729a21a3569731535f06 0x6635f83421bf059cd8111f180f0727128685bae4 0x7ffc57839b00206d1ad20c69a1981b489f772031 0xb279182d99e65703f0076e4812653aab85fca0f0 0xd6ae8250b8348c94847280928c79fb3b63ca453e 0xda35dee8eddeaa556e4c26268463e26fb91ff74f 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91 - genesis: - 0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177 diff --git a/Makefile b/Makefile deleted file mode 100644 index 223f8ae..0000000 --- a/Makefile +++ /dev/null @@ -1 +0,0 @@ -target: ; From b566094b2f1e35e69cee4bff94ac801cfaff99ea Mon Sep 17 00:00:00 2001 From: maxrobot Date: Thu, 29 Nov 2018 13:46:43 +0000 Subject: [PATCH 175/203] Made some changes to the readme --- README.md | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 6361899..d17440d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,24 @@ $ npm run test to test the full stack of contracts including our example flow. -The tests should pass nicely. With that you've just interoperated your test RPC client with the Rinkeby testnet! Our repository includes some example contracts that show you how to build smart contracts that interoperate with another chain and what mechanism that looks like. +The tests should pass as below: +``` + ... + + Check Roots Proof + Gas used to submit check roots proof = 124536 gas + ✓ Successful Check Roots Proof (138ms) + ✓ Fail Roots Proof with wrong chain id (106ms) + ✓ Fail Roots Proof with wrong block hash (100ms) + ✓ Fail Roots Proof with wrong tx nodes (192ms) + ✓ Fail Roots Proof with wrong receipt nodes (132ms) + + + 69 passing (43s) + +``` + +With that you've just interoperated your test RPC client with the Rinkeby testnet! Our repository includes some example contracts that show you how to build smart contracts that interoperate with another chain and what mechanism that looks like. We'll now use these example contracts to show you exactly how interoperation with Rinkeby looks like. @@ -54,14 +71,15 @@ Ethereum Block Store: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` We will deploy our own instance of the `Function.sol` contract and pass proofs to verify a transaction that we will depend on in order to execute a function in the contract. If the proofs verify correctly then the function should emit an event to indicate that it has been executed. Procedure: -1. `./ion-cli` Starts the CLI -2. `>>> connectToClient https://rinkeby.infura.io` Connect to the Rinkeby Testnet -3. `>>> addAccount me /keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. -4. `>>> addContractInstance function ../contracts/functional/Function.sol` Add your functional contract instance which compiles your contract -5. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: +1. `cd ion-cli && make` to build the CLI +2. `./ion-cli` Starts the CLI +3. `>>> connectToClient https://rinkeby.infura.io` Connect to the Rinkeby Testnet +4. `>>> addAccount me /keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. +5. `>>> addContractInstance function ../contracts/functional/Function.sol` Add your functional contract instance which compiles your contract +6. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: * `_storeAddr`: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` * `_verifierAddr`: `0xf973eB920fDB5897d79394F2e49430dCB9aA4ea1` -6. `>>> transactionMessage function verifyAndExecute me 0 gaslimit` Call the function. This requires you to supply the deployed contract instance address. Here you will need to supply the following data as an input to the function when prompted: +7. `>>> transactionMessage function verifyAndExecute me 0 gaslimit` Call the function. This requires you to supply the deployed contract instance address. Here you will need to supply the following data as an input to the function when prompted: * `_chainId`: `0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177` * `_blockHash`: `0xf88ef06bc1a9c60457d8a4b65c4020dae2ef7f3287076a4d2d481a1bcb8e3148` * `_contractEmittedAddress`: `0x5dF43D6eaDc3EE940eCbf66a114486f3eF853da3` @@ -71,7 +89,7 @@ Procedure: * `_receipt`: `0xf90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605` * `_receiptNodes`: `0xf90335f851a08fbb95708b2169b98ca70955d2280ea41a4490918c7097b9fbb0dc02b6c1021d80808080808080a07e520e72a52d285315cad163ae68ff5f5b9d7b2efb8bf38488428249580b8aee8080808080808080f9017180a03f63d06b509ff798f0c456e58402326006f83b1dfbddf00ee61810754489817ca05f0c69a424cccf549fa2a1e460cab220f18238fac997214049480a1c48f320eaa0faee39d4012a0db36c610ac5f41306041dee4488d47bc41242afb40582e2b8ffa0d298be00622dc72ef2d1a2df8a259bcf769d36e4502ef8b1b2dbde2d19736c3ba04f78ffe7b29e2192dee6197eeeb19f56801dfe092c3fc485f8e2ca0141dddb1ca0e1c200d90941dbf37ac5d0f37e40479de4b2fe1a0a1b398c9f64cf80d6010eb0a034d7af644f909a94dc41bfa08ae9d0ea1c0d053e0c520378e8a5f2efd6422b62a068858e77fadd9ae975d9aff2e23e40b0f50dab934654a261930a40101ce370a0a068be4c01c98beead34d05516b5236e6196d85125b89e2632f23bdf16e7b16fe4a09f0c3ad7917f3f28a66d151270d2cd4ece50fecb2bd769c38512f1e9c5f9355ea05e1856c7908a4428edb582898261e563b2356fa3d1134357b47799a3e470bcc18080808080f9016b20b90167f90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605` * `_expectedAddress`: `0xb8844cf76df596e746f360957aa3af954ef51605` -7. Success! The transaction should have been created and sent. Check on [Etherscan](https://rinkeby.etherscan.io/address/0xb8844cf76df596e746f360957aa3af954ef51605) (or any other method) whether the transaction was successful or not. It should have succeeded! +8. Success! The transaction should have been created and sent. Check on [Etherscan](https://rinkeby.etherscan.io/address/0xb8844cf76df596e746f360957aa3af954ef51605) (or any other method) whether the transaction was successful or not. It should have succeeded! ### Try out your own functions! @@ -93,6 +111,8 @@ This results in a framework that should provide a simple interface to make proof * State Validation * State Transition Verification +The two core layers of the Ion framework will need different implementations for each method/mechanism by which validation and verification can be achieved across two interoperating systems. The two layers, validation and state verification, are analogous to the functions of current systems, consensus and state transition respectively. Thus the Ion framework aims to provide interfaces to make interoperation between any ledger governed by any consensus mechanism with another through the development of such interfaces. + #### State Validation In order for two systems or chains to interoperate there must be some notion of the passing of state between the systems. The passing of this state ideally must be trustless and thus the State Validation layer handles this. It's purpose is to provide a mechanism by which passed state is checked for validity and correctness. Since we draw dependence on the state of another system to trigger arbitrary code execution we must ensure that any state that is passed is indeed correct. @@ -103,11 +123,8 @@ Once state has been passed from one system to another it can be used as a depend The State Transition Verification layer should provide a mechanism to allow checks to be made against the stored state from another system. These checks should involve discerning and/or confirming a certain piece of data or event in the state of another chain and using the successful verification to trigger the execution of code. -
      - -The two core layers of the Ion framework will need different implementations for each method/mechanism by which validation and verification can be achieved across two interoperating systems. The two layers, validation and state verification, are analogous to the functions of current systems, consensus and state transition respectively. Thus the Ion framework aims to provide interfaces to make interoperation between any ledger governed by any consensus mechanism with another through the development of such interfaces. -### Ethereum-Ethereum +### Interoperating Betweeen Ethereum Chains With Ethereum, interoperation between chains is mainly a question of validation as they share the EVM. We currently have made an implementation of the Clique proof-of-authority consensus mechanism used by the Rinkeby Testnet for validation. We achieve state verifications via event consumption. Using the presence of an event in a transaction, we can verify if the expected computation was done and to only do something if the verification succeeds. @@ -143,11 +160,11 @@ The Command-Line Interface reference can be found [here](./ion-cli) ## How Ion works -Please see our Wiki for more detailed information about the design philosophy of Ion. +Please see our [wiki](https://github.com/clearmatics/ion/wiki) for more detailed information about the design philosophy of Ion. # Contribute! -Ion is not a finished project! We would love contributors to help evolve Ion into a universal framework for interoperability. +We would love contributors to help evolve Ion into a universal framework for interoperability. Functional use-case smart contracts should not live in this repository. Please create use-cases in your own repositories and we'll include a link to them in our Ion-based contract catalogue. From d63be5c504a7ef9db9a7f33cbe9f205936a28298 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 29 Nov 2018 17:52:06 +0000 Subject: [PATCH 176/203] Updated better formatted tutorial data --- README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d17440d..a21dbfc 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,19 @@ Procedure: * `_blockHash`: `0xf88ef06bc1a9c60457d8a4b65c4020dae2ef7f3287076a4d2d481a1bcb8e3148` * `_contractEmittedAddress`: `0x5dF43D6eaDc3EE940eCbf66a114486f3eF853da3` * `_path`: `0x04` - * `_tx`: `0xf86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5` - * `_txNodes`: `0xf90236f851a0c478a441c408d00ad410c89a76a635913325eb62a8650ccbc96e8998d50e36dc80808080808080a0edb4c44cbd3957a9226f30b982449d487ff09ff0e933a25f1c005d9df93289c38080808080808080f9017180a07ad13782edc2465b8d6c914d6a18368597b6c906b420d5e3a3dd5dbc408166fba0600296a0213fdce5c37d0520f8e23c32c90bad0e8d9163edb6357fe794546e09a05e5cdcbc193fe8a2966f8d5ecc6d94bd527c37b3f6ae0a3530c9f22cd8efc1b4a09fcfbbffd3fc9b6d7bfc57ec78811f425a24c3828d2ac203c06c7540dd382514a0a0b78e007d6cbcd9fd048ebc6397ca0d067397fb5d61f32fdc118377eaf1039ba032a122caf55ecfa596d4671830e058d6116902ada20591c72f43b299d6b0cb95a06c1f1b6f656336723110875d56d38470520fc82eea9939956ea7c77cd98de7e4a0bb2cffa7c59f46bfadcb40f32a8294ed45c991e6b6e858fc1a81c1ae8e546800a0916fe7ee83eed2a2864dcb5989522af36983674b9a89b8ab856f0e92236383a7a0fa44c96e10751887a97d8855c941805d5de5a7bbb31dfbcdb7100144d35ac4cca0c43a7ef5f5eb44ddd864b3fb9e7be9953e49c5ca089c034175d98b80e5f461718080808080f86d20b86af86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5` - * `_receipt`: `0xf90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605` - * `_receiptNodes`: `0xf90335f851a08fbb95708b2169b98ca70955d2280ea41a4490918c7097b9fbb0dc02b6c1021d80808080808080a07e520e72a52d285315cad163ae68ff5f5b9d7b2efb8bf38488428249580b8aee8080808080808080f9017180a03f63d06b509ff798f0c456e58402326006f83b1dfbddf00ee61810754489817ca05f0c69a424cccf549fa2a1e460cab220f18238fac997214049480a1c48f320eaa0faee39d4012a0db36c610ac5f41306041dee4488d47bc41242afb40582e2b8ffa0d298be00622dc72ef2d1a2df8a259bcf769d36e4502ef8b1b2dbde2d19736c3ba04f78ffe7b29e2192dee6197eeeb19f56801dfe092c3fc485f8e2ca0141dddb1ca0e1c200d90941dbf37ac5d0f37e40479de4b2fe1a0a1b398c9f64cf80d6010eb0a034d7af644f909a94dc41bfa08ae9d0ea1c0d053e0c520378e8a5f2efd6422b62a068858e77fadd9ae975d9aff2e23e40b0f50dab934654a261930a40101ce370a0a068be4c01c98beead34d05516b5236e6196d85125b89e2632f23bdf16e7b16fe4a09f0c3ad7917f3f28a66d151270d2cd4ece50fecb2bd769c38512f1e9c5f9355ea05e1856c7908a4428edb582898261e563b2356fa3d1134357b47799a3e470bcc18080808080f9016b20b90167f90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605` + * `_tx`: + + 0xf86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5 + * `_txNodes`: + + 0xf90236f851a0c478a441c408d00ad410c89a76a635913325eb62a8650ccbc96e8998d50e36dc80808080808080a0edb4c44cbd3957a9226f30b982449d487ff09ff0e933a25f1c005d9df93289c38080808080808080f9017180a07ad13782edc2465b8d6c914d6a18368597b6c906b420d5e3a3dd5dbc408166fba0600296a0213fdce5c37d0520f8e23c32c90bad0e8d9163edb6357fe794546e09a05e5cdcbc193fe8a2966f8d5ecc6d94bd527c37b3f6ae0a3530c9f22cd8efc1b4a09fcfbbffd3fc9b6d7bfc57ec78811f425a24c3828d2ac203c06c7540dd382514a0a0b78e007d6cbcd9fd048ebc6397ca0d067397fb5d61f32fdc118377eaf1039ba032a122caf55ecfa596d4671830e058d6116902ada20591c72f43b299d6b0cb95a06c1f1b6f656336723110875d56d38470520fc82eea9939956ea7c77cd98de7e4a0bb2cffa7c59f46bfadcb40f32a8294ed45c991e6b6e858fc1a81c1ae8e546800a0916fe7ee83eed2a2864dcb5989522af36983674b9a89b8ab856f0e92236383a7a0fa44c96e10751887a97d8855c941805d5de5a7bbb31dfbcdb7100144d35ac4cca0c43a7ef5f5eb44ddd864b3fb9e7be9953e49c5ca089c034175d98b80e5f461718080808080f86d20b86af86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5 + + * `_receipt`: + + 0xf90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605 + * `_receiptNodes`: + + 0xf90335f851a08fbb95708b2169b98ca70955d2280ea41a4490918c7097b9fbb0dc02b6c1021d80808080808080a07e520e72a52d285315cad163ae68ff5f5b9d7b2efb8bf38488428249580b8aee8080808080808080f9017180a03f63d06b509ff798f0c456e58402326006f83b1dfbddf00ee61810754489817ca05f0c69a424cccf549fa2a1e460cab220f18238fac997214049480a1c48f320eaa0faee39d4012a0db36c610ac5f41306041dee4488d47bc41242afb40582e2b8ffa0d298be00622dc72ef2d1a2df8a259bcf769d36e4502ef8b1b2dbde2d19736c3ba04f78ffe7b29e2192dee6197eeeb19f56801dfe092c3fc485f8e2ca0141dddb1ca0e1c200d90941dbf37ac5d0f37e40479de4b2fe1a0a1b398c9f64cf80d6010eb0a034d7af644f909a94dc41bfa08ae9d0ea1c0d053e0c520378e8a5f2efd6422b62a068858e77fadd9ae975d9aff2e23e40b0f50dab934654a261930a40101ce370a0a068be4c01c98beead34d05516b5236e6196d85125b89e2632f23bdf16e7b16fe4a09f0c3ad7917f3f28a66d151270d2cd4ece50fecb2bd769c38512f1e9c5f9355ea05e1856c7908a4428edb582898261e563b2356fa3d1134357b47799a3e470bcc18080808080f9016b20b90167f90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605 * `_expectedAddress`: `0xb8844cf76df596e746f360957aa3af954ef51605` 8. Success! The transaction should have been created and sent. Check on [Etherscan](https://rinkeby.etherscan.io/address/0xb8844cf76df596e746f360957aa3af954ef51605) (or any other method) whether the transaction was successful or not. It should have succeeded! @@ -195,4 +204,4 @@ As the developments of the above two layers progress, there may be requirements -With the above, we aim to expand our system-specific implementations for verification of both data validity and state transitions to allow the easier development of smart contracts using these interfaces. \ No newline at end of file +With the above, we aim to expand our system-specific implementations for verification of both data validity and state transitions to allow the easier development of smart contracts using these interfaces. From ca76847c5a04ce8226d5a29ba9d2335a410a2122 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 30 Nov 2018 11:36:50 +0000 Subject: [PATCH 177/203] Fixed clique test bug where block decoding was attmpted before a block was retrieved. Tests should now pass. --- test/clique.js | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/test/clique.js b/test/clique.js index 01c34f6..d52a0f5 100644 --- a/test/clique.js +++ b/test/clique.js @@ -73,11 +73,11 @@ contract('Clique.js', (accounts) => { const watchEvent = (eventObj) => new Promise((resolve,reject) => eventObj.watch((error,event) => error ? reject(error) : resolve(event))); - // Fetch genesis from testrpc - const genesisBlock = rinkeby.eth.getBlock(0); - const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); - const GENESIS_HASH = genesisBlock.hash; - + // Fetch genesis from rinkeby + let genesisBlock; + let VALIDATORS; + let GENESIS_HASH; + let ion; let clique; let storage; @@ -86,6 +86,10 @@ contract('Clique.js', (accounts) => { ion = await MockIon.new(DEPLOYEDCHAINID); clique = await Clique.new(ion.address); storage = await MockStorage.new(ion.address); + + genesisBlock = await await rinkeby.eth.getBlock(0); + VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + GENESIS_HASH = genesisBlock.hash; }) it('Deploy Contract', async () => { @@ -138,7 +142,7 @@ contract('Clique.js', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby - const block = rinkeby.eth.getBlock(1); + const block = await rinkeby.eth.getBlock(1); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -170,7 +174,7 @@ contract('Clique.js', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby - const block = rinkeby.eth.getBlock(1); + const block = await rinkeby.eth.getBlock(1); // Alter txHashin the unsigned header concatenation const rlpHeaders = encoder.encodeBlockHeader(block); @@ -228,7 +232,7 @@ contract('Clique.js', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from testrpc - const block = web3.eth.getBlock(1); + const block = await rinkeby.eth.getBlock(1); const rlpHeaders = encoder.encodeBlockHeader(block); @@ -241,7 +245,7 @@ contract('Clique.js', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from testrpc - const block = rinkeby.eth.getBlock(1); + const block = await rinkeby.eth.getBlock(1); const rlpHeaders = encoder.encodeBlockHeader(block); @@ -273,7 +277,7 @@ contract('Clique.js', (accounts) => { assert.equal(voteProposal, 0); // Fetch block 873982 from rinkeby - let block = rinkeby.eth.getBlock(873982); + let block = await rinkeby.eth.getBlock(873982); let rlpHeaders = encoder.encodeBlockHeader(block); // Submit block should succeed @@ -281,7 +285,7 @@ contract('Clique.js', (accounts) => { console.log("\tGas used to submit block 873982 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); // Fetch block 873983 from rinkeby - block = rinkeby.eth.getBlock(873983); + block = await rinkeby.eth.getBlock(873983); rlpHeaders = encoder.encodeBlockHeader(block); // Submit block should succeed @@ -295,7 +299,7 @@ contract('Clique.js', (accounts) => { assert.equal(voteProposal, 1); // Fetch block 873984 from rinkeby - block = rinkeby.eth.getBlock(873984); + block = await rinkeby.eth.getBlock(873984); rlpHeaders = encoder.encodeBlockHeader(block); // Submit block should succeed @@ -303,7 +307,7 @@ contract('Clique.js', (accounts) => { console.log("\tGas used to submit block 873984 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); // Fetch block 873985 from rinkeby - block = rinkeby.eth.getBlock(873985); + block = await rinkeby.eth.getBlock(873985); rlpHeaders = encoder.encodeBlockHeader(block); // Submit block should succeed @@ -311,7 +315,7 @@ contract('Clique.js', (accounts) => { console.log("\tGas used to submit block 873985 = " + validationReceipt.receipt.gasUsed.toString() + " gas"); // Fetch block 873986 from rinkeby - block = rinkeby.eth.getBlock(873986); + block = await rinkeby.eth.getBlock(873986); rlpHeaders = encoder.encodeBlockHeader(block); // Submit block should succeed From f910901c6a2351a8b7e9402eadd604e4da208238 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 30 Nov 2018 11:43:46 +0000 Subject: [PATCH 178/203] Fixed integration tests where block was attempted to be parsed before retrieval. Modified PatriciaTrieTest to handle internal functions. Removed clashing node dependency. --- package.json | 3 +- test/PatriciaTrieTest.sol | 7 +--- test/integration-clique_ethereum.js | 50 ++++++++++++++++------------- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index f41f2c2..bdbd79f 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "rlp": "^2.0.0", "solc": "^0.4.25", "solhint": "^1.1.10", - "solidity-coverage": "^0.5.0 ", "truffle-assertions": "^0.6.3", "web3-eth-accounts": "^1.0.0-beta.34" }, @@ -30,7 +29,7 @@ "chai-bignumber": "^2.0.2", "ganache-cli": "^6.0.0", "json-bigint-string": "^1.0.0", - "solidity-coverage": "^0.4.0", + "solidity-coverage": "^0.5.0", "truffle": "^4.1.7", "web3-eth-abi": "^1.0.0-beta.33", "web3-utils": "^1.0.0-beta.33" diff --git a/test/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol index 61239b9..441d909 100644 --- a/test/PatriciaTrieTest.sol +++ b/test/PatriciaTrieTest.sol @@ -1,15 +1,10 @@ pragma solidity ^0.4.23; import "truffle/Assert.sol"; -import "truffle/DeployedAddresses.sol"; import "../contracts/libraries/PatriciaTrie.sol"; contract PatriciaTrieTest { - PatriciaTrie instance; - - constructor() public { - instance = PatriciaTrie(DeployedAddresses.PatriciaTrie()); - } + constructor() public {} function testSucceedVerifyNestedNodes() returns (bool) { bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; diff --git a/test/integration-clique_ethereum.js b/test/integration-clique_ethereum.js index eb54b45..c884d36 100644 --- a/test/integration-clique_ethereum.js +++ b/test/integration-clique_ethereum.js @@ -159,9 +159,9 @@ const TRIG_GENESIS_HASH = TESTBLOCK.parentHash; contract('Clique-Ethereum Integration', (accounts) => { - const genesisBlock = rinkeby.eth.getBlock(0); - const VALIDATORS = encoder.extractValidators(genesisBlock.extraData); - const GENESIS_HASH = genesisBlock.hash; + let genesisBlock; + let VALIDATORS; + let GENESIS_HASH; let ion; let clique; @@ -171,6 +171,10 @@ contract('Clique-Ethereum Integration', (accounts) => { ion = await Ion.new(DEPLOYEDCHAINID); clique = await Clique.new(ion.address); storage = await EthereumStore.new(ion.address); + + genesisBlock = await rinkeby.eth.getBlock(0); + VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + GENESIS_HASH = genesisBlock.hash; }) describe('Register Clique Module', () => { @@ -223,7 +227,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby - const block = rinkeby.eth.getBlock(1); + const block = await rinkeby.eth.getBlock(1); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -244,7 +248,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -265,7 +269,7 @@ contract('Clique-Ethereum Integration', (accounts) => { // await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 1 from rinkeby - const block = rinkeby.eth.getBlock(1); + const block = await rinkeby.eth.getBlock(1); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -279,7 +283,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); // Fetch block 2 from rinkeby instead of block 1 - const block = rinkeby.eth.getBlock(2); + const block = await rinkeby.eth.getBlock(2); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -290,7 +294,7 @@ contract('Clique-Ethereum Integration', (accounts) => { it('Fail Add Block from non-clique', async () => { // Fetch block 1 from rinkeby - const block = rinkeby.eth.getBlock(1); + const block = await rinkeby.eth.getBlock(1); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -307,7 +311,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -330,7 +334,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -352,7 +356,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -374,7 +378,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -398,7 +402,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -421,7 +425,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -443,7 +447,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -465,7 +469,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -489,7 +493,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -512,7 +516,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -535,7 +539,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -558,7 +562,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -581,7 +585,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -614,7 +618,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); @@ -643,7 +647,7 @@ contract('Clique-Ethereum Integration', (accounts) => { await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); // Fetch block 2657422 from rinkeby - const block = rinkeby.eth.getBlock(TESTBLOCK.number); + const block = await rinkeby.eth.getBlock(TESTBLOCK.number); const rlpHeaders = encoder.encodeBlockHeader(block); const signedHeaderHash = Web3Utils.sha3(rlpHeaders.signed); From 88e30e84e484adb271b588eb2f35c7a0cdef08ad Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 30 Nov 2018 11:46:00 +0000 Subject: [PATCH 179/203] Removed eth-proof --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index bdbd79f..332fa07 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", - "eth-proof": "git+https://github.com/Shirikatsu/eth-proof.git#log-encoding", "ethereumjs-block": "^2.0.0", "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", From af6367dc29df91fc930608ea372eaf2ba2fc6967 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 30 Nov 2018 11:55:34 +0000 Subject: [PATCH 180/203] Added missing dependencies --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 332fa07..dc6aa6d 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", + "bignumber.js": "^8.0.1", "ethereumjs-block": "^2.0.0", "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", @@ -30,6 +31,7 @@ "json-bigint-string": "^1.0.0", "solidity-coverage": "^0.5.0", "truffle": "^4.1.7", + "web3": "^1.0.0-beta.33", "web3-eth-abi": "^1.0.0-beta.33", "web3-utils": "^1.0.0-beta.33" }, From 45938e8cf89aa92b161f247f56502eafe1f2e07b Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 30 Nov 2018 18:07:47 +0000 Subject: [PATCH 181/203] Added node-gyp to resolve web3 dependency issues --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index dc6aa6d..b55209e 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "ethereumjs-block": "^2.0.0", "ethereumjs-tx": "^1.3.5", "merkle-patricia-tree": "^2.3.1", + "node-gyp": "^3.8.0", "rlp": "^2.0.0", "solc": "^0.4.25", "solhint": "^1.1.10", From 746633430b13b9cdc378be44f200f8796ea5bec4 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 30 Nov 2018 18:19:55 +0000 Subject: [PATCH 182/203] Updated travis to run testrpc before initiating tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b0bd376..ead9718 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ matrix: script: - npm install + - npm run testrpc - npm run test before_install: From a11cd4c923fccca0057599ba9be886a530c2d36c Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 30 Nov 2018 18:27:13 +0000 Subject: [PATCH 183/203] Run testrpc before script --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ead9718..573ac9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,12 @@ matrix: - name: "Javascript Contract Tests" services: - docker - - script: + + before_script: - npm install - - npm run testrpc + - npm run testrpc & + + script: - npm run test before_install: From 568845cbbd3582dc3c9c01a62a60e89bbe9705f8 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 5 Dec 2018 17:17:21 +0000 Subject: [PATCH 184/203] Changed reference to solidity args to fork of geth --- ion-cli/Gopkg.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ion-cli/Gopkg.toml b/ion-cli/Gopkg.toml index 1148bae..7829949 100644 --- a/ion-cli/Gopkg.toml +++ b/ion-cli/Gopkg.toml @@ -34,8 +34,8 @@ version = "1.8.13" [[constraint]] - branch = "solidity-compiler-addargs" - name = "github.com/clearmatics/autonity" + branch = "solidity-compiler-args" + name = "github.com/Shirikatsu/go-ethereum" [[constraint]] name = "github.com/stretchr/testify" From 6865a78f86d4c8a9eb1a416c84183e2d19225b34 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Wed, 5 Dec 2018 17:26:09 +0000 Subject: [PATCH 185/203] Changed reference to go-ethereum --- ion-cli/Gopkg.toml | 2 +- ion-cli/contracts/contract.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ion-cli/Gopkg.toml b/ion-cli/Gopkg.toml index 1148bae..8ab9345 100644 --- a/ion-cli/Gopkg.toml +++ b/ion-cli/Gopkg.toml @@ -35,7 +35,7 @@ [[constraint]] branch = "solidity-compiler-addargs" - name = "github.com/clearmatics/autonity" + name = "github.com/Shirikatsu/go-ethereum" [[constraint]] name = "github.com/stretchr/testify" diff --git a/ion-cli/contracts/contract.go b/ion-cli/contracts/contract.go index e4ab925..8b6a787 100644 --- a/ion-cli/contracts/contract.go +++ b/ion-cli/contracts/contract.go @@ -16,7 +16,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/clearmatics/autonity/common/compiler" + "github.com/Shirikatsu/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" ) From 6b91ed2c2baa7678257362a514209fabf81b6f08 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 10:58:35 +0000 Subject: [PATCH 186/203] Updated gopkg to point to master of fork including compiler updates --- ion-cli/Gopkg.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion-cli/Gopkg.toml b/ion-cli/Gopkg.toml index 7829949..e5da473 100644 --- a/ion-cli/Gopkg.toml +++ b/ion-cli/Gopkg.toml @@ -34,7 +34,7 @@ version = "1.8.13" [[constraint]] - branch = "solidity-compiler-args" + branch = "master" name = "github.com/Shirikatsu/go-ethereum" [[constraint]] From a83d1100f308aeb9fab097ec5f44c288659cec9a Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 11:12:43 +0000 Subject: [PATCH 187/203] Refactored non cli commands into core.go. Removed redundant tests. --- ion-cli/cli/cli.go | 485 ------------------------- ion-cli/cli/core.go | 500 ++++++++++++++++++++++++++ ion-cli/contracts/contract_test.go | 141 -------- ion-cli/contracts/flow_test.go | 249 ------------- ion-cli/contracts/raw_example_test.go | 364 ------------------- 5 files changed, 500 insertions(+), 1239 deletions(-) create mode 100644 ion-cli/cli/core.go delete mode 100644 ion-cli/contracts/contract_test.go delete mode 100644 ion-cli/contracts/flow_test.go delete mode 100644 ion-cli/contracts/raw_example_test.go diff --git a/ion-cli/cli/cli.go b/ion-cli/cli/cli.go index 87378f4..e3234b2 100644 --- a/ion-cli/cli/cli.go +++ b/ion-cli/cli/cli.go @@ -4,23 +4,18 @@ package cli import ( "context" "fmt" - "encoding/hex" "math/big" "strconv" "errors" "strings" - "reflect" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/abiosoft/ishell" "github.com/clearmatics/ion/ion-cli/config" contract "github.com/clearmatics/ion/ion-cli/contracts" - "github.com/clearmatics/ion/ion-cli/utils" ) // Launch - definition of commands and creates the interface @@ -646,484 +641,4 @@ func Launch() { }) shell.Run() -} - -func getClient(url string) (*EthClient, error) { - rpc := utils.ClientRPC(url) - eth := ethclient.NewClient(rpc) - - client := EthClient{client: eth, rpcClient: rpc, url: url} - - _, _, err := getBlockByNumber(&client, "0") - - return &client, err -} - -func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName string) (args []interface{}, err error) { - var inputParameters abi.Arguments - if methodName != "" { - inputParameters = abiStruct.Methods[methodName].Inputs - } else { - inputParameters = abiStruct.Constructor.Inputs - } - - c.ShowPrompt(false) - defer c.ShowPrompt(true) - - for i := 0; i < len(inputParameters); i++ { - argument := inputParameters[i] - c.Printf("Enter input data for parameter %s:\n", argument.Name) - - input := c.ReadLine() - - // bytes = []byte{} argument type = slice, no element, type equates to []uint8 - // byte[] = [][1]byte{} argument type = slice, element type = array, type equates to [][1]uint8 - // byte = bytes1 - // bytesn = [n]byte{} 0 < n < 33, argument type = array, no element, type equates to [n]uint8 - // bytesn[] = [][n]byte{} argument type = slice, element type = array, type equares to [][n]uint8 - // bytesn[m] = [m][n]byte{} argument type = array, element type = array, type equates to [m][n]uint8 - // Many annoying cases of byte arrays - - if argument.Type.Kind == reflect.Array || argument.Type.Kind == reflect.Slice { - c.Println("Argument is array\n") - - // One dimensional byte array - // Accepts all byte arrays as hex string with pre-pended '0x' only - if argument.Type.Elem == nil { - if argument.Type.Type == reflect.TypeOf(common.Address{}) { - // address solidity type - item, err := utils.ConvertToType(input, &argument.Type) - if err != nil { - c.Err(err) - } - args = append(args, item) - continue - } else if argument.Type.Type == reflect.TypeOf([]byte{}) { - // bytes solidity type - bytes, err := hex.DecodeString(input[2:]) - if err != nil { - c.Err(err) - } - args = append(args, bytes) - continue - } else { - // Fixed byte array of size n; bytesn solidity type - // Any submitted bytes longer than the expected size will be truncated - - bytes, err := hex.DecodeString(input[2:]) - if err != nil { - c.Err(err) - } - - // Fixed sized arrays can't be created with variables as size - switch argument.Type.Size { - case 1: - var byteArray [1]byte - copy(byteArray[:], bytes[:1]) - args = append(args, byteArray) - case 2: - var byteArray [2]byte - copy(byteArray[:], bytes[:2]) - args = append(args, byteArray) - case 3: - var byteArray [3]byte - copy(byteArray[:], bytes[:3]) - args = append(args, byteArray) - case 4: - var byteArray [4]byte - copy(byteArray[:], bytes[:4]) - args = append(args, byteArray) - case 5: - var byteArray [5]byte - copy(byteArray[:], bytes[:5]) - args = append(args, byteArray) - case 6: - var byteArray [6]byte - copy(byteArray[:], bytes[:6]) - args = append(args, byteArray) - case 7: - var byteArray [7]byte - copy(byteArray[:], bytes[:7]) - args = append(args, byteArray) - case 8: - var byteArray [8]byte - copy(byteArray[:], bytes[:8]) - args = append(args, byteArray) - case 9: - var byteArray [9]byte - copy(byteArray[:], bytes[:9]) - args = append(args, byteArray) - case 10: - var byteArray [10]byte - copy(byteArray[:], bytes[:10]) - args = append(args, byteArray) - case 11: - var byteArray [11]byte - copy(byteArray[:], bytes[:11]) - args = append(args, byteArray) - case 12: - var byteArray [12]byte - copy(byteArray[:], bytes[:12]) - args = append(args, byteArray) - case 13: - var byteArray [13]byte - copy(byteArray[:], bytes[:13]) - args = append(args, byteArray) - case 14: - var byteArray [14]byte - copy(byteArray[:], bytes[:14]) - args = append(args, byteArray) - case 15: - var byteArray [15]byte - copy(byteArray[:], bytes[:15]) - args = append(args, byteArray) - case 16: - var byteArray [16]byte - copy(byteArray[:], bytes[:16]) - args = append(args, byteArray) - case 17: - var byteArray [17]byte - copy(byteArray[:], bytes[:17]) - args = append(args, byteArray) - case 18: - var byteArray [18]byte - copy(byteArray[:], bytes[:18]) - args = append(args, byteArray) - case 19: - var byteArray [19]byte - copy(byteArray[:], bytes[:19]) - args = append(args, byteArray) - case 20: - var byteArray [20]byte - copy(byteArray[:], bytes[:20]) - args = append(args, byteArray) - case 21: - var byteArray [21]byte - copy(byteArray[:], bytes[:21]) - args = append(args, byteArray) - case 22: - var byteArray [22]byte - copy(byteArray[:], bytes[:22]) - args = append(args, byteArray) - case 23: - var byteArray [23]byte - copy(byteArray[:], bytes[:23]) - args = append(args, byteArray) - case 24: - var byteArray [24]byte - copy(byteArray[:], bytes[:24]) - args = append(args, byteArray) - case 25: - var byteArray [25]byte - copy(byteArray[:], bytes[:25]) - args = append(args, byteArray) - case 26: - var byteArray [26]byte - copy(byteArray[:], bytes[:26]) - args = append(args, byteArray) - case 27: - var byteArray [27]byte - copy(byteArray[:], bytes[:27]) - args = append(args, byteArray) - case 28: - var byteArray [28]byte - copy(byteArray[:], bytes[:28]) - args = append(args, byteArray) - case 29: - var byteArray [29]byte - copy(byteArray[:], bytes[:29]) - args = append(args, byteArray) - case 30: - var byteArray [30]byte - copy(byteArray[:], bytes[:30]) - args = append(args, byteArray) - case 31: - var byteArray [31]byte - copy(byteArray[:], bytes[:31]) - args = append(args, byteArray) - case 32: - var byteArray [32]byte - copy(byteArray[:], bytes[:32]) - args = append(args, byteArray) - default: - errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %i incompatible", argument.Type.Size) - return nil, errors.New(errStr) - } - continue - } - - } - - array := strings.Split(input, ",") - argSize := argument.Type.Size - size := len(array) - if argSize != 0 { - for size != argSize { - c.Printf("Please enter %i comma-separated list of elements:\n", argSize) - input = c.ReadLine() - array = strings.Split(input, ",") - size = len(array) - } - } - - size = len(array) - - elementType := argument.Type.Elem - - // Elements cannot be kind slice only mean slice - if elementType.Kind == reflect.Array && elementType.Type != reflect.TypeOf(common.Address{}) { - // Is 2D byte array - /* Nightmare to implement, have to account for: - * Slice of fixed byte arrays; bytes32[] in solidity for example, generally bytesn[] - * Fixed array of fixed byte arrays; bytes32[10] in solidity for example bytesn[m] - * Slice or fixed array of string; identical to above two cases as string in solidity is array of bytes - - Since the upper bound of elements in an array in solidity is 2^256-1, and each fixed byte array - has a limit of bytes32 (bytes1, bytes2, ..., bytes31, bytes32), and Golang array creation takes - constant length values, we would have to paste the switch-case containing 1-32 fixed byte arrays - 2^256-1 times to handle every possibility. Since arrays of arrays in seldom used, we have not - implemented it. - */ - - return nil, errors.New("2D Arrays unsupported. Use \"bytes\" instead.") - - - /* - slice := make([]interface{}, 0, size) - err = addFixedByteArrays(array, elementType.Size, slice) - if err != nil { - return nil, err - } - args = append(args, slice) - continue - */ - } else { - switch elementType.Type { - case reflect.TypeOf(bool(false)): - convertedArray := make([]bool, 0, size) - for _, item := range array { - b, err := utils.ConvertToBool(item) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, b) - } - args = append(args, convertedArray) - case reflect.TypeOf(int8(0)): - convertedArray := make([]int8, 0, size) - for _, item := range array { - i, err := strconv.ParseInt(item, 10, 8) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, int8(i)) - } - args = append(args, convertedArray) - case reflect.TypeOf(int16(0)): - convertedArray := make([]int16, 0, size) - for _, item := range array { - i, err := strconv.ParseInt(item, 10, 16) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, int16(i)) - } - args = append(args, convertedArray) - case reflect.TypeOf(int32(0)): - convertedArray := make([]int32, 0, size) - for _, item := range array { - i, err := strconv.ParseInt(item, 10, 32) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, int32(i)) - } - args = append(args, convertedArray) - case reflect.TypeOf(int64(0)): - convertedArray := make([]int64, 0, size) - for _, item := range array { - i, err := strconv.ParseInt(item, 10, 64) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, int64(i)) - } - args = append(args, convertedArray) - case reflect.TypeOf(uint8(0)): - convertedArray := make([]uint8, 0, size) - for _, item := range array { - u, err := strconv.ParseUint(item, 10, 8) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, uint8(u)) - } - args = append(args, convertedArray) - case reflect.TypeOf(uint16(0)): - convertedArray := make([]uint16, 0, size) - for _, item := range array { - u, err := strconv.ParseUint(item, 10, 16) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, uint16(u)) - } - args = append(args, convertedArray) - case reflect.TypeOf(uint32(0)): - convertedArray := make([]uint32, 0, size) - for _, item := range array { - u, err := strconv.ParseUint(item, 10, 32) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, uint32(u)) - } - args = append(args, convertedArray) - case reflect.TypeOf(uint64(0)): - convertedArray := make([]uint64, 0, size) - for _, item := range array { - u, err := strconv.ParseUint(item, 10, 64) - if err != nil { - return nil, err - } - convertedArray = append(convertedArray, uint64(u)) - } - args = append(args, convertedArray) - case reflect.TypeOf(&big.Int{}): - convertedArray := make([]*big.Int, 0, size) - for _, item := range array { - newInt := new(big.Int) - newInt, ok := newInt.SetString(item, 10) - if !ok { - return nil, errors.New("Could not convert string to big.int") - } - convertedArray = append(convertedArray, newInt) - } - args = append(args, convertedArray) - case reflect.TypeOf(common.Address{}): - convertedArray := make([]common.Address, 0, size) - for _, item := range array { - a := common.HexToAddress(item) - convertedArray = append(convertedArray, a) - } - args = append(args, convertedArray) - default: - errStr := fmt.Sprintf("Type %s not found", elementType.Type) - return nil, errors.New(errStr) - } - } - } else { - switch argument.Type.Kind { - case reflect.String: - args = append(args, input) - case reflect.Bool: - b, err := utils.ConvertToBool(input) - if err != nil { - return nil, err - } - args = append(args, b) - case reflect.Int8: - i, err := strconv.ParseInt(input, 10, 8) - if err != nil { - return nil, err - } - args = append(args, int8(i)) - case reflect.Int16: - i, err := strconv.ParseInt(input, 10, 16) - if err != nil { - return nil, err - } - args = append(args, int16(i)) - case reflect.Int32: - i, err := strconv.ParseInt(input, 10, 32) - if err != nil { - return nil, err - } - args = append(args, int32(i)) - case reflect.Int64: - i, err := strconv.ParseInt(input, 10, 64) - if err != nil { - return nil, err - } - args = append(args, int64(i)) - case reflect.Uint8: - u, err := strconv.ParseUint(input, 10, 8) - if err != nil { - return nil, err - } - args = append(args, uint8(u)) - case reflect.Uint16: - u, err := strconv.ParseUint(input, 10, 16) - if err != nil { - return nil, err - } - args = append(args, uint16(u)) - case reflect.Uint32: - u, err := strconv.ParseUint(input, 10, 32) - if err != nil { - return nil, err - } - args = append(args, uint32(u)) - case reflect.Uint64: - u, err := strconv.ParseUint(input, 10, 64) - if err != nil { - return nil, err - } - args = append(args, uint64(u)) - case reflect.Ptr: - newInt := new(big.Int) - newInt, ok := newInt.SetString(input, 10) - if !ok { - return nil, errors.New("Could not convert string to big.int") - } - if err != nil { - return nil, err - } - args = append(args, newInt) - case reflect.Array: - if argument.Type.Type == reflect.TypeOf(common.Address{}) { - address := common.HexToAddress(input) - args = append(args, address) - } else { - return nil, errors.New("Conversion failed. Item is array type, cannot parse") - } - default: - errStr := fmt.Sprintf("Error, type not found: %s", argument.Type.Kind) - return nil, errors.New(errStr) - } - } - } - - return -} - -func checkClientExists(client *EthClient) bool { - return client != nil -} - -func addContractInstance(pathToContract string, contractName string, contracts map[string]*contract.ContractInstance) (error) { - fmt.Println("Compiling contract...") - compiledContract, err := contract.CompileContractAt(pathToContract) - if err != nil { - return err - } - _, Abi := contract.GetContractBytecodeAndABI(compiledContract) - abistruct, err := abi.JSON(strings.NewReader(Abi)) - if err != nil { - return err - } - fmt.Println("Creating contract instance...") - contracts[contractName] = &contract.ContractInstance{Contract: compiledContract, Abi: &abistruct, Path: pathToContract} - return nil -} - -func strToHex(input string) (output string) { - val, err := strconv.Atoi(input) - if err != nil { - fmt.Println("please input decimal:", err) - return - } - output = strconv.FormatInt(int64(val), 16) - - return "0x" + output } \ No newline at end of file diff --git a/ion-cli/cli/core.go b/ion-cli/cli/core.go new file mode 100644 index 0000000..9386c78 --- /dev/null +++ b/ion-cli/cli/core.go @@ -0,0 +1,500 @@ +package cli + +import ( + "fmt" + "encoding/hex" + "math/big" + "strconv" + "errors" + "strings" + "reflect" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/abiosoft/ishell" + + contract "github.com/clearmatics/ion/ion-cli/contracts" + "github.com/clearmatics/ion/ion-cli/utils" +) + +func getClient(url string) (*EthClient, error) { + rpc := utils.ClientRPC(url) + eth := ethclient.NewClient(rpc) + + client := EthClient{client: eth, rpcClient: rpc, url: url} + + _, _, err := getBlockByNumber(&client, "0") + + return &client, err +} + +func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName string) (args []interface{}, err error) { + var inputParameters abi.Arguments + if methodName != "" { + inputParameters = abiStruct.Methods[methodName].Inputs + } else { + inputParameters = abiStruct.Constructor.Inputs + } + + c.ShowPrompt(false) + defer c.ShowPrompt(true) + + for i := 0; i < len(inputParameters); i++ { + argument := inputParameters[i] + c.Printf("Enter input data for parameter %s:\n", argument.Name) + + input := c.ReadLine() + + // bytes = []byte{} argument type = slice, no element, type equates to []uint8 + // byte[] = [][1]byte{} argument type = slice, element type = array, type equates to [][1]uint8 + // byte = bytes1 + // bytesn = [n]byte{} 0 < n < 33, argument type = array, no element, type equates to [n]uint8 + // bytesn[] = [][n]byte{} argument type = slice, element type = array, type equares to [][n]uint8 + // bytesn[m] = [m][n]byte{} argument type = array, element type = array, type equates to [m][n]uint8 + // Many annoying cases of byte arrays + + if argument.Type.Kind == reflect.Array || argument.Type.Kind == reflect.Slice { + c.Println("Argument is array\n") + + // One dimensional byte array + // Accepts all byte arrays as hex string with pre-pended '0x' only + if argument.Type.Elem == nil { + if argument.Type.Type == reflect.TypeOf(common.Address{}) { + // address solidity type + item, err := utils.ConvertToType(input, &argument.Type) + if err != nil { + c.Err(err) + } + args = append(args, item) + continue + } else if argument.Type.Type == reflect.TypeOf([]byte{}) { + // bytes solidity type + bytes, err := hex.DecodeString(input[2:]) + if err != nil { + c.Err(err) + } + args = append(args, bytes) + continue + } else { + // Fixed byte array of size n; bytesn solidity type + // Any submitted bytes longer than the expected size will be truncated + + bytes, err := hex.DecodeString(input[2:]) + if err != nil { + c.Err(err) + } + + // Fixed sized arrays can't be created with variables as size + switch argument.Type.Size { + case 1: + var byteArray [1]byte + copy(byteArray[:], bytes[:1]) + args = append(args, byteArray) + case 2: + var byteArray [2]byte + copy(byteArray[:], bytes[:2]) + args = append(args, byteArray) + case 3: + var byteArray [3]byte + copy(byteArray[:], bytes[:3]) + args = append(args, byteArray) + case 4: + var byteArray [4]byte + copy(byteArray[:], bytes[:4]) + args = append(args, byteArray) + case 5: + var byteArray [5]byte + copy(byteArray[:], bytes[:5]) + args = append(args, byteArray) + case 6: + var byteArray [6]byte + copy(byteArray[:], bytes[:6]) + args = append(args, byteArray) + case 7: + var byteArray [7]byte + copy(byteArray[:], bytes[:7]) + args = append(args, byteArray) + case 8: + var byteArray [8]byte + copy(byteArray[:], bytes[:8]) + args = append(args, byteArray) + case 9: + var byteArray [9]byte + copy(byteArray[:], bytes[:9]) + args = append(args, byteArray) + case 10: + var byteArray [10]byte + copy(byteArray[:], bytes[:10]) + args = append(args, byteArray) + case 11: + var byteArray [11]byte + copy(byteArray[:], bytes[:11]) + args = append(args, byteArray) + case 12: + var byteArray [12]byte + copy(byteArray[:], bytes[:12]) + args = append(args, byteArray) + case 13: + var byteArray [13]byte + copy(byteArray[:], bytes[:13]) + args = append(args, byteArray) + case 14: + var byteArray [14]byte + copy(byteArray[:], bytes[:14]) + args = append(args, byteArray) + case 15: + var byteArray [15]byte + copy(byteArray[:], bytes[:15]) + args = append(args, byteArray) + case 16: + var byteArray [16]byte + copy(byteArray[:], bytes[:16]) + args = append(args, byteArray) + case 17: + var byteArray [17]byte + copy(byteArray[:], bytes[:17]) + args = append(args, byteArray) + case 18: + var byteArray [18]byte + copy(byteArray[:], bytes[:18]) + args = append(args, byteArray) + case 19: + var byteArray [19]byte + copy(byteArray[:], bytes[:19]) + args = append(args, byteArray) + case 20: + var byteArray [20]byte + copy(byteArray[:], bytes[:20]) + args = append(args, byteArray) + case 21: + var byteArray [21]byte + copy(byteArray[:], bytes[:21]) + args = append(args, byteArray) + case 22: + var byteArray [22]byte + copy(byteArray[:], bytes[:22]) + args = append(args, byteArray) + case 23: + var byteArray [23]byte + copy(byteArray[:], bytes[:23]) + args = append(args, byteArray) + case 24: + var byteArray [24]byte + copy(byteArray[:], bytes[:24]) + args = append(args, byteArray) + case 25: + var byteArray [25]byte + copy(byteArray[:], bytes[:25]) + args = append(args, byteArray) + case 26: + var byteArray [26]byte + copy(byteArray[:], bytes[:26]) + args = append(args, byteArray) + case 27: + var byteArray [27]byte + copy(byteArray[:], bytes[:27]) + args = append(args, byteArray) + case 28: + var byteArray [28]byte + copy(byteArray[:], bytes[:28]) + args = append(args, byteArray) + case 29: + var byteArray [29]byte + copy(byteArray[:], bytes[:29]) + args = append(args, byteArray) + case 30: + var byteArray [30]byte + copy(byteArray[:], bytes[:30]) + args = append(args, byteArray) + case 31: + var byteArray [31]byte + copy(byteArray[:], bytes[:31]) + args = append(args, byteArray) + case 32: + var byteArray [32]byte + copy(byteArray[:], bytes[:32]) + args = append(args, byteArray) + default: + errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %i incompatible", argument.Type.Size) + return nil, errors.New(errStr) + } + continue + } + + } + + array := strings.Split(input, ",") + argSize := argument.Type.Size + size := len(array) + if argSize != 0 { + for size != argSize { + c.Printf("Please enter %i comma-separated list of elements:\n", argSize) + input = c.ReadLine() + array = strings.Split(input, ",") + size = len(array) + } + } + + size = len(array) + + elementType := argument.Type.Elem + + // Elements cannot be kind slice only mean slice + if elementType.Kind == reflect.Array && elementType.Type != reflect.TypeOf(common.Address{}) { + // Is 2D byte array + /* Nightmare to implement, have to account for: + * Slice of fixed byte arrays; bytes32[] in solidity for example, generally bytesn[] + * Fixed array of fixed byte arrays; bytes32[10] in solidity for example bytesn[m] + * Slice or fixed array of string; identical to above two cases as string in solidity is array of bytes + + Since the upper bound of elements in an array in solidity is 2^256-1, and each fixed byte array + has a limit of bytes32 (bytes1, bytes2, ..., bytes31, bytes32), and Golang array creation takes + constant length values, we would have to paste the switch-case containing 1-32 fixed byte arrays + 2^256-1 times to handle every possibility. Since arrays of arrays in seldom used, we have not + implemented it. + */ + + return nil, errors.New("2D Arrays unsupported. Use \"bytes\" instead.") + + + /* + slice := make([]interface{}, 0, size) + err = addFixedByteArrays(array, elementType.Size, slice) + if err != nil { + return nil, err + } + args = append(args, slice) + continue + */ + } else { + switch elementType.Type { + case reflect.TypeOf(bool(false)): + convertedArray := make([]bool, 0, size) + for _, item := range array { + b, err := utils.ConvertToBool(item) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, b) + } + args = append(args, convertedArray) + case reflect.TypeOf(int8(0)): + convertedArray := make([]int8, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 8) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int8(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(int16(0)): + convertedArray := make([]int16, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 16) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int16(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(int32(0)): + convertedArray := make([]int32, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 32) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int32(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(int64(0)): + convertedArray := make([]int64, 0, size) + for _, item := range array { + i, err := strconv.ParseInt(item, 10, 64) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, int64(i)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint8(0)): + convertedArray := make([]uint8, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 8) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint8(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint16(0)): + convertedArray := make([]uint16, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 16) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint16(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint32(0)): + convertedArray := make([]uint32, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 32) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint32(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(uint64(0)): + convertedArray := make([]uint64, 0, size) + for _, item := range array { + u, err := strconv.ParseUint(item, 10, 64) + if err != nil { + return nil, err + } + convertedArray = append(convertedArray, uint64(u)) + } + args = append(args, convertedArray) + case reflect.TypeOf(&big.Int{}): + convertedArray := make([]*big.Int, 0, size) + for _, item := range array { + newInt := new(big.Int) + newInt, ok := newInt.SetString(item, 10) + if !ok { + return nil, errors.New("Could not convert string to big.int") + } + convertedArray = append(convertedArray, newInt) + } + args = append(args, convertedArray) + case reflect.TypeOf(common.Address{}): + convertedArray := make([]common.Address, 0, size) + for _, item := range array { + a := common.HexToAddress(item) + convertedArray = append(convertedArray, a) + } + args = append(args, convertedArray) + default: + errStr := fmt.Sprintf("Type %s not found", elementType.Type) + return nil, errors.New(errStr) + } + } + } else { + switch argument.Type.Kind { + case reflect.String: + args = append(args, input) + case reflect.Bool: + b, err := utils.ConvertToBool(input) + if err != nil { + return nil, err + } + args = append(args, b) + case reflect.Int8: + i, err := strconv.ParseInt(input, 10, 8) + if err != nil { + return nil, err + } + args = append(args, int8(i)) + case reflect.Int16: + i, err := strconv.ParseInt(input, 10, 16) + if err != nil { + return nil, err + } + args = append(args, int16(i)) + case reflect.Int32: + i, err := strconv.ParseInt(input, 10, 32) + if err != nil { + return nil, err + } + args = append(args, int32(i)) + case reflect.Int64: + i, err := strconv.ParseInt(input, 10, 64) + if err != nil { + return nil, err + } + args = append(args, int64(i)) + case reflect.Uint8: + u, err := strconv.ParseUint(input, 10, 8) + if err != nil { + return nil, err + } + args = append(args, uint8(u)) + case reflect.Uint16: + u, err := strconv.ParseUint(input, 10, 16) + if err != nil { + return nil, err + } + args = append(args, uint16(u)) + case reflect.Uint32: + u, err := strconv.ParseUint(input, 10, 32) + if err != nil { + return nil, err + } + args = append(args, uint32(u)) + case reflect.Uint64: + u, err := strconv.ParseUint(input, 10, 64) + if err != nil { + return nil, err + } + args = append(args, uint64(u)) + case reflect.Ptr: + newInt := new(big.Int) + newInt, ok := newInt.SetString(input, 10) + if !ok { + return nil, errors.New("Could not convert string to big.int") + } + if err != nil { + return nil, err + } + args = append(args, newInt) + case reflect.Array: + if argument.Type.Type == reflect.TypeOf(common.Address{}) { + address := common.HexToAddress(input) + args = append(args, address) + } else { + return nil, errors.New("Conversion failed. Item is array type, cannot parse") + } + default: + errStr := fmt.Sprintf("Error, type not found: %s", argument.Type.Kind) + return nil, errors.New(errStr) + } + } + } + + return +} + +func checkClientExists(client *EthClient) bool { + return client != nil +} + +func addContractInstance(pathToContract string, contractName string, contracts map[string]*contract.ContractInstance) (error) { + fmt.Println("Compiling contract...") + compiledContract, err := contract.CompileContractAt(pathToContract) + if err != nil { + return err + } + _, Abi := contract.GetContractBytecodeAndABI(compiledContract) + abistruct, err := abi.JSON(strings.NewReader(Abi)) + if err != nil { + return err + } + fmt.Println("Creating contract instance...") + contracts[contractName] = &contract.ContractInstance{Contract: compiledContract, Abi: &abistruct, Path: pathToContract} + return nil +} + +func strToHex(input string) (output string) { + val, err := strconv.Atoi(input) + if err != nil { + fmt.Println("please input decimal:", err) + return + } + output = strconv.FormatInt(int64(val), 16) + + return "0x" + output +} \ No newline at end of file diff --git a/ion-cli/contracts/contract_test.go b/ion-cli/contracts/contract_test.go deleted file mode 100644 index f15ed10..0000000 --- a/ion-cli/contracts/contract_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd -package contract - -import ( - "bytes" - "context" - "log" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/crypto" -) - -func Test_CompileAndDeployIon(t *testing.T) { - // --------------------------------------------- - // START BLOCKCHAIN SIMULATOR - // --------------------------------------------- - - ctx := context.Background() - initialBalance := big.NewInt(1000000000) - - userAKey, _ := crypto.GenerateKey() - userAddr := crypto.PubkeyToAddress(userAKey.PublicKey) - - // start simulated blockchain - alloc := make(core.GenesisAlloc) - alloc[userAddr] = core.GenesisAccount{ - Balance: initialBalance, - } - blockchain := backends.NewSimulatedBackend(alloc) - - // create a chain id - chainID := crypto.Keccak256Hash([]byte("test argument")) // Ion argument - - // start compile and deploy ion - contractChan := CompileAndDeployIon(ctx, blockchain, userAKey, chainID) - - // commit first block after sent transaction for deployment of patricia trie lib - blockchain.Commit() - // patriciaTrieContractInstance := <-contractChan - <-contractChan - - // commit after transaction for deployment of Ion (with reference to Patricia Trie lib) as been sent - blockchain.Commit() - ionContractInstance := <-contractChan - - // call contract variable - methodName := "chainId" - out := new([32]byte) - CallContract(ctx, blockchain, ionContractInstance.Contract, userAddr, ionContractInstance.Address, methodName, out) - - if !bytes.Equal((*out)[:], chainID.Bytes()) { - t.Fatal("ERROR chainID result from contract call, and sent to contract constructor differ") - } -} - -func Test_RegisterChain(t *testing.T) { - // --------------------------------------------- - // HARD CODED DATA - // --------------------------------------------- - testValidators := []common.Address{ - common.HexToAddress("0x42eb768f2244c8811c63729a21a3569731535f06"), - common.HexToAddress("0x6635f83421bf059cd8111f180f0727128685bae4"), - common.HexToAddress("0x7ffc57839b00206d1ad20c69a1981b489f772031"), - common.HexToAddress("0xb279182d99e65703f0076e4812653aab85fca0f0"), - common.HexToAddress("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), - common.HexToAddress("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), - common.HexToAddress("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), - } - - // check comments on TestCompileAndDeploy() - ctx := context.Background() - initialBalance := big.NewInt(1000000000) - userAKey, _ := crypto.GenerateKey() - userAddr := crypto.PubkeyToAddress(userAKey.PublicKey) - alloc := make(core.GenesisAlloc) - alloc[userAddr] = core.GenesisAccount{ - Balance: initialBalance, - } - blockchain := backends.NewSimulatedBackend(alloc) - var chainID [32]byte - copy(chainID[:], crypto.Keccak256Hash([]byte("DEPLOYEDCHAINID")).Bytes()) - contractChan := CompileAndDeployIon(ctx, blockchain, userAKey, chainID) - blockchain.Commit() - <-contractChan - blockchain.Commit() - ionContractInstance := <-contractChan - - // deploy validation contract - var ionContractAddr [20]byte - copy(ionContractAddr[:], ionContractInstance.Address.Bytes()) - contractChan = CompileAndDeployValidation(ctx, blockchain, userAKey, chainID, ionContractAddr) - blockchain.Commit() - validationContractInstance := <-contractChan - - var chainIDA [32]byte - var validationAddress [20]byte - copy(validationAddress[:], validationContractInstance.Address.Bytes()) - copy(chainIDA[:], crypto.Keccak256Hash([]byte("TESTCHAINID")).Bytes()) - deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") - txRegisterChain := RegisterChain( - ctx, - blockchain, - userAKey, - validationContractInstance.Contract, - validationContractInstance.Address, - chainIDA, - testValidators, - deployedChainID, - ) - blockchain.Commit() - - registerChainReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChain) - if err != nil { - log.Fatal("ERROR while waiting for contract deployment") - } - if registerChainReceipt.Status == 0 { - t.Fatalf("ERROR transaction of RegisterChain failed!: %#v\n", registerChainReceipt) - } - - methodName := "chains" - var isChainRegistered bool - CallContract( - ctx, - blockchain, - validationContractInstance.Contract, - userAddr, - validationContractInstance.Address, - methodName, - &isChainRegistered, - chainID, - ) - - if !isChainRegistered { - t.Log("ERROR expecting value of chains(validation.address) to be true, but it was ", isChainRegistered) - } -} diff --git a/ion-cli/contracts/flow_test.go b/ion-cli/contracts/flow_test.go deleted file mode 100644 index c334936..0000000 --- a/ion-cli/contracts/flow_test.go +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd -package contract - -import ( - "bytes" - "context" - "math/big" - "testing" - - "github.com/clearmatics/ion/ion-cli/utils" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rlp" -) - -// TODO -// avoid having to get data from Rinkeby, make it deploy a trigger function into a PoA chain - -// TestVerifyTx test for the full flow of Ion -func Test_VerifyTx(t *testing.T) { - ctx := context.Background() - - // --------------------------------------------- - // HARD CODED DATA - // --------------------------------------------- - testValidators := []common.Address{ - common.HexToAddress("0x42eb768f2244c8811c63729a21a3569731535f06"), - common.HexToAddress("0x6635f83421bf059cd8111f180f0727128685bae4"), - common.HexToAddress("0x7ffc57839b00206d1ad20c69a1981b489f772031"), - common.HexToAddress("0xb279182d99e65703f0076e4812653aab85fca0f0"), - common.HexToAddress("0xd6ae8250b8348c94847280928c79fb3b63ca453e"), - common.HexToAddress("0xda35dee8eddeaa556e4c26268463e26fb91ff74f"), - common.HexToAddress("0xfc18cbc391de84dbd87db83b20935d3e89f5dd91"), - } - - deployedChainID := common.HexToHash("0xab830ae0774cb20180c8b463202659184033a9f30a21550b89a2b406c3ac8075") - testChainID := common.HexToHash("0x22b55e8a4f7c03e1689da845dd463b09299cb3a574e64c68eafc4e99077a7254") - - urlEventChain := "https://rinkeby.infura.io" - txHashWithEvent := common.HexToHash("0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") - - signer := types.HomesteadSigner{} // blockchain simulater signer is this one - userKey, _ := crypto.GenerateKey() - userAddr := crypto.PubkeyToAddress(userKey.PublicKey) - userIntialBalance := big.NewInt(1000000000) - - // --------------------------------------------- - // GET BLOCK WITH EVENT FROM RINKEBY CHAIN - // --------------------------------------------- - - clientRPC := utils.ClientRPC(urlEventChain) - defer clientRPC.Close() - - blockNumberStr, txTrigger, err := utils.BlockNumberByTransactionHash(ctx, clientRPC, txHashWithEvent) - if err != nil { - t.Fatal("ERROR couldn't find block by tx hash: ", err) - } - - var blockNumber big.Int - blockNumber.SetString((*blockNumberStr)[2:], 16) - - client := ethclient.NewClient(clientRPC) - eventTxBlockNumber := blockNumber - block, err := client.BlockByNumber(ctx, &eventTxBlockNumber) - if err != nil { - t.Fatal("ERROR retrieving block: ", err) - } - - // --------------------------------------------- - // START BLOCKCHAIN SIMULATOR - // --------------------------------------------- - alloc := make(core.GenesisAlloc) - alloc[userAddr] = core.GenesisAccount{Balance: userIntialBalance} - blockchain := backends.NewSimulatedBackend(alloc) - - // --------------------------------------------- - // COMPILE AND DEPLOY ION - // --------------------------------------------- - contractChan := CompileAndDeployIon(ctx, blockchain, userKey, deployedChainID) - blockchain.Commit() - <-contractChan // PatriciaTrie libraryContractInstance - blockchain.Commit() - ionContractInstance := <-contractChan - - // --------------------------------------------- - // COMPILE AND DEPLOY VALIDATION - // --------------------------------------------- - var ionContractAddr [20]byte - copy(ionContractAddr[:], ionContractInstance.Address.Bytes()) - contractChan = CompileAndDeployValidation(ctx, blockchain, userKey, deployedChainID, ionContractAddr) - blockchain.Commit() - validationContractInstance := <-contractChan - - // --------------------------------------------- - // REGISTER CHAIN ON VALIDATION - // --------------------------------------------- - - var genesisHash [32]byte - copy(genesisHash[:], block.ParentHash().Bytes()) - txRegisterChainValidation := RegisterChain( - ctx, - blockchain, - userKey, - validationContractInstance.Contract, - validationContractInstance.Address, - testChainID, - testValidators, - genesisHash, - ) - blockchain.Commit() - registerChainValidationReceipt, err := bind.WaitMined(ctx, blockchain, txRegisterChainValidation) - if err != nil || registerChainValidationReceipt.Status == 0 { - t.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // SUBMIT BLOCK ON VALIDATION - // --------------------------------------------- - blockHeader := block.Header() - extraData := blockHeader.Extra - unsignedExtraData := extraData[:len(extraData)-(64+1)] // 64 bytes + 1 vanity byte - signedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) - blockHeader.Extra = unsignedExtraData - unsignedBlockHeaderRLP, _ := rlp.EncodeToBytes(blockHeader) - txSubmitBlockValidation := SubmitBlock( - ctx, - blockchain, - userKey, - validationContractInstance.Contract, - validationContractInstance.Address, - testChainID, - unsignedBlockHeaderRLP, - signedBlockHeaderRLP, - ) - - blockchain.Commit() - submitBlockValidationReceipt, err := bind.WaitMined(ctx, blockchain, txSubmitBlockValidation) - if err != nil || submitBlockValidationReceipt.Status == 0 { - t.Fatal("ERROR while waiting for contract deployment") - } - - // --------------------------------------------- - // CHECK ROOTS PROOF ON ION - // --------------------------------------------- - blockHash := block.Hash() - blockTransactions := block.Transactions() - txTrie := utils.TxTrie(blockTransactions) - blockReceipts := utils.GetBlockTxReceipts(client, block) - receiptTrie := utils.ReceiptTrie(blockReceipts) - - txKey := []byte{0x01} - txProofArr := utils.Proof(txTrie, txKey) - receiptKey := []byte{0x01} - receiptProofArr := utils.Proof(receiptTrie, receiptKey) - - checkRootsProofIon := TransactionContract( - ctx, - blockchain, - userKey, - ionContractInstance.Contract, - ionContractInstance.Address, - nil, - uint64(3000000), - "CheckRootsProof", - testChainID, - blockHash, - txProofArr, - receiptProofArr, - ) - - blockchain.Commit() - chackRootsProofIonReceipt, err := bind.WaitMined(ctx, blockchain, checkRootsProofIon) - if err != nil || chackRootsProofIonReceipt.Status == 0 { - t.Fatal("ERROR while waiting for contract deployment", err) - } - - // --------------------------------------------- - // COMPILE AND DEPLOY TRIGGER VERIFIER AND CONSUMER FUNCTION - // --------------------------------------------- - contractChan = CompileAndDeployTriggerVerifierAndConsumerFunction( - ctx, - blockchain, - userKey, - ionContractInstance.Address, - ) - blockchain.Commit() - <-contractChan // triggerEventVerifierContractInstance := <-contractChan - blockchain.Commit() - consumerFunctionContractInstance := <-contractChan - - // --------------------------------------------- - // VERIFY FUNCTION EXECUITION - // --------------------------------------------- - triggerCalledBy, _ := types.Sender(signer, txTrigger) - - // Generate the proof - txPath, txValue, txNodes, receiptValue, receiptNodes := utils.GenerateProof( - ctx, - clientRPC, - txHashWithEvent, - ) - - txVerifyAndExecuteFunction := VerifyExecute( - ctx, - blockchain, - userKey, - consumerFunctionContractInstance.Contract, - consumerFunctionContractInstance.Address, - testChainID, - blockHash, - *txTrigger.To(), // TRIG_DEPLOYED_RINKEBY_ADDR, - txPath, // TEST_PATH, - txValue, // TEST_TX_VALUE, - txNodes, // TEST_TX_NODES, - receiptValue, // TEST_RECEIPT_VALUE, - receiptNodes, // TEST_RECEIPT_NODES, - triggerCalledBy, // TRIG_CALLED_BY, - nil, - ) - - blockchain.Commit() - verifyAndExecuteFunctionReceipt, err := bind.WaitMined(ctx, blockchain, txVerifyAndExecuteFunction) - if err != nil || verifyAndExecuteFunctionReceipt.Status == 0 { - t.Logf("\n\n%#v\n\n%#v\n", txTrigger, verifyAndExecuteFunctionReceipt) - t.Fatal("ERROR while waiting for contract deployment", err) - } - - // confirm the Executed event was emited by Consumer Function - eventSignatureHash := crypto.Keccak256Hash([]byte("Executed()")) // Ion argument - - foundExecuted := false - for _, vlog := range verifyAndExecuteFunctionReceipt.Logs { - if len(vlog.Topics) < 1 { - continue - } - foundExecuted = bytes.Equal(vlog.Topics[0].Bytes(), eventSignatureHash.Bytes()) - if foundExecuted { - break - } - } - if !foundExecuted { - t.Fatal("ERROR did not find Executed() event") - } -} diff --git a/ion-cli/contracts/raw_example_test.go b/ion-cli/contracts/raw_example_test.go deleted file mode 100644 index 0706eed..0000000 --- a/ion-cli/contracts/raw_example_test.go +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) 2018 Clearmatics Technologies Ltd -package contract - -import ( - "bytes" - "context" - "encoding/json" - "math/big" - "os" - "regexp" - "strings" - "testing" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/compiler" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" -) - -func TestRawTransactionSimulated(t *testing.T) { - ctx := context.Background() - initialBalance := big.NewInt(1000000000) - - userAKey, _ := crypto.GenerateKey() - userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) - - alloc := make(core.GenesisAlloc) - alloc[userAAddr] = core.GenesisAccount{ - Balance: initialBalance, - } - - blockchain := backends.NewSimulatedBackend(alloc) - - userBKey, _ := crypto.GenerateKey() - userBAddr := crypto.PubkeyToAddress(userBKey.PublicKey) - - // create transaction - // NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) - from := userAAddr // useless variable, just to make clear who the signer is - nonce, err := blockchain.PendingNonceAt(ctx, from) // uint64(0) - if err != nil { - t.Fatal("Error getting pending nonce ", err) - } - to := userBAddr - amount := big.NewInt(10000) // random amount - gasLimit := uint64(30000) // random magic number (we could estimate) - gasPrice, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) - if err != nil { - t.Fatal("Error suggesting gas price ", err) - } - // data := []byte{} - tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, nil) - - // to better understand the different signers - // worth looking into https://github.com/ethereum/go-ethereum/blob/cbfb40b0aab093e1b612f3b16834894b2cc67882/core/types/transaction_signing.go#L42-L53 - // signer need chainID - //chainID := big.NewInt(18) - //signer := types.NewEIP155Signer(chainID) - // simulated backend used homestead signer... but the latest might be EIP155? - signer := types.HomesteadSigner{} - signedTx, err := types.SignTx(tx, signer, userAKey) - if err != nil { - t.Fatal("Error signing tx: ", err) - } - - blockchain.SendTransaction(ctx, signedTx) - blockchain.Commit() - - txReceipt, _ := blockchain.TransactionReceipt(ctx, signedTx.Hash()) - - gasUsed := big.NewInt(int64(txReceipt.GasUsed)) - balA, err := blockchain.BalanceAt(ctx, userAAddr, nil) - if err != nil { - t.Fatal("Error retrieving balance of user A") - } - balB, err := blockchain.BalanceAt(ctx, userBAddr, nil) - if err != nil { - t.Fatal("Error retrieving balance of user B") - } - sum := new(big.Int) - sum.Add(balA, balB) - sum.Add(sum, gasUsed) - - // assert - if sum.Cmp(initialBalance) != 0 { - t.Fatal("FAILED: bad sum of balances and gas cost of transfer") - } -} - -func TestCompileContract(t *testing.T) { - // --------------------------------------------- - // COMPILE ION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - ionContractPath := basePath + "Ion.sol" - - contracts, err := compiler.CompileSolidity("", ionContractPath) - if err != nil { - t.Fatal("ERROR failed to compile Ion.sol:", err) - } - - patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] - if patriciaTrieContract == nil { - t.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") - } - - patriciaTrieABIBytes, err := json.Marshal(patriciaTrieContract.Info.AbiDefinition) - if err != nil { - t.Fatal("ERROR marshalling PatriciaTrie ABI:", err) - } - contractBinStr := patriciaTrieContract.Code - contractABIStr := string(patriciaTrieABIBytes) - - // --------------------------------------------- - // START BLOCKCHAIN SIMULATOR - // --------------------------------------------- - ctx := context.Background() - initialBalance := big.NewInt(1000000000) - - userAKey, _ := crypto.GenerateKey() - userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) - - // start simulated blockchain - alloc := make(core.GenesisAlloc) - alloc[userAAddr] = core.GenesisAccount{ - Balance: initialBalance, - } - blockchain := backends.NewSimulatedBackend(alloc) - - // --------------------------------------------- - // DEPLOY PATRICIA LIB ADDRESS - // --------------------------------------------- - // generate payload bytes (we are using PatriciaTrie in our example) - bytecode := common.Hex2Bytes(contractBinStr) - abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) - if err != nil { - t.Fatal("ERROR reading PatriciaTrie ABI ", err) - } - // packedABI, err := abi.Pack("",arg1,arg2,arg3) // if there is construxtor - packedABI, err := abiPatriciaTrie.Pack("") - if err != nil { - t.Fatal("ERROR packing ABI ", err) - } - payloadBytecode := append(bytecode, packedABI...) - - // transaction parameters - from := userAAddr // useless variable, just to make clear who the signer is - nonce, err := blockchain.PendingNonceAt(ctx, from) // uint64(0) - if err != nil { - t.Fatal("Error getting pending nonce ", err) - } - amount := big.NewInt(0) // random amount - gasLimit := uint64(3000000) // random magic number (we could estimate) - gasPrice, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) - if err != nil { - t.Fatal("Error suggesting gas price ", err) - } - - // create contract transaction NewContractCreation is the same has NewTransaction with `to` == nil - // tx := types.NewTransaction(nonce, nil, amount, gasLimit, gasPrice, payloadBytecode) - tx := types.NewContractCreation(nonce, amount, gasLimit, gasPrice, payloadBytecode) - - // sign transaction - signer := types.HomesteadSigner{} - signedTx, err := types.SignTx(tx, signer, userAKey) - if err != nil { - t.Fatal("Error signing tx: ", err) - } - - err = blockchain.SendTransaction(ctx, signedTx) - if err != nil { - t.Fatal("ERROR sending contract transaction") - } - blockchain.Commit() - - txReceipt, err := blockchain.TransactionReceipt(ctx, signedTx.Hash()) - if err != nil { - t.Fatal("ERROR getting tx receipt", err) - } - if txReceipt.GasUsed == 0 || txReceipt.Status == 0 { - t.Fatal("ERROR contract did not deploy properly") - } -} - -// inspired by https://medium.com/@akshay_111meher/creating-offline-raw-transactions-with-go-ethereum-8d6cc8174c5d -func TestDeployRawContract(t *testing.T) { - - // --------------------------------------------- - // COMPILE ION AND DEPENDENCIES - // --------------------------------------------- - basePath := os.Getenv("GOPATH") + "/src/github.com/clearmatics/ion/contracts/" - ionContractPath := basePath + "Ion.sol" - - contracts, err := compiler.CompileSolidity("", ionContractPath) - if err != nil { - t.Fatal("ERROR failed to compile Ion.sol:", err) - } - - patriciaTrieContract := contracts[basePath+"libraries/PatriciaTrie.sol:PatriciaTrie"] - if patriciaTrieContract == nil { - t.Fatal("ERROR solc compiler in go-ethereum did not compile expected depency: Ion.sol expected to depend on PatriciaTrie") - } - - patriciaTrieABIBytes, err := json.Marshal(patriciaTrieContract.Info.AbiDefinition) - if err != nil { - t.Fatal("ERROR marshalling PatriciaTrie ABI:", err) - } - - ionContract := contracts[basePath+"Ion.sol:Ion"] - ionABIBytes, err := json.Marshal(ionContract.Info.AbiDefinition) - if err != nil { - t.Fatal("ERROR marshalling Ion ABI:", err) - } - - contractBinStr := patriciaTrieContract.Code[2:] - contractABIStr := string(patriciaTrieABIBytes) - contractIonBinStr := ionContract.Code[2:] - contractIonABIStr := string(ionABIBytes) // contract.IonABI - - // --------------------------------------------- - // START BLOCKCHAIN SIMULATOR - // --------------------------------------------- - - ctx := context.Background() - initialBalance := big.NewInt(1000000000) - - userAKey, _ := crypto.GenerateKey() - userAAddr := crypto.PubkeyToAddress(userAKey.PublicKey) - - // start simulated blockchain - alloc := make(core.GenesisAlloc) - alloc[userAAddr] = core.GenesisAccount{ - Balance: initialBalance, - } - blockchain := backends.NewSimulatedBackend(alloc) - - // --------------------------------------------- - // DEPLOY PATRICIA LIB ADDRESS - // --------------------------------------------- - // generate payload bytes (we are using PatriciaTrie in our example) - bytecode := common.Hex2Bytes(contractBinStr) - abiPatriciaTrie, err := abi.JSON(strings.NewReader(contractABIStr)) - if err != nil { - t.Fatal("ERROR reading PatriciaTrie ABI ", err) - } - // packedABI, err := abi.Pack("",arg1,arg2,arg3) // if there is construxtor - packedABI, err := abiPatriciaTrie.Pack("") - if err != nil { - t.Fatal("ERROR packing ABI ", err) - } - payloadBytecode := append(bytecode, packedABI...) - - // transaction parameters - from := userAAddr // useless variable, just to make clear who the signer is - nonce, err := blockchain.PendingNonceAt(ctx, from) // uint64(0) - if err != nil { - t.Fatal("Error getting pending nonce ", err) - } - amount := big.NewInt(0) // random amount - gasLimit := uint64(3000000) // random magic number (we could estimate) - gasPrice, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) - if err != nil { - t.Fatal("Error suggesting gas price ", err) - } - - // create contract transaction NewContractCreation is the same has NewTransaction with `to` == nil - // tx := types.NewTransaction(nonce, nil, amount, gasLimit, gasPrice, payloadBytecode) - tx := types.NewContractCreation(nonce, amount, gasLimit, gasPrice, payloadBytecode) - - // sign transaction - signer := types.HomesteadSigner{} - signedTx, err := types.SignTx(tx, signer, userAKey) - if err != nil { - t.Fatal("Error signing tx: ", err) - } - - blockchain.SendTransaction(ctx, signedTx) - blockchain.Commit() - - txReceipt, err := blockchain.TransactionReceipt(ctx, signedTx.Hash()) - if err != nil { - t.Fatal("ERROR getting tx receipt", err) - } - - // --------------------------------------------- - // DEPLOY ION CONTRACT WITH PATRICIA LIB ADDRESS - // --------------------------------------------- - // after PatriciaTrie is deployed we deploy the Ion contract - patriciaTrieLibAddr := txReceipt.ContractAddress - - // add library address to Ion bytecode - var re = regexp.MustCompile(`__.*__`) - contractIonBinStrWithLibAddr := re.ReplaceAllString(contractIonBinStr, patriciaTrieLibAddr.Hex()[2:]) - - bytecodeIon := common.Hex2Bytes(contractIonBinStrWithLibAddr) - abiIon, err := abi.JSON(strings.NewReader(contractIonABIStr)) - if err != nil { - t.Fatal("ERROR reading Ion ABI ", err) - } - - constructorArg1Ion := crypto.Keccak256Hash([]byte("test argument")) // Ion argument - packedABIIon, err := abiIon.Pack("", constructorArg1Ion) // the Ion constructor argument is added here! - if err != nil { - t.Fatal("ERROR packing ABI ", err) - } - payloadBytecodeIon := append(bytecodeIon, packedABIIon...) - - // transaction parameters - fromIon := userAAddr // useless variable, just to make clear who the signer is - nonceIon, err := blockchain.PendingNonceAt(ctx, fromIon) // uint64(0) - if err != nil { - t.Fatal("Error getting pending nonce ", err) - } - amountIon := big.NewInt(0) - gasLimitIon := uint64(3000000) // random magic number (we could estimate) - gasPriceIon, err := blockchain.SuggestGasPrice(ctx) //new(big.Int) - if err != nil { - t.Fatal("Error suggesting gas price ", err) - } - - // create transaction - txIon := types.NewContractCreation(nonceIon, amountIon, gasLimitIon, gasPriceIon, payloadBytecodeIon) - - // sign transaction - signedTxIon, err := types.SignTx(txIon, signer, userAKey) - if err != nil { - t.Fatal("Error signing tx: ", err) - } - - blockchain.SendTransaction(ctx, signedTxIon) - blockchain.Commit() - - // test to see if chain id in contract matches the one sent - txReceiptIon, err := blockchain.TransactionReceipt(ctx, signedTxIon.Hash()) - if err != nil { - t.Fatal("ERROR getting tx receipt", err) - } - ionAddr := txReceiptIon.ContractAddress - - // contract Call function (to actually run a write function we would need to add transaction) - methodName := "chainId" - out := new([32]byte) - input, err := abiIon.Pack(methodName) - if err != nil { - t.Fatal("ERROR packing the method name for the contract call", err) - } - msg := ethereum.CallMsg{From: userAAddr, To: &ionAddr, Data: input} - output, err := blockchain.CallContract(ctx, msg, nil) - if err != nil { - t.Fatal("ERROR calling the Ion Contract", err) - } - err = abiIon.Unpack(out, methodName, output) - if err != nil { - t.Fatal("ERROR upacking the call", err) - } - - if !bytes.Equal((*out)[:], constructorArg1Ion.Bytes()) { - t.Fatalf("ERROR bytes stored in contract differ from bytes expected\n\tExpected:\t% 0x\n\tResult:\t\t% 0x\n", constructorArg1Ion.Bytes(), *out) - } -} From ac1b259ed6395326d6282e63be48365922294b48 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 11:20:46 +0000 Subject: [PATCH 188/203] Return tuple mismatch in config test fix --- ion-cli/config/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index bfd4a27..a1c8149 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -40,7 +40,7 @@ func Test_InitUser(t *testing.T) { expectedFrom := common.HexToAddress("2be5ab0e43b6dc2908d5321cf318f35b80d0c10d") expectedPrivateKey := "e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b" - auth, userkey := config.InitUser(keystore, password) + auth, userkey, err := config.InitUser(keystore, password) assert.Equal(t, auth.From, expectedFrom) privateKey := fmt.Sprintf("%x", crypto.FromECDSA(userkey.PrivateKey)) From 75c7cf8c12c04811de43b5fbbcf378b7b75a7d89 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 11:27:03 +0000 Subject: [PATCH 189/203] Handled error from tests --- ion-cli/config/config_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index a1c8149..98dbcde 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -41,6 +41,7 @@ func Test_InitUser(t *testing.T) { expectedPrivateKey := "e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b" auth, userkey, err := config.InitUser(keystore, password) + assert.Equal(err, nil) assert.Equal(t, auth.From, expectedFrom) privateKey := fmt.Sprintf("%x", crypto.FromECDSA(userkey.PrivateKey)) From a0845dc87f95e7264f651ebbe91b7d25aa1eeb74 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 11:36:36 +0000 Subject: [PATCH 190/203] Handled error from tests --- ion-cli/config/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 98dbcde..9c11b93 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -41,7 +41,7 @@ func Test_InitUser(t *testing.T) { expectedPrivateKey := "e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b" auth, userkey, err := config.InitUser(keystore, password) - assert.Equal(err, nil) + assert.Equal(t, err, nil) assert.Equal(t, auth.From, expectedFrom) privateKey := fmt.Sprintf("%x", crypto.FromECDSA(userkey.PrivateKey)) From 5275df57934e29aa1aaed91d7123778ddfc8e8a6 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 13:22:03 +0000 Subject: [PATCH 191/203] Fixed remaining tests --- ion-cli/cli/core.go | 2 +- ion-cli/config/config_test.go | 12 ++---------- ion-cli/main.go | 2 +- ion-cli/utils/type.go | 2 +- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/ion-cli/cli/core.go b/ion-cli/cli/core.go index 9386c78..bab440d 100644 --- a/ion-cli/cli/core.go +++ b/ion-cli/cli/core.go @@ -217,7 +217,7 @@ func parseMethodParameters(c *ishell.Context, abiStruct *abi.ABI, methodName str copy(byteArray[:], bytes[:32]) args = append(args, byteArray) default: - errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %i incompatible", argument.Type.Size) + errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %d incompatible", argument.Type.Size) return nil, errors.New(errStr) } continue diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go index 9c11b93..5737603 100644 --- a/ion-cli/config/config_test.go +++ b/ion-cli/config/config_test.go @@ -15,17 +15,9 @@ import ( "github.com/clearmatics/ion/ion-cli/config" ) -func Test_ReadValidSetupJson(t *testing.T) { - path := findPath() + "./test.json" - setup := config.ReadSetup(path) - - assert.Equal(t, "127.0.0.1:8545", setup.AddrTo) - assert.Equal(t, "127.0.0.1:8501", setup.AddrFrom) - assert.Equal(t, "0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", setup.Ion) -} func Test_ReadValidKeystore(t *testing.T) { - path := findPath() + "./UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + path := findPath() + "../keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" contents := config.ReadString(path) const val = "{\"address\":\"2be5ab0e43b6dc2908d5321cf318f35b80d0c10d\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"0b11aa865046778a1b16a9b8cb593df704e3fe09f153823d75442ad1aab66caa\",\"cipherparams\":{\"iv\":\"4aa66b789ee2d98cf77272a72eeeaa50\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"b957fa7b7577240fd3791168bbe08903af4c8cc62c304f1df072dc2a59b1765e\"},\"mac\":\"197a06eb0449301d871400a6bdf6c136b6f7658ee41e3f2f7fd81ca11cd954a3\"},\"id\":\"a3cc1eae-3e36-4659-b759-6cf416216e72\",\"version\":3}" @@ -35,7 +27,7 @@ func Test_ReadValidKeystore(t *testing.T) { } func Test_InitUser(t *testing.T) { - keystore := "./UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + keystore := "../keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" password := "password1" expectedFrom := common.HexToAddress("2be5ab0e43b6dc2908d5321cf318f35b80d0c10d") expectedPrivateKey := "e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b" diff --git a/ion-cli/main.go b/ion-cli/main.go index 70ee901..34c9f0c 100644 --- a/ion-cli/main.go +++ b/ion-cli/main.go @@ -16,7 +16,7 @@ func main() { func printWelcome() { // display welcome info. fmt.Println("===============================================================") - fmt.Println("Ion Command Line Interface\n") + fmt.Print("Ion Command Line Interface\n\n") fmt.Println("Use 'help' to list commands") fmt.Println("===============================================================") } diff --git a/ion-cli/utils/type.go b/ion-cli/utils/type.go index fe79707..ce67f00 100644 --- a/ion-cli/utils/type.go +++ b/ion-cli/utils/type.go @@ -179,7 +179,7 @@ func ConvertAndAppend(c *ishell.Context, input string, argument *abi.Argument, o copy(byteArray[:], bytes[:32]) output = append(output, byteArray) default: - errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %i incompatible", argument.Type.Size) + errStr := fmt.Sprintf("Error parsing fixed size byte array. Array of size %d incompatible", argument.Type.Size) return nil, errors.New(errStr) } return output, nil From 424278ebee5bd94502d7f8440694f6f2fecb763b Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 13:28:29 +0000 Subject: [PATCH 192/203] Updated Readme with prerequisites --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a21dbfc..90e44e6 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ We envision Ion to evolve to become a library of tools that developers can use o Clone the repository and ensure that all the components work out of the box. +You will need [`nodejs`](https://nodejs.org/en/) and [`golang`](https://golang.org/) installed. + Run: ``` From 4884fb9dba66b59f30c650d8d6650e6fef74d86a Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 13:40:03 +0000 Subject: [PATCH 193/203] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 90e44e6..15177f0 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Procedure: 1. `cd ion-cli && make` to build the CLI 2. `./ion-cli` Starts the CLI 3. `>>> connectToClient https://rinkeby.infura.io` Connect to the Rinkeby Testnet -4. `>>> addAccount me /keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. +4. `>>> addAccount me ./keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. 5. `>>> addContractInstance function ../contracts/functional/Function.sol` Add your functional contract instance which compiles your contract 6. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: * `_storeAddr`: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` From 2682a8453dc136f1b0d43384a757289a37121204 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 13:44:08 +0000 Subject: [PATCH 194/203] Update .travis.yml --- .travis.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 573ac9c..62b5793 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ matrix: - docker run --name testrpc --rm -d -it -p 127.0.0.1:8501:8545 node bash - docker exec -d -it testrpc /bin/bash ./docker_build/launch_geth.sh - - name: "Golang Ion-CLI Tests" + - name: "Ion-CLI Tests" language: go go: 1.9.x script: @@ -30,6 +30,20 @@ matrix: - cp -r "${GOPATH}/src/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1" "vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/" - make build - make test + - ./ion-cli + - connectToClient https://rinkeby.infura.io + - addAccount me ./keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605 + - addContractInstance function ../contracts/functional/Function.sol + - transactionMessage function verifyAndExecute me 0x8A8375fC4d0f49C36bbeeb7e6476756498F62E6D 0 100000 + - 0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177 + - 0xf88ef06bc1a9c60457d8a4b65c4020dae2ef7f3287076a4d2d481a1bcb8e3148 + - 0x5dF43D6eaDc3EE940eCbf66a114486f3eF853da3 + - 0x04 + - 0xf86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5 + - 0xf90236f851a0c478a441c408d00ad410c89a76a635913325eb62a8650ccbc96e8998d50e36dc80808080808080a0edb4c44cbd3957a9226f30b982449d487ff09ff0e933a25f1c005d9df93289c38080808080808080f9017180a07ad13782edc2465b8d6c914d6a18368597b6c906b420d5e3a3dd5dbc408166fba0600296a0213fdce5c37d0520f8e23c32c90bad0e8d9163edb6357fe794546e09a05e5cdcbc193fe8a2966f8d5ecc6d94bd527c37b3f6ae0a3530c9f22cd8efc1b4a09fcfbbffd3fc9b6d7bfc57ec78811f425a24c3828d2ac203c06c7540dd382514a0a0b78e007d6cbcd9fd048ebc6397ca0d067397fb5d61f32fdc118377eaf1039ba032a122caf55ecfa596d4671830e058d6116902ada20591c72f43b299d6b0cb95a06c1f1b6f656336723110875d56d38470520fc82eea9939956ea7c77cd98de7e4a0bb2cffa7c59f46bfadcb40f32a8294ed45c991e6b6e858fc1a81c1ae8e546800a0916fe7ee83eed2a2864dcb5989522af36983674b9a89b8ab856f0e92236383a7a0fa44c96e10751887a97d8855c941805d5de5a7bbb31dfbcdb7100144d35ac4cca0c43a7ef5f5eb44ddd864b3fb9e7be9953e49c5ca089c034175d98b80e5f461718080808080f86d20b86af86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5 + - 0xf90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605 + - 0xf90335f851a08fbb95708b2169b98ca70955d2280ea41a4490918c7097b9fbb0dc02b6c1021d80808080808080a07e520e72a52d285315cad163ae68ff5f5b9d7b2efb8bf38488428249580b8aee8080808080808080f9017180a03f63d06b509ff798f0c456e58402326006f83b1dfbddf00ee61810754489817ca05f0c69a424cccf549fa2a1e460cab220f18238fac997214049480a1c48f320eaa0faee39d4012a0db36c610ac5f41306041dee4488d47bc41242afb40582e2b8ffa0d298be00622dc72ef2d1a2df8a259bcf769d36e4502ef8b1b2dbde2d19736c3ba04f78ffe7b29e2192dee6197eeeb19f56801dfe092c3fc485f8e2ca0141dddb1ca0e1c200d90941dbf37ac5d0f37e40479de4b2fe1a0a1b398c9f64cf80d6010eb0a034d7af644f909a94dc41bfa08ae9d0ea1c0d053e0c520378e8a5f2efd6422b62a068858e77fadd9ae975d9aff2e23e40b0f50dab934654a261930a40101ce370a0a068be4c01c98beead34d05516b5236e6196d85125b89e2632f23bdf16e7b16fe4a09f0c3ad7917f3f28a66d151270d2cd4ece50fecb2bd769c38512f1e9c5f9355ea05e1856c7908a4428edb582898261e563b2356fa3d1134357b47799a3e470bcc18080808080f9016b20b90167f90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605 + - 0xb8844cf76df596e746f360957aa3af954ef51605 before_install: - sudo add-apt-repository ppa:ethereum/ethereum -y @@ -37,7 +51,6 @@ matrix: - sudo apt-get install solc -y - notifications: slack: on_failure: always From f0a81da2be4ff603f0d4be91d81c3d9fcde14866 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 13:56:29 +0000 Subject: [PATCH 195/203] Update .travis.yml --- .travis.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 62b5793..e492a7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,20 +30,6 @@ matrix: - cp -r "${GOPATH}/src/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1" "vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/" - make build - make test - - ./ion-cli - - connectToClient https://rinkeby.infura.io - - addAccount me ./keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605 - - addContractInstance function ../contracts/functional/Function.sol - - transactionMessage function verifyAndExecute me 0x8A8375fC4d0f49C36bbeeb7e6476756498F62E6D 0 100000 - - 0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177 - - 0xf88ef06bc1a9c60457d8a4b65c4020dae2ef7f3287076a4d2d481a1bcb8e3148 - - 0x5dF43D6eaDc3EE940eCbf66a114486f3eF853da3 - - 0x04 - - 0xf86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5 - - 0xf90236f851a0c478a441c408d00ad410c89a76a635913325eb62a8650ccbc96e8998d50e36dc80808080808080a0edb4c44cbd3957a9226f30b982449d487ff09ff0e933a25f1c005d9df93289c38080808080808080f9017180a07ad13782edc2465b8d6c914d6a18368597b6c906b420d5e3a3dd5dbc408166fba0600296a0213fdce5c37d0520f8e23c32c90bad0e8d9163edb6357fe794546e09a05e5cdcbc193fe8a2966f8d5ecc6d94bd527c37b3f6ae0a3530c9f22cd8efc1b4a09fcfbbffd3fc9b6d7bfc57ec78811f425a24c3828d2ac203c06c7540dd382514a0a0b78e007d6cbcd9fd048ebc6397ca0d067397fb5d61f32fdc118377eaf1039ba032a122caf55ecfa596d4671830e058d6116902ada20591c72f43b299d6b0cb95a06c1f1b6f656336723110875d56d38470520fc82eea9939956ea7c77cd98de7e4a0bb2cffa7c59f46bfadcb40f32a8294ed45c991e6b6e858fc1a81c1ae8e546800a0916fe7ee83eed2a2864dcb5989522af36983674b9a89b8ab856f0e92236383a7a0fa44c96e10751887a97d8855c941805d5de5a7bbb31dfbcdb7100144d35ac4cca0c43a7ef5f5eb44ddd864b3fb9e7be9953e49c5ca089c034175d98b80e5f461718080808080f86d20b86af86808843b9aca00830186a0945df43d6eadc3ee940ecbf66a114486f3ef853da38084457094cc1ca08231f8f3c7c32c425d43418053eea8f3de09a64e40833329d8ca94d118498f72a00373c76a75251dc0da8f06658e3a261a31ec85759102266ee9110c022f9d45d5 - - 0xf90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605 - - 0xf90335f851a08fbb95708b2169b98ca70955d2280ea41a4490918c7097b9fbb0dc02b6c1021d80808080808080a07e520e72a52d285315cad163ae68ff5f5b9d7b2efb8bf38488428249580b8aee8080808080808080f9017180a03f63d06b509ff798f0c456e58402326006f83b1dfbddf00ee61810754489817ca05f0c69a424cccf549fa2a1e460cab220f18238fac997214049480a1c48f320eaa0faee39d4012a0db36c610ac5f41306041dee4488d47bc41242afb40582e2b8ffa0d298be00622dc72ef2d1a2df8a259bcf769d36e4502ef8b1b2dbde2d19736c3ba04f78ffe7b29e2192dee6197eeeb19f56801dfe092c3fc485f8e2ca0141dddb1ca0e1c200d90941dbf37ac5d0f37e40479de4b2fe1a0a1b398c9f64cf80d6010eb0a034d7af644f909a94dc41bfa08ae9d0ea1c0d053e0c520378e8a5f2efd6422b62a068858e77fadd9ae975d9aff2e23e40b0f50dab934654a261930a40101ce370a0a068be4c01c98beead34d05516b5236e6196d85125b89e2632f23bdf16e7b16fe4a09f0c3ad7917f3f28a66d151270d2cd4ece50fecb2bd769c38512f1e9c5f9355ea05e1856c7908a4428edb582898261e563b2356fa3d1134357b47799a3e470bcc18080808080f9016b20b90167f90164018311aac9b9010000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000800000000000f85af858945df43d6eadc3ee940ecbf66a114486f3ef853da3e1a027a9902e06885f7c187501d61990eae923b37634a8d6dda55a04dc7078395340a0000000000000000000000000b8844cf76df596e746f360957aa3af954ef51605 - - 0xb8844cf76df596e746f360957aa3af954ef51605 before_install: - sudo add-apt-repository ppa:ethereum/ethereum -y From fc2649c717d3f9092c31dccd2aa430250e542aad Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 15:48:13 +0000 Subject: [PATCH 196/203] Update README.md --- ion-cli/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ion-cli/README.md b/ion-cli/README.md index 6f28a66..14f1bc6 100644 --- a/ion-cli/README.md +++ b/ion-cli/README.md @@ -4,7 +4,9 @@ The Command-Line Interface reference. ## Building the CLI -Run `make build` to fetch sources and compile the binary. +Clean the directory: `make clean` + +Run `make build` to fetch sources and compile the binary. This will error if attempted to be built outside of your `GOPATH`. ## Usage From 52faaf65ebdb5a89752a4d6d2f96687736558e91 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 15:50:08 +0000 Subject: [PATCH 197/203] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 15177f0..87f4231 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Ethereum Block Store: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` We will deploy our own instance of the `Function.sol` contract and pass proofs to verify a transaction that we will depend on in order to execute a function in the contract. If the proofs verify correctly then the function should emit an event to indicate that it has been executed. Procedure: -1. `cd ion-cli && make` to build the CLI +1. We'll need the CLI here, [build the CLI](./ion-cli/). 2. `./ion-cli` Starts the CLI 3. `>>> connectToClient https://rinkeby.infura.io` Connect to the Rinkeby Testnet 4. `>>> addAccount me ./keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. From 1704ecffd014579dc37dd90cb5123cecc22edee8 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Thu, 6 Dec 2018 16:49:50 +0000 Subject: [PATCH 198/203] Added requirements to CLI readme --- ion-cli/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ion-cli/README.md b/ion-cli/README.md index 14f1bc6..0d57746 100644 --- a/ion-cli/README.md +++ b/ion-cli/README.md @@ -4,7 +4,11 @@ The Command-Line Interface reference. ## Building the CLI -Clean the directory: `make clean` +Clean the directory: `make clean`. + +### Requirements + +* [`solc`](https://github.com/ethereum/solidity/releases) Run `make build` to fetch sources and compile the binary. This will error if attempted to be built outside of your `GOPATH`. From 1df2ae97653ee13b56cae265c1159ee5f9b85273 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 7 Dec 2018 10:00:33 +0000 Subject: [PATCH 199/203] Update README.md --- ion-cli/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion-cli/README.md b/ion-cli/README.md index 0d57746..0c24574 100644 --- a/ion-cli/README.md +++ b/ion-cli/README.md @@ -8,7 +8,7 @@ Clean the directory: `make clean`. ### Requirements -* [`solc`](https://github.com/ethereum/solidity/releases) +* [`solc`](https://github.com/ethereum/solidity/releases) ensure matching compiler version with target solidity code as 0.4.x will not be compatible with solc 0.5 Run `make build` to fetch sources and compile the binary. This will error if attempted to be built outside of your `GOPATH`. From a0ea842c92db19be14bdd004264b706fbcda9760 Mon Sep 17 00:00:00 2001 From: Shirikatsu Date: Fri, 7 Dec 2018 10:02:52 +0000 Subject: [PATCH 200/203] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 87f4231..e904c74 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Procedure: 2. `./ion-cli` Starts the CLI 3. `>>> connectToClient https://rinkeby.infura.io` Connect to the Rinkeby Testnet 4. `>>> addAccount me ./keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. -5. `>>> addContractInstance function ../contracts/functional/Function.sol` Add your functional contract instance which compiles your contract +5. `>>> addContractInstance function /absolute/path/to/contracts/functional/Function.sol` Add your functional contract instance which compiles your contract. Must be passed an absolute path. 6. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: * `_storeAddr`: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` * `_verifierAddr`: `0xf973eB920fDB5897d79394F2e49430dCB9aA4ea1` From 2d0184c55ba9fb18fa8c9600afcd9e8048565375 Mon Sep 17 00:00:00 2001 From: Duarte Aragao Date: Mon, 10 Dec 2018 14:58:01 +0000 Subject: [PATCH 201/203] more obvious password in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e904c74..b91569f 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Procedure: 1. We'll need the CLI here, [build the CLI](./ion-cli/). 2. `./ion-cli` Starts the CLI 3. `>>> connectToClient https://rinkeby.infura.io` Connect to the Rinkeby Testnet -4. `>>> addAccount me ./keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is 'test'. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. +4. `>>> addAccount me ./keystore/UTC--2018-11-14T13-34-31.599642840Z--b8844cf76df596e746f360957aa3af954ef51605` Add an account to be signing transactions with. We've included one that already has Rinkeby ETH for you :) Password to the keystore is `test`. If you arrived late to the party and there is no ETH left, tough luck, try creating your own account and requesting ETH from a faucet. Alternatively you can run this exact thread of commands on a `ganache-cli` instance but make sure you connect to the correct endpoint in step 2. 5. `>>> addContractInstance function /absolute/path/to/contracts/functional/Function.sol` Add your functional contract instance which compiles your contract. Must be passed an absolute path. 6. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: * `_storeAddr`: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` From 70ceba30798e8204f48b7cb353c7c937bf8ef456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duarte=20Arag=C3=A3o?= Date: Mon, 10 Dec 2018 15:12:53 +0000 Subject: [PATCH 202/203] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b91569f..01b862f 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Procedure: 6. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: * `_storeAddr`: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` * `_verifierAddr`: `0xf973eB920fDB5897d79394F2e49430dCB9aA4ea1` -7. `>>> transactionMessage function verifyAndExecute me 0 gaslimit` Call the function. This requires you to supply the deployed contract instance address. Here you will need to supply the following data as an input to the function when prompted: +7. `>>> transactionMessage function verifyAndExecute me 0 100000` Call the function. This requires you to supply the deployed contract instance address. Here you will need to supply the following data as an input to the function when prompted: * `_chainId`: `0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177` * `_blockHash`: `0xf88ef06bc1a9c60457d8a4b65c4020dae2ef7f3287076a4d2d481a1bcb8e3148` * `_contractEmittedAddress`: `0x5dF43D6eaDc3EE940eCbf66a114486f3eF853da3` From c3e73557cef55869bb64529408d7e0ff3815cfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duarte=20Arag=C3=A3o?= Date: Mon, 10 Dec 2018 15:19:38 +0000 Subject: [PATCH 203/203] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 01b862f..c3a75cb 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Procedure: 6. `>>> deployContract function me 1000000` Deploy your contract to Rinkeby! This will return an address that the contract is deployed at if successful. This contract has a constructor that requires two parameters to be supplied when prompted: * `_storeAddr`: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` * `_verifierAddr`: `0xf973eB920fDB5897d79394F2e49430dCB9aA4ea1` -7. `>>> transactionMessage function verifyAndExecute me 0 100000` Call the function. This requires you to supply the deployed contract instance address. Here you will need to supply the following data as an input to the function when prompted: +7. `>>> transactionMessage function verifyAndExecute me 0 1000000` Call the function. This requires you to supply the deployed contract instance address. Here you will need to supply the following data as an input to the function when prompted: * `_chainId`: `0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177` * `_blockHash`: `0xf88ef06bc1a9c60457d8a4b65c4020dae2ef7f3287076a4d2d481a1bcb8e3148` * `_contractEmittedAddress`: `0x5dF43D6eaDc3EE940eCbf66a114486f3eF853da3`

      GtWoKA~$`S)#VplgLf-3Guw%b1+^$GC0B| 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%0DkaO&i4e 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 bKW6pF_h$7{^TB`oU;j*w{UdqYuTK9D#;K25 diff --git a/poa-network/single-peer/node1/geth/nodes/CURRENT b/poa-network/single-peer/node1/geth/nodes/CURRENT deleted file mode 100644 index af00d34..0000000 --- a/poa-network/single-peer/node1/geth/nodes/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000097 diff --git a/poa-network/single-peer/node1/geth/nodes/LOCK b/poa-network/single-peer/node1/geth/nodes/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/poa-network/single-peer/node1/geth/nodes/LOG b/poa-network/single-peer/node1/geth/nodes/LOG deleted file mode 100644 index dcc2d5b..0000000 --- a/poa-network/single-peer/node1/geth/nodes/LOG +++ /dev/null @@ -1,379 +0,0 @@ -=============== Jul 12, 2018 (BST) =============== -11:09:05.859266 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:09:05.881724 db@open opening -11:09:05.886827 version@stat F·[] S·0B[] Sc·[] -11:09:05.902200 db@janitor F·2 G·0 -11:09:05.902230 db@open done T·20.463441ms -=============== Jul 12, 2018 (BST) =============== -11:24:30.549578 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:24:30.549938 version@stat F·[] S·0B[] Sc·[] -11:24:30.549967 db@open opening -11:24:30.550069 journal@recovery F·1 -11:24:30.555568 journal@recovery recovering @1 -11:24:30.575186 memdb@flush created L0@2 N·1953 S·15KiB "n:\xbb..ver,v1870":"version,v1" -11:24:30.579660 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] -11:24:30.598959 db@janitor F·3 G·0 -11:24:30.599047 db@open done T·49.061622ms -=============== Jul 12, 2018 (BST) =============== -11:27:23.929314 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:27:23.929673 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] -11:27:23.929707 db@open opening -11:27:23.929818 journal@recovery F·1 -11:27:23.933816 journal@recovery recovering @3 -11:27:23.944145 memdb@flush created L0@5 N·155 S·1KiB "n:\xbb..ver,v2057":"n:\xdc..ong,v1961" -11:27:23.948584 version@stat F·[2] S·17KiB[17KiB] Sc·[0.50] -11:27:23.965318 db@janitor F·4 G·0 -11:27:23.965391 db@open done T·35.663326ms -11:27:23.969673 table@compaction L0·2 -> L1·0 S·17KiB Q·2110 -11:27:23.983676 table@build created L1@8 N·9 S·411B "n:\xbb..ver,v2057":"version,v1" -11:27:23.983838 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:27:24.000730 table@compaction committed F-1 S-16KiB Ke·0 D·2099 T·30.949886ms -11:27:24.000800 table@remove removed @5 -11:27:24.000839 table@remove removed @2 -=============== Jul 12, 2018 (BST) =============== -11:34:08.322462 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:34:08.322604 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:34:08.322614 db@open opening -11:34:08.322650 journal@recovery F·1 -11:34:08.324145 journal@recovery recovering @6 -11:34:08.351791 memdb@flush created L0@9 N·957 S·7KiB "n:\xbb..ver,v3049":"n:\xdc..ong,v2117" -11:34:08.356450 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] -11:34:08.382422 db@janitor F·4 G·0 -11:34:08.382467 db@open done T·59.843968ms -=============== Jul 12, 2018 (BST) =============== -11:53:49.053572 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:53:49.053723 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] -11:53:49.053735 db@open opening -11:53:49.053775 journal@recovery F·1 -11:53:49.055338 journal@recovery recovering @10 -11:53:49.069911 memdb@flush created L0@12 N·3140 S·24KiB "n:\xbb..ver,v6197":"n:\xdc..ong,v3076" -11:53:49.071823 version@stat F·[2 1] S·33KiB[32KiB 411B] Sc·[0.50 0.00] -11:53:49.087260 db@janitor F·5 G·0 -11:53:49.087302 db@open done T·33.558786ms -11:53:49.089173 table@compaction L0·2 -> L1·1 S·33KiB Q·6209 -11:53:49.100536 table@build created L1@15 N·9 S·412B "n:\xbb..ver,v6197":"version,v1" -11:53:49.100861 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] -11:53:49.115649 table@compaction committed F-2 S-32KiB Ke·0 D·4097 T·26.423679ms -11:53:49.115759 table@remove removed @12 -11:53:49.115813 table@remove removed @9 -11:53:49.115854 table@remove removed @8 -=============== Jul 12, 2018 (BST) =============== -14:17:44.682705 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:17:44.683753 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] -14:17:44.683816 db@open opening -14:17:44.683982 journal@recovery F·1 -14:17:44.689029 journal@recovery recovering @13 -14:17:44.749579 memdb@flush created L0@16 N·10616 S·83KiB "n:\xbb..ver,v16777":"n:\xdc..ong,v6212" -14:17:44.750996 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] -14:17:44.779208 db@janitor F·4 G·0 -14:17:44.779238 db@open done T·95.395734ms -=============== Jul 12, 2018 (BST) =============== -14:39:51.265662 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:39:51.265819 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] -14:39:51.265832 db@open opening -14:39:51.265875 journal@recovery F·1 -14:39:51.267251 journal@recovery recovering @17 -14:39:51.282847 memdb@flush created L0@19 N·3518 S·28KiB "n:\xbb..ver,v20335":"n:\xdc..ong,v16833" -14:39:51.284827 version@stat F·[2 1] S·112KiB[112KiB 412B] Sc·[0.50 0.00] -14:39:51.304139 db@janitor F·5 G·0 -14:39:51.304178 db@open done T·38.337769ms -14:39:51.306434 table@compaction L0·2 -> L1·1 S·112KiB Q·20345 -14:39:51.328923 table@build created L1@22 N·9 S·410B "n:\xbb..ver,v20335":"version,v1" -14:39:51.329000 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -14:39:51.352502 table@compaction committed F-2 S-112KiB Ke·0 D·14134 T·46.026738ms -14:39:51.352618 table@remove removed @19 -14:39:51.352681 table@remove removed @16 -14:39:51.352719 table@remove removed @15 -=============== Jul 12, 2018 (BST) =============== -15:37:20.124805 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:37:20.125293 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -15:37:20.125338 db@open opening -15:37:20.125492 journal@recovery F·1 -15:37:20.131018 journal@recovery recovering @20 -15:37:20.167319 memdb@flush created L0@23 N·9030 S·71KiB "n:\xbb..ver,v29311":"n:\xdc..ong,v20356" -15:37:20.170842 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] -15:37:20.187160 db@janitor F·4 G·0 -15:37:20.187230 db@open done T·61.857192ms -=============== Jul 12, 2018 (BST) =============== -15:48:32.297828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -15:48:32.297998 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] -15:48:32.298011 db@open opening -15:48:32.298064 journal@recovery F·1 -15:48:32.299666 journal@recovery recovering @24 -15:48:32.368672 memdb@flush created L0@26 N·1824 S·14KiB "n:\xbb..ver,v31169":"n:\xdc..ong,v29379" -15:48:32.370730 version@stat F·[2 1] S·86KiB[85KiB 410B] Sc·[0.50 0.00] -15:48:32.387501 db@janitor F·5 G·0 -15:48:32.387524 db@open done T·89.5036ms -15:48:32.391376 table@compaction L0·2 -> L1·1 S·86KiB Q·31201 -15:48:32.409611 table@build created L1@29 N·9 S·411B "n:\xbb..ver,v31169":"version,v1" -15:48:32.409682 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -15:48:32.424137 table@compaction committed F-2 S-85KiB Ke·0 D·10854 T·32.684737ms -15:48:32.424229 table@remove removed @26 -15:48:32.424293 table@remove removed @23 -15:48:32.424332 table@remove removed @22 -=============== Jul 12, 2018 (BST) =============== -16:05:29.052109 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:05:29.052302 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -16:05:29.052322 db@open opening -16:05:29.052385 journal@recovery F·1 -16:05:29.053889 journal@recovery recovering @27 -16:05:29.070585 memdb@flush created L0@30 N·2723 S·21KiB "n:\xbb..ver,v33872":"n:\xdc..ong,v31212" -16:05:29.072728 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] -16:05:29.088665 db@janitor F·4 G·0 -16:05:29.088693 db@open done T·36.35836ms -=============== Jul 12, 2018 (BST) =============== -16:23:49.639965 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:23:49.640119 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] -16:23:49.640132 db@open opening -16:23:49.640177 journal@recovery F·1 -16:23:49.641522 journal@recovery recovering @31 -16:23:49.702907 memdb@flush created L0@33 N·2951 S·23KiB "n:\xbb..ver,v36828":"n:\xdc..ong,v33936" -16:23:49.707537 version@stat F·[2 1] S·45KiB[45KiB 411B] Sc·[0.50 0.00] -16:23:49.726802 db@janitor F·5 G·0 -16:23:49.726888 db@open done T·86.744755ms -16:23:49.730542 table@compaction L0·2 -> L1·1 S·45KiB Q·36877 -16:23:49.755043 table@build created L1@36 N·9 S·404B "n:\xbb..ver,v36828":"version,v1" -16:23:49.755142 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] -16:23:49.769539 table@compaction committed F-2 S-45KiB Ke·0 D·5674 T·38.915634ms -16:23:49.769669 table@remove removed @33 -16:23:49.769735 table@remove removed @30 -16:23:49.769777 table@remove removed @29 -=============== Jul 12, 2018 (BST) =============== -16:40:12.633424 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:40:12.633675 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] -16:40:12.633694 db@open opening -16:40:12.633751 journal@recovery F·1 -16:40:12.635430 journal@recovery recovering @34 -16:40:12.653741 memdb@flush created L0@37 N·2658 S·21KiB "n:\xbb..ver,v39480":"n:\xdc..ong,v36880" -16:40:12.655362 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] -16:40:12.672204 db@janitor F·4 G·0 -16:40:12.672249 db@open done T·38.544509ms -=============== Jul 12, 2018 (BST) =============== -16:57:40.345817 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -16:57:40.345996 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] -16:57:40.346012 db@open opening -16:57:40.346070 journal@recovery F·1 -16:57:40.347980 journal@recovery recovering @38 -16:57:40.363783 memdb@flush created L0@40 N·2786 S·22KiB "n:\xbb..ver,v42253":"n:\xdc..ong,v39543" -16:57:40.365500 version@stat F·[2 1] S·44KiB[43KiB 404B] Sc·[0.50 0.00] -16:57:40.381342 db@janitor F·5 G·0 -16:57:40.381385 db@open done T·35.364738ms -16:57:40.383292 table@compaction L0·2 -> L1·1 S·44KiB Q·42323 -16:57:40.408961 table@build created L1@43 N·9 S·410B "n:\xbb..ver,v42253":"version,v1" -16:57:40.409041 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -16:57:40.423831 table@compaction committed F-2 S-43KiB Ke·0 D·5444 T·40.39884ms -16:57:40.423935 table@remove removed @40 -16:57:40.423986 table@remove removed @37 -16:57:40.424026 table@remove removed @36 -21:39:50.525477 memdb@flush N·43421 S·3MiB -21:39:50.610325 memdb@flush created L0@45 N·43421 S·341KiB "n:\xbb..ver,v85728":"n:\xdc..ong,v42330" -21:39:50.610621 version@stat F·[1 1] S·341KiB[341KiB 410B] Sc·[0.25 0.00] -21:39:50.619942 memdb@flush committed F·1 T·94.239078ms -21:39:50.627386 journal@remove removed @41 -=============== Jul 13, 2018 (BST) =============== -02:22:42.318770 memdb@flush N·43426 S·3MiB -02:22:42.349319 memdb@flush created L0@47 N·43426 S·341KiB "n:\xbb..ver,v129168":"n:\xdc..ong,v85750" -02:22:42.349367 version@stat F·[2 1] S·682KiB[682KiB 410B] Sc·[0.50 0.00] -02:22:42.356398 memdb@flush committed F·1 T·37.578228ms -02:22:42.357339 journal@remove removed @44 -07:04:10.330333 memdb@flush N·43422 S·3MiB -07:04:10.393823 memdb@flush created L0@49 N·43422 S·341KiB "n:\xbb..ver,v172517":"n:\xdc..ong,v129177" -07:04:10.393906 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] -07:04:10.401140 memdb@flush committed F·1 T·70.637042ms -07:04:10.404444 journal@remove removed @46 -=============== Jul 13, 2018 (BST) =============== -11:03:48.229037 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:03:48.229335 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] -11:03:48.229357 db@open opening -11:03:48.229460 journal@recovery F·1 -11:03:48.233070 journal@recovery recovering @48 -11:03:48.333384 memdb@flush created L0@50 N·35960 S·283KiB "n:\xbb..ver,v208539":"n:\xdc..ong,v172602" -11:03:48.335105 version@stat F·[4 1] S·1MiB[1MiB 410B] Sc·[1.00 0.00] -11:03:48.365177 db@janitor F·7 G·0 -11:03:48.365234 db@open done T·135.861856ms -11:03:48.365374 table@compaction L0·4 -> L1·1 S·1MiB Q·208553 -11:03:48.537826 table@build created L1@53 N·9 S·411B "n:\xbb..ver,v208539":"version,v1" -11:03:48.537925 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:03:48.552126 table@compaction committed F-4 S-1MiB Ke·0 D·166229 T·186.66634ms -11:03:48.552301 table@remove removed @50 -11:03:48.552405 table@remove removed @49 -11:03:48.552509 table@remove removed @47 -11:03:48.552616 table@remove removed @45 -11:03:48.552651 table@remove removed @43 -=============== Jul 13, 2018 (BST) =============== -11:20:12.182469 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:20:12.182651 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] -11:20:12.182664 db@open opening -11:20:12.182717 journal@recovery F·1 -11:20:12.184513 journal@recovery recovering @51 -11:20:12.241385 memdb@flush created L0@54 N·2632 S·21KiB "n:\xbb..ver,v211126":"n:\xdc..ong,v208560" -11:20:12.243129 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] -11:20:12.267182 db@janitor F·4 G·0 -11:20:12.267224 db@open done T·84.550385ms -=============== Jul 13, 2018 (BST) =============== -11:22:05.344239 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:22:05.344426 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] -11:22:05.344439 db@open opening -11:22:05.344495 journal@recovery F·1 -11:22:05.346064 journal@recovery recovering @55 -11:22:05.396304 memdb@flush created L0@57 N·327 S·2KiB "n:\xbb..ver,v211460":"n:\xdc..ong,v211193" -11:22:05.398077 version@stat F·[2 1] S·24KiB[23KiB 411B] Sc·[0.50 0.00] -11:22:05.423465 db@janitor F·5 G·0 -11:22:05.423498 db@open done T·79.043478ms -11:22:05.431533 table@compaction L0·2 -> L1·1 S·24KiB Q·211514 -11:22:05.447314 table@build created L1@60 N·9 S·410B "n:\xbb..ver,v211460":"version,v1" -11:22:05.447458 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -11:22:05.465235 table@compaction committed F-2 S-23KiB Ke·0 D·2959 T·33.57446ms -11:22:05.465771 table@remove removed @57 -11:22:05.465835 table@remove removed @54 -11:22:05.465892 table@remove removed @53 -=============== Jul 13, 2018 (BST) =============== -11:28:36.605530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:28:36.605766 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] -11:28:36.605790 db@open opening -11:28:36.605861 journal@recovery F·1 -11:28:36.605970 journal@recovery recovering @58 -11:28:36.669491 memdb@flush created L0@61 N·1083 S·8KiB "n:\xbb..ver,v212511":"n:\xdc..ong,v211525" -11:28:36.675160 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] -11:28:36.702895 db@janitor F·4 G·0 -11:28:36.702923 db@open done T·97.12478ms -=============== Jul 13, 2018 (BST) =============== -11:41:32.591748 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:32.592105 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] -11:41:32.592141 db@open opening -11:41:32.592263 journal@recovery F·1 -11:41:32.596765 journal@recovery recovering @62 -11:41:32.663254 memdb@flush created L0@64 N·2051 S·16KiB "n:\xbb..ver,v214616":"n:\xdc..ong,v212601" -11:41:32.667391 version@stat F·[2 1] S·25KiB[25KiB 410B] Sc·[0.50 0.00] -11:41:32.687539 db@janitor F·5 G·0 -11:41:32.687649 db@open done T·95.481415ms -11:41:32.693255 table@compaction L0·2 -> L1·1 S·25KiB Q·214650 -11:41:32.705795 table@build created L1@67 N·9 S·402B "n:\xbb..ver,v214616":"version,v1" -11:41:32.705947 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] -11:41:32.716509 table@compaction committed F-2 S-25KiB Ke·0 D·3134 T·23.166583ms -11:41:32.716920 table@remove removed @64 -11:41:32.717040 table@remove removed @61 -11:41:32.717124 table@remove removed @60 -=============== Jul 13, 2018 (BST) =============== -13:24:41.332660 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:24:41.333223 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] -13:24:41.333279 db@open opening -13:24:41.333442 journal@recovery F·1 -13:24:41.338137 journal@recovery recovering @65 -13:24:41.431439 memdb@flush created L0@68 N·16181 S·126KiB "n:\xbb..ver,v230767":"n:\xdc..ong,v214663" -13:24:41.436600 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] -13:24:41.455095 db@janitor F·4 G·0 -13:24:41.455178 db@open done T·121.864633ms -=============== Jul 13, 2018 (BST) =============== -13:39:14.287874 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:39:14.288364 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] -13:39:14.288413 db@open opening -13:39:14.288637 journal@recovery F·1 -13:39:14.294999 journal@recovery recovering @69 -13:39:14.358894 memdb@flush created L0@71 N·373 S·3KiB "n:\xbb..ver,v231162":"n:\xdc..ong,v230839" -13:39:14.362425 version@stat F·[2 1] S·129KiB[129KiB 402B] Sc·[0.50 0.00] -13:39:14.378518 db@janitor F·5 G·0 -13:39:14.378592 db@open done T·90.139823ms -13:39:14.382837 table@compaction L0·2 -> L1·1 S·129KiB Q·231206 -13:39:14.423154 table@build created L1@74 N·9 S·408B "n:\xbb..ver,v231162":"version,v1" -13:39:14.423312 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] -13:39:14.430225 table@compaction committed F-2 S-129KiB Ke·0 D·16554 T·47.299275ms -13:39:14.430806 table@remove removed @71 -13:39:14.431030 table@remove removed @68 -13:39:14.431114 table@remove removed @67 -=============== Jul 13, 2018 (BST) =============== -13:42:01.201254 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:42:01.202082 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] -13:42:01.202135 db@open opening -13:42:01.202346 journal@recovery F·1 -13:42:01.208136 journal@recovery recovering @72 -13:42:01.262455 memdb@flush created L0@75 N·6173 S·223KiB "n:\x00..ail,v235103":"n:\xff..ing,v237371" -13:42:01.264229 version@stat F·[1 1] S·223KiB[223KiB 408B] Sc·[0.25 0.00] -13:42:01.281802 db@janitor F·4 G·0 -13:42:01.281968 db@open done T·79.800956ms -13:42:01.378033 table@compaction L0·1 -> L1·1 S·223KiB Q·237380 -13:42:01.396425 table@build created L1@78 N·4559 S·204KiB "n:\x00..ail,v235103":"version,v1" -13:42:01.396501 version@stat F·[0 1] S·204KiB[0B 204KiB] Sc·[0.00 0.00] -13:42:01.403777 table@compaction committed F-1 S-19KiB Ke·0 D·1623 T·25.655949ms -13:42:01.403949 table@remove removed @75 -13:42:01.404032 table@remove removed @74 -=============== Jul 13, 2018 (BST) =============== -13:50:51.642894 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:50:51.643089 version@stat F·[0 1] S·204KiB[0B 204KiB] Sc·[0.00 0.00] -13:50:51.643107 db@open opening -13:50:51.643167 journal@recovery F·1 -13:50:51.645218 journal@recovery recovering @76 -13:50:51.775777 memdb@flush created L0@79 N·15634 S·576KiB "n:\x00..ing,v250524":"n:\xff..ing,v246194" -13:50:51.777852 version@stat F·[1 1] S·781KiB[576KiB 204KiB] Sc·[0.25 0.00] -13:50:51.797181 db@janitor F·4 G·0 -13:50:51.797218 db@open done T·154.10061ms -13:50:51.858184 table@compaction L0·1 -> L1·1 S·781KiB Q·253056 -13:50:51.900361 table@build created L1@82 N·15140 S·710KiB "n:\x00..ail,v235103":"version,v1" -13:50:51.901224 version@stat F·[0 1] S·710KiB[0B 710KiB] Sc·[0.00 0.01] -13:50:51.909091 table@compaction committed F-1 S-70KiB Ke·0 D·5053 T·50.683078ms -13:50:51.910084 table@remove removed @79 -13:50:51.913610 table@remove removed @78 -=============== Jul 13, 2018 (BST) =============== -13:54:37.269315 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:54:37.269838 version@stat F·[0 1] S·710KiB[0B 710KiB] Sc·[0.00 0.01] -13:54:37.269907 db@open opening -13:54:37.270104 journal@recovery F·1 -13:54:37.276150 journal@recovery recovering @80 -13:54:37.357368 memdb@flush created L0@83 N·1973 S·78KiB "n:\x00..ail,v253125":"n:\xff..ing,v253349" -13:54:37.364118 version@stat F·[1 1] S·789KiB[78KiB 710KiB] Sc·[0.25 0.01] -13:54:37.381416 db@janitor F·4 G·0 -13:54:37.381496 db@open done T·111.553712ms -13:54:37.414782 table@compaction L0·1 -> L1·1 S·789KiB Q·254996 -13:54:37.443397 table@build created L1@86 N·16383 S·772KiB "n:\x00..ail,v235103":"version,v1" -13:54:37.443515 version@stat F·[0 1] S·772KiB[0B 772KiB] Sc·[0.00 0.01] -13:54:37.450421 table@compaction committed F-1 S-16KiB Ke·0 D·730 T·35.579233ms -13:54:37.450796 table@remove removed @83 -13:54:37.451019 table@remove removed @82 -=============== Jul 13, 2018 (BST) =============== -13:57:11.212091 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -13:57:11.212882 version@stat F·[0 1] S·772KiB[0B 772KiB] Sc·[0.00 0.01] -13:57:11.212955 db@open opening -13:57:11.213215 journal@recovery F·1 -13:57:11.220864 journal@recovery recovering @84 -13:57:11.305053 memdb@flush created L0@87 N·3132 S·113KiB "n:\x00..ail,v255171":"n:\xff..ing,v256390" -13:57:11.312835 version@stat F·[1 1] S·885KiB[113KiB 772KiB] Sc·[0.25 0.01] -13:57:11.334674 db@janitor F·4 G·0 -13:57:11.334790 db@open done T·121.757337ms -13:57:11.370088 table@compaction L0·1 -> L1·1 S·885KiB Q·258123 -13:57:11.401172 table@build created L1@90 N·17944 S·848KiB "n:\x00..ail,v235103":"version,v1" -13:57:11.401249 version@stat F·[0 1] S·848KiB[0B 848KiB] Sc·[0.00 0.01] -13:57:11.412346 table@compaction committed F-1 S-37KiB Ke·0 D·1571 T·42.186121ms -13:57:11.412485 table@remove removed @87 -13:57:11.412711 table@remove removed @86 -=============== Jul 13, 2018 (BST) =============== -14:14:58.851035 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:14:58.851219 version@stat F·[0 1] S·848KiB[0B 848KiB] Sc·[0.00 0.01] -14:14:58.851233 db@open opening -14:14:58.851274 journal@recovery F·1 -14:14:58.853147 journal@recovery recovering @88 -14:14:58.930188 memdb@flush created L0@91 N·18217 S·488KiB "n:\x00..ing,v272680":"n:\xff..ing,v259302" -14:14:58.932029 version@stat F·[1 1] S·1MiB[488KiB 848KiB] Sc·[0.25 0.01] -14:14:58.951250 db@janitor F·4 G·0 -14:14:58.951279 db@open done T·100.037464ms -14:14:59.236427 table@compaction L0·1 -> L1·1 S·1MiB Q·276382 -14:14:59.290345 table@build created L1@94 N·23452 S·1MiB "n:\x00..ail,v235103":"version,v1" -14:14:59.290583 version@stat F·[0 1] S·1MiB[0B 1MiB] Sc·[0.00 0.01] -14:14:59.297982 table@compaction committed F-1 S-189KiB Ke·0 D·12709 T·61.475181ms -14:14:59.300378 table@remove removed @91 -14:14:59.300707 table@remove removed @90 -=============== Jul 13, 2018 (BST) =============== -14:34:10.197079 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -14:34:10.197845 version@stat F·[0 1] S·1MiB[0B 1MiB] Sc·[0.00 0.01] -14:34:10.197930 db@open opening -14:34:10.198164 journal@recovery F·1 -14:34:10.206290 journal@recovery recovering @92 -14:34:10.304595 memdb@flush created L0@95 N·15756 S·365KiB "n:\x00..ail,v280370":"n:\xff..ong,v283459" -14:34:10.310007 version@stat F·[1 1] S·1MiB[365KiB 1MiB] Sc·[0.25 0.01] -14:34:10.328427 db@janitor F·4 G·0 -14:34:10.328528 db@open done T·130.556877ms -14:34:10.453233 table@compaction L0·1 -> L1·1 S·1MiB Q·292146 -14:34:10.490415 table@build created L1@98 N·25961 S·1MiB "n:\x00..ail,v280370":"version,v1" -14:34:10.490499 version@stat F·[0 1] S·1MiB[0B 1MiB] Sc·[0.00 0.01] -14:34:10.497891 table@compaction committed F-1 S-216KiB Ke·0 D·13247 T·44.607513ms -14:34:10.498081 table@remove removed @95 -14:34:10.498424 table@remove removed @94 diff --git a/poa-network/single-peer/node1/geth/nodes/MANIFEST-000097 b/poa-network/single-peer/node1/geth/nodes/MANIFEST-000097 deleted file mode 100644 index 452f7ab1386c5bb89f8d68240c7ca132d6948b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmX?q!ri=#iIGt%C$%g!CnZVGsj?)sJhM2}IX|}`u_&=5zlbS;Ifn2!6gl zZPAuD@3+`2W53j)G3TFEN@j6#epzafRZe1YNkL{_I^(l1%nU%l&Jh3TjTq1h1|~bh ze&z0uRYf)b&API_=jxX|-{60K(v|)1S#>AZFxg0CTV9D=kdtTJkr}I`Du40KYx_4* z8a5?u?R%NDzh@$>NXyJiNlVPkVKj1Q0a*cZ{{_7z(i^VZaL(VXyfXTw`APY!A{{ei z%Z|>ec<}kshL5&WODZ}xXMX=VSJ*~3`@4G952kOz7F>po@@x7s-Z`})35DyIUf8tsf8?pV#f!9b!>eykI&Fmw+B0C!Vj@Bjb+ diff --git a/poa-network/single-peer/node1/geth/transactions.rlp b/poa-network/single-peer/node1/geth/transactions.rlp deleted file mode 100755 index 2f6e1f63ed690ec6b0262c286eab7f610ea83b09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 637035 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

      (eXz+%? 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%0AT@Gyg^YS@JLa!0E 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

    GtWoKA~$`S)#VplgLf-3Guw%b1+^$GC0B| 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%0DkaO&i4e z+w%UggDrE!W3J#6%9_t+|%M$5AWuEK{ubzEfh zWIinkcFU0LAA5@xX-j>4J2GAUf9w8lx&!FL|Ctv8AqDe7B0)a=KYj+P#2A&Tu0zC8 zxXs_4aX>CSEmw9w=oz^Ed%GUDX9)*tHeT@F&seEtRW3Noa7>jc(I>*mBII&;yzVB& zmAmI|RYL^myhFwKeKaxMp^4e30^7!2g>PsAP2B!uh8jiRwLdLTX?@*)0>>UBe|bg^ zrQ8^<`}sODIe=cK=&nNgX;V=nLej{>=K9gO?R!g$4*tKgfU`P`0ir7q(8q?eaS2j1 zkd=SSZ3=lMA^b_G`8CO^A;EE3vwH+7R(12`SEbxV>e`Rt*v(&__W5!y=-2UHZts>- zG)z5us$2bD8|&nA+m32f35u;m%%Nw4fUSD|fO+X?cM0eZ%rCleX5x5dTHiXr`aO7u z^~E>`r`XSx*I(t12abmClh)n{YZ#N6e1rAr)#Z&>{zrr#Ymg88#?cL#alycnhfuT( zRZdATE`@306-%&+EBMzSdkx?VZ~%OP#2x524VFT12Xccp-+SO(rgDwBA;`a9gw`Y2 zSIFa{&~Cl@wcBZvTjZ&TSBjPF5B^4zrudN+^;nJ8o-9A_dW@_-_&SlNv<%cizoi}y+P^fQIq;a@JWJZNKFeL z|4S;Nd%JjC>YdbPLHGXpW5#@n=7O7Okh_5TMY6FA#OU7vjPMrHRDYF(<<{PMYq}}c z&oD_Eo=)f4o#nN7I9B~rD#hI^yw>jYSN07_o~Ng5PtMR!ZiwRw$T5`1+V07R{iUv; zhg!J=pgooYR{o#1(^-FgqQ{;6>h@Idn`NBtcjpq{+8H3O3?8eHCL1f9Hf!hj22o!J zCSI-?p;M(W;aKZq_|niz9p+~izL_BZg<@BTeN6^*A(AB>esSDY2U4W6^UPy(4t^u} zk@jzi-=A8%<+LTDqi(Q2(on#&+Tu3uvZv2`Gky^$ivSE83V+Q7cpFDgNpVQ;antge ztZWSh$sCGnwtk$m8XAKop$Wlg=#y*SNvpNv&HMJ6%u{B+)?06ToL{%IUng0NJr>TM zb%iPmUjtw<(3Y2IR_ugmp4P5zc216HXhqjh2o4%H_a3+fQot<${)3>opwDvS(4sB} zG}I54aBh72AR03SAHxv=Dda=DhM^(vLK3MU2B0q-El{+6O^iL3|FrnQ&Nfa-=Eg<> za-##UvMczwUR*DX$vNzycC?B$<^)sfhxahd=ZpAq$Z|gtMYB%Vk@V%)|EFbbh)v;X zRG%m@%|Nh5oJ2_WS=&`Ky_nk1VoABSnEU&REyo{nbW3WjwgznRLK@5aDw+6)<&&5) zz1=&?n~tC4Jlc&mYBr`K3HSt1jQs5dfK;6mh@^&?f%T#{r`1Kh@^~NpJh}7X z(|W&Y%;|aFQrXHw?tVt-UBXo76bIE=wYy4`M1;QNcbl>|X{Uq#zobpF3~p} zTdZ@2^hMi3P#yy$TX;EiR$`Tux%`L4+YSzu6ENPC{S-dG~cP+65)V0MNvw zp*%qd*lSqqD+!!+>r~=?&+{e|372&$mo{x~)6@DmLv!RYyPN-9kHLQa@Wqq**F^bt zrB(=r9iMC6s>iMWJt_%C%Df7+0}9XvZH|=wF504713&Wou^2t-Gd39d-0%ChXhpWC z%cB%R`%aPRW$!|^Svgeg?*zppVs%4=+&|1w5Us7RN0Q=4oj!d=WiG-5_4>xb#GT%a zc1;O^gOy_S5KqFh=FvXFCXuq(4nHP7`5oKP(}^grRs4u&sJEAqNB$D^UWXO(_O_?A z5}#tJd+dIqrFybv*2yEt%*iHkIzD5_)x%F?(ci%)p*SDFax34U&!d(LQ&2FRQ#ScjLZ#A;^%#8& z(W)xzTPd`=pO}@MDt0GT)hVr}ekyh;8gbW6C%PeGos zZ!;6pb$foC1e=`QRDBY!;M>cjAW=$YP89wPJ%Wm*0E%lzJOocYK<`lnp#r>Hcg)AJ zH*JYd;~W*`FdkEeacaFnk_1wQ}0A z_;JWXuvP*gg!%T%@5Jv4;Y|V$lAq%r<%EYfZejM(Fi#=KEXl@+kOdgk6qq2)0;jpb zA<0}rI(UnsRIAwKai@7Pk!Bn$T(U3AS`|Al8yR7qwI=zHaPDYj>Zdq8bZk&LR8d@(MrL>4~16=@Wa=~Fcwuwp!m|nq)63)ZHypFh#ufI0t|rY zCl3w2J*N^S3k@0bs~?$J2_}jDrZgkyC*jR#8>=rbA};dQizu&QnbN(hqw(y88e&q{ z&hPB{QHkWX$a^?ir8`tE2tF19{mxMfC1@meg1^g#&T`ZuWeKhNhUhGtbj4*5@8h$Y zua@kZuzgKmmbsi!N@3r+KYj017@w!Ih{x@yzoV|m&YU4LfTLTvM)wuHtl;WyrwxMa zNVFCWo>UJVh5dpOt`U2}HwU35;F&0cm=q^<4XUXNC3YqzB`UmzR#91}A!SKOrKil? zXr3ulZ#OZn&J4RRF3PBJ4;kaH`1 zI@_r}WJA$Xl9Or0pUl4$-qbzh=GF-qD7(*6Uz;mSj0wnQC4Yz0M2;BbLQyu%#l zaDm>?As&Y>eZd^zAcWo+BPNB{FJlIB5JE^jG)S9&V^&f?KCvQYNiQfSDMGkgQn44& z26?_5OtZ5!_0(lcFOOq2yEY$wd7gbcN{HZo+5VR(p$7e< z7zA+|A_EP+mxwi|x{s74EA(zV2~F!Av9f&0EV~E~t4&6Q-9I9{}1T5;I0Us&FI);ry$>oUG;h#IPV!;=X zpMWozo5k9Ju|p}w!Sm2DRx+@LDAU37dJJ}-DlSr*3eNIF1`kGGee&hE3hu(@Yk?k@ zX+?s2@}!wK$}>YZzXUI`4_3)ha4v9Y&PbUl+dsG}otfWb_ZGpfoGFiMC!@AXH>t@P#()4)7xChs4qF;%V$?w|~P#Pofycv$O`Zf?L zON&`Gw(?V$$viUwbgtk9Yu^}e@XXv}DCzDU< z;CjKc%gwM2Og~3mK@)bGGO5z6Oy-l*j81msp1>JArGqMkUE(9rKoia$d1wWc4hr;A z+bGT&>;y_z4pv+WX04OMLE$gGt0tI%6fK@ue9o~ovYIES*ZOAHxBA|g(+a5%gG(S+ z`MNV>_y9iT_vbnrzI>AvC$ECYB(U|eIn~G8>1SKOtVWSkC_TOPYn-xRm?jgHfsfdW zC@T}zLS;>dlx65Oi8u_nE@YiQ4V7k|?|w68eRnIyR#Ew;>_F*!d*)}7Bx{zb(CHv6thjzt_%Uo6{mhy&#iz@VPoz2!{ny_NM&vWl@XtE}tlh8P7ZL zbti^EyVPZhF9oB357{R4i^##&E!D^OvwW)LWQj4RsT&np1^m$qsi$Id9ZH>GI?Y z#a&Jlb`&)~&7#A6;QTJ`h@y4#jjdd-;5hS&Ov@MXI=&E-O3yx{<#;OuS*VBw)Z`;c zDh|9o1vkzPbRROcJr3xws_;p}-g7gH7`(}!D&fWt6K(b5*m$~1ALSk|m8J1gvL>UQ zhrEV1EZbp-^=_ZAPuqCWQPAy_?Z=9L0D_!}SvuhpmALb&x1qOWiD%&-dU5wSfW>~R zZ%-2wZf+JWHKU+NBnuaMqbXHwclq@`=Yax^2l|kz6la=~!{hktSPB9z$ zgKE zITsFsYoi=ZZ|{Y?-28c%K``QD82NBeA#_T*Z)vh8iA0cRt^}bJ4T1Kxuyn(hKjB^3 zRYO_(h`r!z(|FflU!>V|_xpK_(CPj0y3!{v{EpC_j0OY)kM8&+TRdOWc;bxMr+|jj6jt*|Ms~gIlPNbp!Gx>7 zFJ(8GfMZV!aGu&24H{P;eVFSZ3x!8F!;9>Mpd1U}9rY9N59Bi76gcg;(Yhvjh@8`% z^DrZYsGi9faFWYB`Th*dYma7pxr&)+lihKXbFuZskIex-8;>uG-M-HscP2g6Q{Fa9 z#!5yAIO3oU&9GR*4|d>FoBV*{j#_S{^dPt3^{Vc?AKmRCZQ3TRZC6>GrTR1*)(^6^ zPSpkF-4E^<+oQi_`4yErGUn)JaCy7eBO~v=c*RaVg4mR50B7(8K93ZX>nZU7JT)6X zP!)lcUID*7eB|#wF7^`ada;6F+wmIJH{F$x3->W#$B1~-Y?+yD? zb@GAi%w)u8v@*El86&oCKM`auian%Gjy7l-V}NNg-{XHFhX94nomgh2$kQ_DC441l zqZ^;Zc&$)!-u*O3&Mt_qxhsCu<&C$IqrxP|bl*E3UPdmZ9b0GJw(+}+tBj)d=ccq<;#VC3AK~ zREb3{*#Ff*htsYN_r;V_c1y6Dm^&4F(0xtsM&loEb(LJ=`8ftBT6hqr(*!yh5=4CQYq>F6+){lc_g2(l zieH07%&(W~3oh&fuU}k~FVS^4k3W(%3QPfd${-d#RZXyf@}>C7{l}biDk)fGltRV> zE}Sr#5jsLf#=lGrJ`*z#->0$~elC{H;rx0!f^=YGTvjpeR{?8HOly?a*_TFa%%ht? z99b&K+Tcxn1Q-2cP=17f2)ucbAi)j_<(~&8&gd_KL3OBrAJ~!NB*JUeR-~*T#*Mb` zc^`~V&-sGiF{CC9VVU-~MGMDOO%^cr-qXdvX`sE4YJ6g@7l@gwfHJ%HE*&qSddW(QI2W_k`ct zT6bP)nBg(Is0roy3>&1rcQb7WnD8vbt7;Ly*{dXV{uX?I=x+!-yo)efRS_yg!W0gJ zm(CIYC*dpH z>h~q5Ybzb7$V3nX&X1j-(~J|~AjqDPO+Y)383hPJh@irh0*dh77^2GvFqBES{xqyI zU;MjW6JN)#4ka6U8A}P5$|*>V;=HcC*ymurs`|P96H&kNP|XuACk>7R&d0<#;e}C( zLAR!AF`{$9L@fxsznJK&-3_RS1`zF{Hlli9KJ0*vUi?aQ#^HdJ743UoH(fTvE1(+Wnu*D+{DF5Z$ESz`So>LR`;PvFPd0F zCAe!u9nj!&NTO=kI#O0F1=H1iJk1JQX@cH|cjUbc5&hP2y%?mm&PY^P6CjE!Zcd^lhQaIFT(~4@8?C zPL&#l`qjSK&uV-Es7f{oR8>PW$)*D*8G`Xe4I3>&H7k4bDG0vcIL5j@APk;JO@;z*qk6O+O7u1J2s zq@dEtz*rAYyKzLJ=ns{-1^z0i>P9I{3P+}*0sK{U?~MbyX{4;|^Mcr#vb9A;D9QLs z!R%0)>n>Q#s5mAO57H|+uD_yiWIl3Bose}>v0OpwEwd8->J#$QEq}ue6-!3_8Y*#w zQaKv@&BBc&a$3;lBX^S^4BsA>GQ99rD9)1jiOsxi+Z|Zklh0?tJ+Ef@_d2K)Z|E{z z1f=Iruh$2fCJO6J8cADp_>rk$+2dT{`2ikRd`jSf4;7XnQHH_W&TdrObpx_pOuyqg z1LHh%WHPHeWW_b<8dNN=AzG1*t6#Glkv^=*%;%5#UG3~UHI!8=+pBkqd;_;gOpV!J1-?V<`$VTG8#6LNXXp_L*sRz(d^heHEb;~^G3UMzfgitM*)B~&?y>5>ROyib-+ z-hhvkRS_AeuxhTfYm%@>lixg6KC7YBE$TF@`>l>R_ z;a1l@t|s+^1OsXRS0j|xNCcUyqV6#>&Q3TvPYOgu#2DU?M?TB}6r!rl?Vph|Uo8@D zkqfQll67tM@UY`9t*2$Li^a2K(A3t(31`QQpHQoD_-`r}_D`x+uB&rhSkB9w1-zE) zw24QMc^W)|M>mnjqdbLq1^f2cmxEAM3pHK>Ld(pf%ulQg2Ww8^^{kr*Ln&)DLnO%Q zpcN*6q2A;OPx!b-_Z_SW{RIrz)pCot^IM{gpxzhjN^L)nK^uxNL~j`|DEG=5w1 zjT>eEa0!pUq4eXy$5_8dLt(seTrckaIhv0l6h9);0kOj64%5x|9M3Cl569hp&v&Sn zUEhC#yfNfR{a^zM`=oitP<3-D|30L2=I3{qB;r8n@T>a*`!lI=adXxAjzaQ?fy#1qaJ zVKr14vNsqOl1%mZe{Xcs`W9i`YAz*xzNO!W-tNI{a**?$Mpotr0Op3kcULH0qK>6e zqJ4L7TDx3H(RQ&ba%1D&EFn(0FG(h2Upe6q-FI)+em^^YZ2RtwCi6wrprKfq`|Qgx2AUH&&!-ztG^nE+~G$hM-!ezrJkr>_XX|+W9)Lf-w5; zUTtF2G+vRdL@?}wd(^$dQJ*NJg+w?y6s<(45aC|8_`}AiN4E?wK`u7F23FB6I{X7;Tqqza<|9mOPlSd zeq`$DTQ1}IJPT3Qqc-YWCjz{Yt#Mwx-8&C{=|BB{O1tlOs^9+s;4e9J@Ul5LGP4en zk#($N<{+c&kr9=YA|oS_J+etCTS-mJYhem!rjh7u8+GsoOYRztw)*H=>Ci94PV>5PWCJ3c1pstRR)p9(V6;yKj)9^SXC z`LQIPdM5RmnABJCo;j6bX`M62^Zw?t>!K~0E#YmV|3#P94wwsA=-gn0fs+w8{3@Ph z5KkZ|8vJQ5^g=H2Av+&2$wYk{X_z*g`WW^Aw|!WnRWI@_vsM|7wQKr;6+v=r{&XbH zENr6i@gHR?^y>YI?r<2?r8)=yE@U|dMd7YjD@Z6Np5=aU1fz=p9><7eFVU!v#s|1k zisepUS4pb~(U&>DE3A)+aSv{MQe=#X@pR$$+CRLfE_<}G6$i3R4?ytmR+hPcANj^j z4x*|1xgoTRonJREFqdqin{M(rITvUw?R|JaZ|z$F(EvyW9FgZ)9s7c9Dg( zAMe2_Mc*}(zliv+ijK^(gy2mOH+~wJz~A>+3dz7g#LzQDP9l^!#xhqb`-ga~e(E%x z#^=(}2NiSA$k@4g+j+{4MWiL(^CpGcUf3sV51je2Yj6z>VvZnv*(oBV<2Lw*he=2TsH~0RjPT~fSy2z;4w7!YS z_SlSDk>AVv9iFRYttgN{n3)-v(4>yAo-xzSun<(u4%-cK=p5hs zi&)!zS&ysyW?kYF{b%yl^S=$@PJ!ow?(&(vpEn(Lpgv4vi3!W_^(7Vxvs5?ub?MT5 z&x@+7V4u6=W4cvN1W^ZyiVpc^gB9%$>XNzL)@#Y8sYsLii44Y3t}m{tt*nknH62d# ztJ_0F3=F%Bp&a!2pXW4!uT;?9|LbApA-dO%P&#nQ38rt^w}nXGD~ zyGY{~wgrk4+SikHuV?$Sz5f$?zSl0xqbEaieNaRy+K3Ay-JOB;G*_?l4wDVUYV<>J z$=3@tm{f#iFBq9_{=5(vPJ*zy1={7k0Jh`RafB6tkpcONt&r>$0e3Tsa$mOli> zk9~&UXR}xubS+@GIf;D*Lk`)xtHB?N*jq4Qcxwkmt!v_0mezF-q}Drcf4JS6?N)W= zQ5I3l-4uJZo5%#_TY6;glRpu2qNEs^FLxQ5uUsuFD9&-E_*z}pP-KqPASXiZw6mkd zsR@d9{v$OPTh3G9-|WRZnX-Rw$ouXtT|R$q_>ROSwRiEcAtG))GdG{0z2mHl#WnRo zTJv?J(7TN$4r6;iM;%{5Qf9^)c;P#H5@sE7i%LuhJ~?227fwgO-KuwHs_88mwYi(D zKH;sb-mSvhbTRpltF*JaIJka~g6s3w8Pw_$Fb6(s?lC+mNmMS&_?E21ClDIx6ZK=bW3lFRiz? zSe71z9$IYKHaT{kJym>j?(=`$#rh;iGDZV&`xn)e?u5A?v$U|i@UKor z!A+o1m()NoZu4p|JdfhsWrC=}LA!Y;O5)*x@XO`;r4nn&y;okolhwg|w({fQEJlEaD4rzYU; zqN(+6NIuTyEbZPhWF(`dKOfyV-5OfPA-m01Ofgj35vHwvI-fZk5x+}msq55D)aB8- z>EO=qzE_w{Bk>mcH&;!B-_&uIqaIU%;_8(f5>^WN#I{%5{$jaCzu!7}p>d{}-JRL% z;i!8_NYuMo{P%5d6aPFCg(BgDmB7!nNO4x8Orqyf0v+mFQ49dt{Xuf)9EC_W7kIa^kd`9<9?J6y%I{FrdWvA1zGN-7NTT{hu!1-ix2%?+}24A35G!fkK zm215~4sk!mg&+R>lWV)63Gsj$v`-}g+)WrW#DkaIpXlK~uekG3jv&bS;6xS5+Ijon z5h2~WtochP&!U4NFI1&)uxs@M>$@2|$m}Th)P%-%fUr{LE2O(mahkX&aS3Msdx&VH z|Gh_omCAsqLdg-K^A7rOMmhIOvKNpu_bMB*wuc)nO^0}>N1FxLEpgYOelikp4-fWt z|I7v&Fg>ISk?igz93-5bvogo)$f3`3rgHVPLuSuiM4Qq>k9Sw#-h+z? z_+^6P;|%Yiua1QSl7o_qO}`nx*R$x$iZ9;voOR+(()|5)I%zH-FP%6?;*PhyQ|&5U zAVhBI)z&!a|72I;2^N*8TS5sh#qtzm77%WNV*T*T0-j?0ON3hjxZ2%KJR@Ys1V#5d z3Ty>YW}}Ri-BHf_8;iAcHtc>xZ)Hk;qnnxp58ICP_BJcq`+ZfW$K+%@YbeJaRQj?h zcYOKPuVbzIhvxMG2>c;)CV9|(NQCN;`v1uf$&fPfy=INUi4cwaIPKWw6Ir4 zsK??>J)Nlp%WJ~$=2)wQWzV@50q+-q1$Yw&3ceP1>&?F8;O?HOE8pf!$s#VxRGH8{ z%HvUKXVtw*1FvN9=HhQ4Jaa&g9#hL(g1Lxza)p)w(K<}TK=qJ@fP1nVhxf7EjK7fh zJf(Bkc{pKU-y z%7HZ^H@XAwuknVHxj;CqdDhKYo_{%b`-++NE*X*H7Hve|8)f`Gpo~`I0ql3^QC~LJ@0(l z1vsga?`^mn(uau+#JZaM`Ic7O2sob{8jQ)SP2Q7*Vtdx>)=U{RBivt0^OP{mDY3uG z&&1oM=P4+%b?<%V@aZYLvn5;famqA6*m6e23xmpK6{5m2?yHjqxFOifg5BWvKlsMT z>NeiIs_^$c0}eE5_>qdEV>-3?+)2^hG z&j*ZD&5=gei+H?q*>5_1KNOUuAR#18z-OKOyGMWCgtn}7?*9&M6%ePDHMUtF^% zAznh0t0nBwc>P2=^W9PbI&B!s6#1*IhG<&OnfAruIi%Bga{3zQw7m0eyilO!;K~VB z>IM;G2ORue;5o(s@!TBL>Zm<|TCz7#AU6(;?2W;oC%|APu$*~rKxT8!3;F$&PiJ2tI|W|mm7G>h=Q#8ZI7WVhtCq9AZ7+jBIDdB6wpwVLFQZoj9m4ko_zO$OtM5pldbSt7etV2DK`HJo8?HYoUU+UGs!%@;E z!>|S;!=Fl2@HLuqF7yU_I4WlC*I^{GZQhDpVLh)#{+mt)Ok-vXQbA!mM<(i?yO#4y z^ysuz)xh@*RvI>DG+flfc9@x07o&HcoJ7^wwD`K;zTtcF+%Iu&(SV{$g7NN^+1WDM zpT(H}Mlp*!m@=|{D1@603BQUGO#U}e4;7}*!f5Kce2cUdPccEolddw!dNB6SI#8NO zzAis?^&_Bo zf@pC8L}-Or51d{v2m;6iT$rB8Wd zhTxb%p%-MYpeXKX7|!}7)B$3#tF*!JMxgLGh!5djqzYa(^*iiXu6jREcWC)_b~L4m zBnqQoJ$|5Mj+R^dJ+2;l?V85?gFh}@KcBwNpZOXjwvCl}cJ=E#1LN!KT>r(hy3&Pz zgT^IV0yK^FpM-Nz7laA8=&2Vz$;#oy!kz-s*DUAlBr0!*A6pXg{j!3os^(IVybF$v znJ|?b-b!42m(TF}>jwzY)hla*bfRGEYlKq`mevJ9R0@iMm-~cQ@sUsrcODl!ydu2U z#fgkXY0?J4{b#}hWV-~#*iq#&j&LyvE;WlsXgocQwi@e!+gtV4tX~Wh8)}90>U(Q- zLX}?V@X>bOPsY3>I2~=1l&2!HXY$A6xe?cNPZ^QfDVH|Vp*Zd;LAa;v(zk*vkR=6K z);QKLPy?13w%7(%j);quB6oA4s$U5P>VZXpl!?ukHVY`%O>VPqc#b!w6-h|)icUPe ztu~<(sc1Y*D+tp#&?Zg6#od?6Ff&j*Hy<0kw0J2M{}GvR!GZP!4m`coMRr2KC6tF8 zp`N9Mes#WL=xkZtr^G0KwM~32z_yc>vXo=jVrg&WqM5kBv#Ddiw8NFB!X_C2PautC$hi(HiFYs5~atK{bps)%-rPP|LT=n;CP9; zU281!qp?kSGvbkCmXTvb``cZ1+kN};r-IKB2N^lkC_ceQJnjK-cdVlX9k4*q)y)gpJp&93e;+&Cvvf&u$! zl4VTf-^R@lW8HnM4LLP9PIWSPO;hVBV(D-Bo&>+tdqilxPHz`I(&JEU9c?F9%gSoQ z+Gx||%2_-YJrg2)jAd+>ya?|chL}l_4wPD9&WhGBZ!Dyi1}}CrqqHITpxFN(9s%t z$?Zl5C%nJBgrWjNzL(<%hOaopFJHMm*siyJnTEzjY(eE{>%m<-+)^^CTmoJ(fwH3egx5>V?Xkw<#Le)BE`d?p61=mWdajj zFdFeno*Qu)e*Fi$*02x(_o~^D45R=MH8OkcYT5w6L^6X3U7r!Y|HnNR;SIcsG>FtxJXc zkt2!@6aqh!!-(!WFzj&wDGbu`A9qTBEO787Q&HM}SwVBJJ1?&Ar}1FJ({650KQ%ui zU(ON|DRhwvg^z*Ki`36u>GoVxFX3FR`|gUh^xEJot|-ZG$f8lvO96;<9x*yNa8vXU zgfh|xKt~%8A{LJa*~?x_smo&bZ8d2zk9({(g(RG5ReJUAn9t}p*X(6m;?@`}g84~? zKIA&n__n>+ep^zEnFyoGSszp$W-bVDSV{h`nM!#h2F^#O1*O$e2-*1>N{4zDkc@Ud z2+wn+NKd=6nfp{~jy0HyOM>cCQs!z{YU#zK6Y=S)sZ)LCeDUHG|Cs*ou=Se(JKO(y zq=gExZ2T?68$4}4GQ3|5eGTjqcrz7jkoj^bsF6QecX{qJyGS(8-7rteBzwy7rtLlc ze$CM>y55Kjy6p5DcKL@!nSt5&+MiGLv&85)(O<|TyAOIK_k9Eu3Bq!@D`JggPY@Xa zAiD7LuUI~qL1Y>^!3i(Lr%{vOrLvGUeidIP-y8}mGAmBWd6mo8yRi4_tn{k5hveWF zQ-#OonMrAIieaf&NoY^?EkCbJD7?7S6V?2|M9eLz{n>xpVtf_oq|oqAiFg1i2~^Rn z;pmmRWnortrV@o$(j1dPooOt^Vq$u}dc*xe-4EX?)blkq2PFw0#pv&?HcSqOO1;+R z%XnP1U-F=WG{t-O-%_F~eAp?TjJibuvb|^B&*bUk@lXME5&XR_vOUDXj%n<%d)>jGej}OXJMHwNcb%z|?~89iXF_^rxN;eP zPdkgW2k-Gs#dC@jV_1zwutVTjJQ9B_JtSZk znx?*+cHTFMbEblvzG&mQeTnxoIuep6DN-|a(YI)K#i!!f`3nPUv=i5D?MsF&Uj8@O zSud1GTQx!Co`Nng>Wf4H*#ZHV7p`c0MITFdvDs85`(@bH@6g4p4ENibER~N+-sSMQ ziKL;0-OsmKinzTqLLGBaitaynS6`o{P)6|n{qZg@NHzv`2h_|;yu$n?;PMsbQCg!} zJ#BGzSLr=2+y7|@483%J*r=s(ma%j$Bxfo|qW?=WElb+|+TLt-J@00=zo4evJ~6_4 zM(o}g{rmsw?8Kf#14apvzeL;5kQQ^L8N_X(z;%CH^f$V?;=>e+s++=q|71X@F`M$L z@vm2Z`|P$u?&OkN_Rlp);R6`IlAXo$uStlOE@oIwgoZiFXH~?=|0R0^sx5S%%1Rzg zN$2ygY=nc%Iq%f{ckW(eD$&%xu4FQ4KsL?giS7>77Nof|HtughSzp_`7PI@dQ74^j74#cGps7x;^L@UPpp(}Q76WtslPy!nyGxPVCBM0ou8sr09o#5o^`R4+9T27Dsue*yRybx6gA;k zsYZxun+)-$I`0_XER$M75eY%X+{8Tac&Ah@>K=#}mkits_H?7%r~J7YThkJFt~8)t zdYEW`=I@8KYaJzJEia<{2t4J|2(G1fQ@PQO_x+VLO@(#KhS>rGxRm}n=lI#^-X*BSy8roDyTiuvB@vQ#A3?hTNIOne zxz?$#`;69+u6Lx6#}uFb3w+k#9CXrf)SUE!BN?K+70gF>4y41u5`*F={bOf$S5|Yv(BG}~=dL8=xWg;HT#Fi6 zXX&f52G!-(%QMBV`@OK&1;HacrN*b6LQz~_YB926p^Fy-4r2xVXc%9?0r4`&V0rM< zZ_vaA6v|{`oC%5*U0zVtf{5s2W$CY7Q3b)UR=7p_J!O4re|HtwqX6TrUjKV&=q$lvw4^h_#EjP&&To~8B0GgDxoha)su`I%M_+%~T`bV1}&QtO#Jtd8tyzGz<3 z8*^=y8C$y_PZvjZgE7eTT^Y1C7|2#-SP#A{tT_6ZP{eCOosy&0k$Z17a3J|D1>=Zp zL&Vdsh%O4DSjN;|s7013VCZH{z)*bKCuNuO5G7sn$VMGj<2w<&@krQ#}QU|#XMND|h&xy;~oO#bBTo(_i7RX61 zQ{E2$_~!!Or~lgG^nBSvObmEj^<37C7Z&yR@7(rimR-F{-IpjriOI0~TpyhuTM{d| zm;6^Dj5cO{X&;Yo_%t9?(5mVUT~2+CT=>-ZCFTR3`d=lBv28%O#5y#qzx%)*em*W+fdO&-8umnbMMU`Wav{T?x*cyZa?MTd{)LhYCkZ#R zRc_@MP?>~yR_3!GOq?yp;ZbeHT<0w&?0AdlRVWx-X`IW-|NFdkzh#5*&4`*FIF`E4ZK3lppTSvX?)yEFaPat|eDkHW&owfpS=5u;bBDH{ zr`4Vv4E@SJv?IETSsOTb81q7LoSYkhgui8A3n}eDY0i`4Z%Zg!1TyOI!749~nKgsV zQeznu&Se|CowAnK5n5p@C)OGwUlsCI`8cGiEV0p)<<^UwE^RzQ_s<{my`thxWVC~$ zKVyHPI>DLqb+&Yc@f~D2emYm139UYRsNa3B#)gDc6k7WXtJzpf-6BG6;a^%z5(*~# zp^A@`%-wMlk5s#;RwpSnENL?BYN+AU0qm>Q*ND0aF)W<+0~_P`5~}BZOb3_v%jIJ1 zpayOM26!Sxt{(#ta1HY_*X}0&l#AS^3Tu2@Z>-79 zh&cZ}k~`X2^?iDrmua2fTe&vim;I;mDU7j_!%`3tTv#SI1Oi2k+{P&6^Dem}aYU0S z?MDJWcR_BR`M-nNn!a>76dXw@sKNamfkddH4U;d+)WlQv^|i*7Uu?H-RpjRslnqlX zB!oH5{7py7X=;5ky-HB!4!bvmAbZEQj*TF)Wk-l>1Q)>($8s+)=Mc?~V3eAkAU}c! z4_~zi2$520loXEL3A1yhar3>H;dZbFRlIPsT;oU;{<9~Z(CO_Bcxl=d#~zNEIy_L4j6GnP>nD`cDe0N5kb zdK-+?yJqFly6T8FT3QCtzCHPFW{3*xYiTQ+<}Rm!(_<8l$P}S3+{wIf+B=1`u55y0 zySjPy$I|3FGl+Vglk&Bc(5o-^ml`}5_hn@osk?VMEF{+6T;Q6?KIzfda(X|#7;^c@ z>qm%q=Og{>DmC#V-3oHJwpk(K-$yytdlCJu_ErLBPlU$p^IfucwR1Zzy5CA_zzuz=|!D0ZrE^^BcHv$cEeG|xwt^B-;R>!kF0=H9ry`44&#gzI$GYzTB$z7aozV7tzY(jQ*V7E>w$Go+a>+!z1y$5?(lD{D1rS0X2I}K zz2YinjG)-{*N1o9xl!hXV>hUmvxVyg7{W$ExDVDIrgzn)Z#~IP%ybwHz46Ow?lQyt z`)8RShF(}=B^eJF>*Z2&BrA2*DUnU%is*PWqPxJLAAU|yB%oxO5Ir{BvP|%Pm{Qfh zEp9#gyKQ4J3k$Id1ABTS1JU;^&MUk?8j}ZfiT)@cNAXvG`;9VVxwAOLV;?5tmB{nw znYWG2+(!QY@rd)Ai1|^woeY&djaB;0t zd^ng@^zqfVsIz348k;5-j0Qeuwf(`L<4(qX^Jc?hM6$sMMZj6Bl@FIMtSys$aa(eW z>!CzoZP+y%Y8SVYo+h3S3amym1ieB1RfE3_E5$i(Bl^a~bm8eWrT#7fsGs{O7-BE`F6#@Clq^F9T&&bhuY?23!MDf8~;OQQof z_Sh*@3RdbA+6{)ozT(<3b)dNBh?kZ0`_ns@%6`d+x!#{>ltr(OaqKO9)(Uzusgkb`Obr3W-7|%9%ewmHi ze<)vy*Ug>`zHs+@WUBSD98S(gvM=VXOBV%ucbBVc{no@yD`R_cdrfz7OZuT3?q!p@ z0c>#VC*^p@L;`Nup~0|`FPSa7ULokd*IniFZ}fz!CPN&bz3~Y%D(MkoMgy02jQtc<(PlZi;M^{@>DEVvk+@^ zsGQk0aXg7?5nK1Hx~8gcV7!@?j7ooelz=rs?*@1D-qXy3CK4_P-g zxc6`6$OsE>t|-4pae?-7z|2ao0 z3uGS&iW3qqNbdH{r(>QaLE4f(>@;F54AjKwI1Gc6s7XRw8aMJPqguP@5vSFO}$OI)XVwT#FW9=|zc(~YBA!BSQ;dFaFP06hO* zwHEb?9GXmufU{auC&7O1DVTN>KATkifDweIxaIia(rwlJf)WC5+L+$d^oB2cm93xDZY+&s zr9Kf+Jwzg65=k=Q=?Jw7M;v(m{Ud~9Bpkg_zN;%a(P)e|9pw7@TW88fm-96Zsxs%L z`gyBcq94#y;|~y~BJrJj!>ihh=2*k4LA6%ruAH+Mq-2*wKuIV82{sM8M5Hz449p zgecbG?@Bwhg6Sadson+G!lxWrEn!+kjLWm;6W;T~4^~<~M14A$6dmY#TlTU^T%pf< zCH7V=xvC3(;en57cFylB8m*+E=O2&r?yO>k(4dMB!c z8YBoQ{v&UEv1>knt@Ku5>Ve;?>){Wk_xz4^8IRV|T-PhE?`vPsdKxF&&T#eF1)0jx zp7`DG)#_|K=Z)d`b&SMUF#nMBheuwk_x+3Ve>a*}4w%K^X>UGP|MP$k_|Znqyi-&fA9NBv1#^S}8=ex>@mF0fei z{ag44)tzb1hZ5g@DDUyqnkDwg;{xREW(C=->jpWBi|E4|auyX%Tor~HEc|*S`trW( zu!I#0k6cfA_>h*MD+I&C1L|jvq0k(60~I{}L%j=iiw!Z)&uu9H=bfpq{)<=7mj;uU z)slAaGF&XoQKcLZagWKn^>ZcFI)E}TrGkWds`fj@nMxV2Q{-zp4l zq5o4_^927lbhW$Gj>Cggm1{dTg~PfuN--A+ii_?scA@Nj?ea>_jcRN|Nw0DRJ2v{Mdn;sP z;ugbVvovyr2OUi=b$F(SVuMIcWIyJ7vMdtG!#z#@x=nREK=1{<)I}m>{k#U+07MTL z_jk!#HE~a)I0L&n{Uc@W%GOutc`alW^Epnr8s9dDh7(xrn~VHvbRZcJZAD{>%K%0YYI`sb=Y zY61iaf82y_J%eNV)|C1JerB{hDp2P=zPL$K$4_>=QI%)-P)*V0KGz)*qIHF=UtH%T z3#d}|r|xZiw4R?Ey?OP=i*x^;|EeH@J6~v~;U@@+Kh{kYPLj@7G1dr8>0sr#-ER6- zZOa>#4V=HX7-MO}!+@y2EbK>aarP(Cq-+#<+4a2Uo1ab;8Hojm7L4g7!4WAEJLL() zW32iF{4-AzJh;LH{p6-X!@G@|$(VD{YQ;S`c0#iaJi4p6x=;2f)2DSxxnV`RA?2^g zYw}2mHzK6>x9uK3$u*)1D%7q`EHOqQ z8W)yzk&^^X^h00#e>s_vS;hhhDJAV=2YJW<)25N z6dCt8aEw~j-}{w&#!`{yh0tJy~3!*%~{(4gf&l1bgv6}+j)MMY^Q_UEr z<6MDfRN=7T>K`oxLAF-Zfa0Q+l!8hak5F2{nQs!^sqwrvMwXw}A+S106 z*T1X*Khi0>RTE3%5L0^U#JB6FYjM7Ir(&1LF)Vz}e5``3(j(COGHWX0*D=ccnu{+q z`Q1t{I9#Hjp!BFtnpa8auIl6Co==Pm>0439?Tllr203~16P84j%+NQj)2n{peya(?N> z=|N6UWZ%rqNQfE2V_=~H)V8++T3_*WU_vA%u_{twll>%t=}}cor{lXPI?eBFsjNJ2 zG{_y65G_BNUbGYt3sO;s_WEs=P2|sHY%li5Jx%6L{`ML&{H$xmj6C_Fh4v7Dwz$>R zV8WSJyW=WBajQtShbt|AD6cX+Hgk{qtfz$X3A@IA_g|L_-pn@2r9auL=f2TL2s{&v zZ|~7sMLu{CN9U1~)Igvy_4y(2#ZF5LS^G*GJtPKFPw}A|*fHRCVh{AWqPcu0J=rzG zpD5pyYfR)CbFgk4jd8iYg%o`?72#_oi;@sYj|S^h08UeqCrnf$8|vRAmXz@mLWUhk?Rx5uZv^+S zVGNY>o19Y;#LGER^VTEJ>J@hSQ*%^1Xe8~_Irwn(q)NZN_lp`m1=cd@Pv{neB zR!|f&V^#;fjEDBQLqy=?U7a<&4MFjM?`za;1A4(@O#@-4L+@(8%7f~bm#Ac3okmZc zv#A^xVh!EH5lDyO_TVtn_9d@BHFh3uLxa0sE&NNVzi_&XSa>b^S_mou49pJ(_kv=2 z=jSUY14nXA?E@5VvWVM!igWaNZ65K+Wle6omLgtKFLU$_XRA3Wam^#!4-Z%U_$H~L zJB)>5rZzEH+FsdT@ZQ^N37BHU;Z3m?IJ)WDY5@oq9Bzo3=?VypcRai9rPDKYA*sK{ zNsE(j3LiFP;rtp^f8J4Y#jjbAHi>>swnvZpy1bKKdehhU%5rzFZ28^|PzI}74javC z&}Nq!d@^zE2(?cJ_MHjPdLfSq*U%6b;#dgW+|}W_t7KV-6D0WgZMNEBIX zr(1}^F(6MB48ShCu@T*7@Z9NXE%;6PhHfQB51c9Z|2-#*@mobR&3K4j3=5r@0OIc- zZj=PPmZ7&sR)RQ7rVZhouGR}@hR8@fX=(oik**Hv9fGWt5JV3=1bP4wkh3fT*Z}m- zLC^<)2BbCP0Rn(!;1Dnd87Rwv4gf;}K_S2*un$m>LeOo%8<+tI00Lx3V+MSIabOKN z1L%g6py7s~2S5Pu4cG=q zFG3I+@B|`(44@pK;Q@6D2mrnT+ki1I$c_ed06csUBm<-ae*p`A2&xCr0^qX%QNSvo zje#I*;4u&etOJlB1Tg>}Km_mxI0meQAjk#i2Nr-mz*HE5?gRe7EU*QTTmsh>@BoH^ zAHWGIe`7qyRg>`75BV175%j;5R@l39d2V4h#WOQsD1_UEsPjC>v-7MuA^| zt_*m;fCn%P`~Z#tQ&~{AfG*$?7J`%kBcK{U$wAN)U=&ydG~^-39H;^q6d*_dhyZ>7 zYKovNpaSRuW`Qk$L1+W0AX$L+JF&I4WM*D`9L&~4V(e=*TDA=3;~yQLA?Z4fopo;AP0a}AJk1C z6i5R~fL4Il0OarnUIS&o7XWh|TwCB5aPgEt+20Q?|fo}lL0=y^S2%xeAeiPIQpa-~Y4eA153fu?$fh3>+Ahm%YR^T#_K?K?rnHyV^ bKW6pF_h$7{^TB`oU;j*w{UdqYuTK9D#;K25 literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/nodes/CURRENT b/poa-network/single-peer/node1/geth/nodes/CURRENT new file mode 100644 index 0000000..af00d34 --- /dev/null +++ b/poa-network/single-peer/node1/geth/nodes/CURRENT @@ -0,0 +1 @@ +MANIFEST-000097 diff --git a/poa-network/single-peer/node1/geth/nodes/LOCK b/poa-network/single-peer/node1/geth/nodes/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/poa-network/single-peer/node1/geth/nodes/LOG b/poa-network/single-peer/node1/geth/nodes/LOG new file mode 100644 index 0000000..dcc2d5b --- /dev/null +++ b/poa-network/single-peer/node1/geth/nodes/LOG @@ -0,0 +1,379 @@ +=============== Jul 12, 2018 (BST) =============== +11:09:05.859266 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:09:05.881724 db@open opening +11:09:05.886827 version@stat F·[] S·0B[] Sc·[] +11:09:05.902200 db@janitor F·2 G·0 +11:09:05.902230 db@open done T·20.463441ms +=============== Jul 12, 2018 (BST) =============== +11:24:30.549578 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:24:30.549938 version@stat F·[] S·0B[] Sc·[] +11:24:30.549967 db@open opening +11:24:30.550069 journal@recovery F·1 +11:24:30.555568 journal@recovery recovering @1 +11:24:30.575186 memdb@flush created L0@2 N·1953 S·15KiB "n:\xbb..ver,v1870":"version,v1" +11:24:30.579660 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] +11:24:30.598959 db@janitor F·3 G·0 +11:24:30.599047 db@open done T·49.061622ms +=============== Jul 12, 2018 (BST) =============== +11:27:23.929314 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:27:23.929673 version@stat F·[1] S·15KiB[15KiB] Sc·[0.25] +11:27:23.929707 db@open opening +11:27:23.929818 journal@recovery F·1 +11:27:23.933816 journal@recovery recovering @3 +11:27:23.944145 memdb@flush created L0@5 N·155 S·1KiB "n:\xbb..ver,v2057":"n:\xdc..ong,v1961" +11:27:23.948584 version@stat F·[2] S·17KiB[17KiB] Sc·[0.50] +11:27:23.965318 db@janitor F·4 G·0 +11:27:23.965391 db@open done T·35.663326ms +11:27:23.969673 table@compaction L0·2 -> L1·0 S·17KiB Q·2110 +11:27:23.983676 table@build created L1@8 N·9 S·411B "n:\xbb..ver,v2057":"version,v1" +11:27:23.983838 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:27:24.000730 table@compaction committed F-1 S-16KiB Ke·0 D·2099 T·30.949886ms +11:27:24.000800 table@remove removed @5 +11:27:24.000839 table@remove removed @2 +=============== Jul 12, 2018 (BST) =============== +11:34:08.322462 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:34:08.322604 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:34:08.322614 db@open opening +11:34:08.322650 journal@recovery F·1 +11:34:08.324145 journal@recovery recovering @6 +11:34:08.351791 memdb@flush created L0@9 N·957 S·7KiB "n:\xbb..ver,v3049":"n:\xdc..ong,v2117" +11:34:08.356450 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] +11:34:08.382422 db@janitor F·4 G·0 +11:34:08.382467 db@open done T·59.843968ms +=============== Jul 12, 2018 (BST) =============== +11:53:49.053572 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:53:49.053723 version@stat F·[1 1] S·8KiB[7KiB 411B] Sc·[0.25 0.00] +11:53:49.053735 db@open opening +11:53:49.053775 journal@recovery F·1 +11:53:49.055338 journal@recovery recovering @10 +11:53:49.069911 memdb@flush created L0@12 N·3140 S·24KiB "n:\xbb..ver,v6197":"n:\xdc..ong,v3076" +11:53:49.071823 version@stat F·[2 1] S·33KiB[32KiB 411B] Sc·[0.50 0.00] +11:53:49.087260 db@janitor F·5 G·0 +11:53:49.087302 db@open done T·33.558786ms +11:53:49.089173 table@compaction L0·2 -> L1·1 S·33KiB Q·6209 +11:53:49.100536 table@build created L1@15 N·9 S·412B "n:\xbb..ver,v6197":"version,v1" +11:53:49.100861 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] +11:53:49.115649 table@compaction committed F-2 S-32KiB Ke·0 D·4097 T·26.423679ms +11:53:49.115759 table@remove removed @12 +11:53:49.115813 table@remove removed @9 +11:53:49.115854 table@remove removed @8 +=============== Jul 12, 2018 (BST) =============== +14:17:44.682705 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:17:44.683753 version@stat F·[0 1] S·412B[0B 412B] Sc·[0.00 0.00] +14:17:44.683816 db@open opening +14:17:44.683982 journal@recovery F·1 +14:17:44.689029 journal@recovery recovering @13 +14:17:44.749579 memdb@flush created L0@16 N·10616 S·83KiB "n:\xbb..ver,v16777":"n:\xdc..ong,v6212" +14:17:44.750996 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] +14:17:44.779208 db@janitor F·4 G·0 +14:17:44.779238 db@open done T·95.395734ms +=============== Jul 12, 2018 (BST) =============== +14:39:51.265662 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:39:51.265819 version@stat F·[1 1] S·84KiB[83KiB 412B] Sc·[0.25 0.00] +14:39:51.265832 db@open opening +14:39:51.265875 journal@recovery F·1 +14:39:51.267251 journal@recovery recovering @17 +14:39:51.282847 memdb@flush created L0@19 N·3518 S·28KiB "n:\xbb..ver,v20335":"n:\xdc..ong,v16833" +14:39:51.284827 version@stat F·[2 1] S·112KiB[112KiB 412B] Sc·[0.50 0.00] +14:39:51.304139 db@janitor F·5 G·0 +14:39:51.304178 db@open done T·38.337769ms +14:39:51.306434 table@compaction L0·2 -> L1·1 S·112KiB Q·20345 +14:39:51.328923 table@build created L1@22 N·9 S·410B "n:\xbb..ver,v20335":"version,v1" +14:39:51.329000 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +14:39:51.352502 table@compaction committed F-2 S-112KiB Ke·0 D·14134 T·46.026738ms +14:39:51.352618 table@remove removed @19 +14:39:51.352681 table@remove removed @16 +14:39:51.352719 table@remove removed @15 +=============== Jul 12, 2018 (BST) =============== +15:37:20.124805 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:37:20.125293 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +15:37:20.125338 db@open opening +15:37:20.125492 journal@recovery F·1 +15:37:20.131018 journal@recovery recovering @20 +15:37:20.167319 memdb@flush created L0@23 N·9030 S·71KiB "n:\xbb..ver,v29311":"n:\xdc..ong,v20356" +15:37:20.170842 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] +15:37:20.187160 db@janitor F·4 G·0 +15:37:20.187230 db@open done T·61.857192ms +=============== Jul 12, 2018 (BST) =============== +15:48:32.297828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:48:32.297998 version@stat F·[1 1] S·71KiB[71KiB 410B] Sc·[0.25 0.00] +15:48:32.298011 db@open opening +15:48:32.298064 journal@recovery F·1 +15:48:32.299666 journal@recovery recovering @24 +15:48:32.368672 memdb@flush created L0@26 N·1824 S·14KiB "n:\xbb..ver,v31169":"n:\xdc..ong,v29379" +15:48:32.370730 version@stat F·[2 1] S·86KiB[85KiB 410B] Sc·[0.50 0.00] +15:48:32.387501 db@janitor F·5 G·0 +15:48:32.387524 db@open done T·89.5036ms +15:48:32.391376 table@compaction L0·2 -> L1·1 S·86KiB Q·31201 +15:48:32.409611 table@build created L1@29 N·9 S·411B "n:\xbb..ver,v31169":"version,v1" +15:48:32.409682 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +15:48:32.424137 table@compaction committed F-2 S-85KiB Ke·0 D·10854 T·32.684737ms +15:48:32.424229 table@remove removed @26 +15:48:32.424293 table@remove removed @23 +15:48:32.424332 table@remove removed @22 +=============== Jul 12, 2018 (BST) =============== +16:05:29.052109 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:05:29.052302 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +16:05:29.052322 db@open opening +16:05:29.052385 journal@recovery F·1 +16:05:29.053889 journal@recovery recovering @27 +16:05:29.070585 memdb@flush created L0@30 N·2723 S·21KiB "n:\xbb..ver,v33872":"n:\xdc..ong,v31212" +16:05:29.072728 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] +16:05:29.088665 db@janitor F·4 G·0 +16:05:29.088693 db@open done T·36.35836ms +=============== Jul 12, 2018 (BST) =============== +16:23:49.639965 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:23:49.640119 version@stat F·[1 1] S·22KiB[21KiB 411B] Sc·[0.25 0.00] +16:23:49.640132 db@open opening +16:23:49.640177 journal@recovery F·1 +16:23:49.641522 journal@recovery recovering @31 +16:23:49.702907 memdb@flush created L0@33 N·2951 S·23KiB "n:\xbb..ver,v36828":"n:\xdc..ong,v33936" +16:23:49.707537 version@stat F·[2 1] S·45KiB[45KiB 411B] Sc·[0.50 0.00] +16:23:49.726802 db@janitor F·5 G·0 +16:23:49.726888 db@open done T·86.744755ms +16:23:49.730542 table@compaction L0·2 -> L1·1 S·45KiB Q·36877 +16:23:49.755043 table@build created L1@36 N·9 S·404B "n:\xbb..ver,v36828":"version,v1" +16:23:49.755142 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] +16:23:49.769539 table@compaction committed F-2 S-45KiB Ke·0 D·5674 T·38.915634ms +16:23:49.769669 table@remove removed @33 +16:23:49.769735 table@remove removed @30 +16:23:49.769777 table@remove removed @29 +=============== Jul 12, 2018 (BST) =============== +16:40:12.633424 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:40:12.633675 version@stat F·[0 1] S·404B[0B 404B] Sc·[0.00 0.00] +16:40:12.633694 db@open opening +16:40:12.633751 journal@recovery F·1 +16:40:12.635430 journal@recovery recovering @34 +16:40:12.653741 memdb@flush created L0@37 N·2658 S·21KiB "n:\xbb..ver,v39480":"n:\xdc..ong,v36880" +16:40:12.655362 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] +16:40:12.672204 db@janitor F·4 G·0 +16:40:12.672249 db@open done T·38.544509ms +=============== Jul 12, 2018 (BST) =============== +16:57:40.345817 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +16:57:40.345996 version@stat F·[1 1] S·21KiB[21KiB 404B] Sc·[0.25 0.00] +16:57:40.346012 db@open opening +16:57:40.346070 journal@recovery F·1 +16:57:40.347980 journal@recovery recovering @38 +16:57:40.363783 memdb@flush created L0@40 N·2786 S·22KiB "n:\xbb..ver,v42253":"n:\xdc..ong,v39543" +16:57:40.365500 version@stat F·[2 1] S·44KiB[43KiB 404B] Sc·[0.50 0.00] +16:57:40.381342 db@janitor F·5 G·0 +16:57:40.381385 db@open done T·35.364738ms +16:57:40.383292 table@compaction L0·2 -> L1·1 S·44KiB Q·42323 +16:57:40.408961 table@build created L1@43 N·9 S·410B "n:\xbb..ver,v42253":"version,v1" +16:57:40.409041 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +16:57:40.423831 table@compaction committed F-2 S-43KiB Ke·0 D·5444 T·40.39884ms +16:57:40.423935 table@remove removed @40 +16:57:40.423986 table@remove removed @37 +16:57:40.424026 table@remove removed @36 +21:39:50.525477 memdb@flush N·43421 S·3MiB +21:39:50.610325 memdb@flush created L0@45 N·43421 S·341KiB "n:\xbb..ver,v85728":"n:\xdc..ong,v42330" +21:39:50.610621 version@stat F·[1 1] S·341KiB[341KiB 410B] Sc·[0.25 0.00] +21:39:50.619942 memdb@flush committed F·1 T·94.239078ms +21:39:50.627386 journal@remove removed @41 +=============== Jul 13, 2018 (BST) =============== +02:22:42.318770 memdb@flush N·43426 S·3MiB +02:22:42.349319 memdb@flush created L0@47 N·43426 S·341KiB "n:\xbb..ver,v129168":"n:\xdc..ong,v85750" +02:22:42.349367 version@stat F·[2 1] S·682KiB[682KiB 410B] Sc·[0.50 0.00] +02:22:42.356398 memdb@flush committed F·1 T·37.578228ms +02:22:42.357339 journal@remove removed @44 +07:04:10.330333 memdb@flush N·43422 S·3MiB +07:04:10.393823 memdb@flush created L0@49 N·43422 S·341KiB "n:\xbb..ver,v172517":"n:\xdc..ong,v129177" +07:04:10.393906 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] +07:04:10.401140 memdb@flush committed F·1 T·70.637042ms +07:04:10.404444 journal@remove removed @46 +=============== Jul 13, 2018 (BST) =============== +11:03:48.229037 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:03:48.229335 version@stat F·[3 1] S·1024KiB[1024KiB 410B] Sc·[0.75 0.00] +11:03:48.229357 db@open opening +11:03:48.229460 journal@recovery F·1 +11:03:48.233070 journal@recovery recovering @48 +11:03:48.333384 memdb@flush created L0@50 N·35960 S·283KiB "n:\xbb..ver,v208539":"n:\xdc..ong,v172602" +11:03:48.335105 version@stat F·[4 1] S·1MiB[1MiB 410B] Sc·[1.00 0.00] +11:03:48.365177 db@janitor F·7 G·0 +11:03:48.365234 db@open done T·135.861856ms +11:03:48.365374 table@compaction L0·4 -> L1·1 S·1MiB Q·208553 +11:03:48.537826 table@build created L1@53 N·9 S·411B "n:\xbb..ver,v208539":"version,v1" +11:03:48.537925 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:03:48.552126 table@compaction committed F-4 S-1MiB Ke·0 D·166229 T·186.66634ms +11:03:48.552301 table@remove removed @50 +11:03:48.552405 table@remove removed @49 +11:03:48.552509 table@remove removed @47 +11:03:48.552616 table@remove removed @45 +11:03:48.552651 table@remove removed @43 +=============== Jul 13, 2018 (BST) =============== +11:20:12.182469 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:20:12.182651 version@stat F·[0 1] S·411B[0B 411B] Sc·[0.00 0.00] +11:20:12.182664 db@open opening +11:20:12.182717 journal@recovery F·1 +11:20:12.184513 journal@recovery recovering @51 +11:20:12.241385 memdb@flush created L0@54 N·2632 S·21KiB "n:\xbb..ver,v211126":"n:\xdc..ong,v208560" +11:20:12.243129 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] +11:20:12.267182 db@janitor F·4 G·0 +11:20:12.267224 db@open done T·84.550385ms +=============== Jul 13, 2018 (BST) =============== +11:22:05.344239 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:22:05.344426 version@stat F·[1 1] S·21KiB[21KiB 411B] Sc·[0.25 0.00] +11:22:05.344439 db@open opening +11:22:05.344495 journal@recovery F·1 +11:22:05.346064 journal@recovery recovering @55 +11:22:05.396304 memdb@flush created L0@57 N·327 S·2KiB "n:\xbb..ver,v211460":"n:\xdc..ong,v211193" +11:22:05.398077 version@stat F·[2 1] S·24KiB[23KiB 411B] Sc·[0.50 0.00] +11:22:05.423465 db@janitor F·5 G·0 +11:22:05.423498 db@open done T·79.043478ms +11:22:05.431533 table@compaction L0·2 -> L1·1 S·24KiB Q·211514 +11:22:05.447314 table@build created L1@60 N·9 S·410B "n:\xbb..ver,v211460":"version,v1" +11:22:05.447458 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +11:22:05.465235 table@compaction committed F-2 S-23KiB Ke·0 D·2959 T·33.57446ms +11:22:05.465771 table@remove removed @57 +11:22:05.465835 table@remove removed @54 +11:22:05.465892 table@remove removed @53 +=============== Jul 13, 2018 (BST) =============== +11:28:36.605530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:28:36.605766 version@stat F·[0 1] S·410B[0B 410B] Sc·[0.00 0.00] +11:28:36.605790 db@open opening +11:28:36.605861 journal@recovery F·1 +11:28:36.605970 journal@recovery recovering @58 +11:28:36.669491 memdb@flush created L0@61 N·1083 S·8KiB "n:\xbb..ver,v212511":"n:\xdc..ong,v211525" +11:28:36.675160 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] +11:28:36.702895 db@janitor F·4 G·0 +11:28:36.702923 db@open done T·97.12478ms +=============== Jul 13, 2018 (BST) =============== +11:41:32.591748 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:32.592105 version@stat F·[1 1] S·9KiB[8KiB 410B] Sc·[0.25 0.00] +11:41:32.592141 db@open opening +11:41:32.592263 journal@recovery F·1 +11:41:32.596765 journal@recovery recovering @62 +11:41:32.663254 memdb@flush created L0@64 N·2051 S·16KiB "n:\xbb..ver,v214616":"n:\xdc..ong,v212601" +11:41:32.667391 version@stat F·[2 1] S·25KiB[25KiB 410B] Sc·[0.50 0.00] +11:41:32.687539 db@janitor F·5 G·0 +11:41:32.687649 db@open done T·95.481415ms +11:41:32.693255 table@compaction L0·2 -> L1·1 S·25KiB Q·214650 +11:41:32.705795 table@build created L1@67 N·9 S·402B "n:\xbb..ver,v214616":"version,v1" +11:41:32.705947 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] +11:41:32.716509 table@compaction committed F-2 S-25KiB Ke·0 D·3134 T·23.166583ms +11:41:32.716920 table@remove removed @64 +11:41:32.717040 table@remove removed @61 +11:41:32.717124 table@remove removed @60 +=============== Jul 13, 2018 (BST) =============== +13:24:41.332660 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:24:41.333223 version@stat F·[0 1] S·402B[0B 402B] Sc·[0.00 0.00] +13:24:41.333279 db@open opening +13:24:41.333442 journal@recovery F·1 +13:24:41.338137 journal@recovery recovering @65 +13:24:41.431439 memdb@flush created L0@68 N·16181 S·126KiB "n:\xbb..ver,v230767":"n:\xdc..ong,v214663" +13:24:41.436600 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] +13:24:41.455095 db@janitor F·4 G·0 +13:24:41.455178 db@open done T·121.864633ms +=============== Jul 13, 2018 (BST) =============== +13:39:14.287874 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:39:14.288364 version@stat F·[1 1] S·126KiB[126KiB 402B] Sc·[0.25 0.00] +13:39:14.288413 db@open opening +13:39:14.288637 journal@recovery F·1 +13:39:14.294999 journal@recovery recovering @69 +13:39:14.358894 memdb@flush created L0@71 N·373 S·3KiB "n:\xbb..ver,v231162":"n:\xdc..ong,v230839" +13:39:14.362425 version@stat F·[2 1] S·129KiB[129KiB 402B] Sc·[0.50 0.00] +13:39:14.378518 db@janitor F·5 G·0 +13:39:14.378592 db@open done T·90.139823ms +13:39:14.382837 table@compaction L0·2 -> L1·1 S·129KiB Q·231206 +13:39:14.423154 table@build created L1@74 N·9 S·408B "n:\xbb..ver,v231162":"version,v1" +13:39:14.423312 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] +13:39:14.430225 table@compaction committed F-2 S-129KiB Ke·0 D·16554 T·47.299275ms +13:39:14.430806 table@remove removed @71 +13:39:14.431030 table@remove removed @68 +13:39:14.431114 table@remove removed @67 +=============== Jul 13, 2018 (BST) =============== +13:42:01.201254 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:42:01.202082 version@stat F·[0 1] S·408B[0B 408B] Sc·[0.00 0.00] +13:42:01.202135 db@open opening +13:42:01.202346 journal@recovery F·1 +13:42:01.208136 journal@recovery recovering @72 +13:42:01.262455 memdb@flush created L0@75 N·6173 S·223KiB "n:\x00..ail,v235103":"n:\xff..ing,v237371" +13:42:01.264229 version@stat F·[1 1] S·223KiB[223KiB 408B] Sc·[0.25 0.00] +13:42:01.281802 db@janitor F·4 G·0 +13:42:01.281968 db@open done T·79.800956ms +13:42:01.378033 table@compaction L0·1 -> L1·1 S·223KiB Q·237380 +13:42:01.396425 table@build created L1@78 N·4559 S·204KiB "n:\x00..ail,v235103":"version,v1" +13:42:01.396501 version@stat F·[0 1] S·204KiB[0B 204KiB] Sc·[0.00 0.00] +13:42:01.403777 table@compaction committed F-1 S-19KiB Ke·0 D·1623 T·25.655949ms +13:42:01.403949 table@remove removed @75 +13:42:01.404032 table@remove removed @74 +=============== Jul 13, 2018 (BST) =============== +13:50:51.642894 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:50:51.643089 version@stat F·[0 1] S·204KiB[0B 204KiB] Sc·[0.00 0.00] +13:50:51.643107 db@open opening +13:50:51.643167 journal@recovery F·1 +13:50:51.645218 journal@recovery recovering @76 +13:50:51.775777 memdb@flush created L0@79 N·15634 S·576KiB "n:\x00..ing,v250524":"n:\xff..ing,v246194" +13:50:51.777852 version@stat F·[1 1] S·781KiB[576KiB 204KiB] Sc·[0.25 0.00] +13:50:51.797181 db@janitor F·4 G·0 +13:50:51.797218 db@open done T·154.10061ms +13:50:51.858184 table@compaction L0·1 -> L1·1 S·781KiB Q·253056 +13:50:51.900361 table@build created L1@82 N·15140 S·710KiB "n:\x00..ail,v235103":"version,v1" +13:50:51.901224 version@stat F·[0 1] S·710KiB[0B 710KiB] Sc·[0.00 0.01] +13:50:51.909091 table@compaction committed F-1 S-70KiB Ke·0 D·5053 T·50.683078ms +13:50:51.910084 table@remove removed @79 +13:50:51.913610 table@remove removed @78 +=============== Jul 13, 2018 (BST) =============== +13:54:37.269315 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:54:37.269838 version@stat F·[0 1] S·710KiB[0B 710KiB] Sc·[0.00 0.01] +13:54:37.269907 db@open opening +13:54:37.270104 journal@recovery F·1 +13:54:37.276150 journal@recovery recovering @80 +13:54:37.357368 memdb@flush created L0@83 N·1973 S·78KiB "n:\x00..ail,v253125":"n:\xff..ing,v253349" +13:54:37.364118 version@stat F·[1 1] S·789KiB[78KiB 710KiB] Sc·[0.25 0.01] +13:54:37.381416 db@janitor F·4 G·0 +13:54:37.381496 db@open done T·111.553712ms +13:54:37.414782 table@compaction L0·1 -> L1·1 S·789KiB Q·254996 +13:54:37.443397 table@build created L1@86 N·16383 S·772KiB "n:\x00..ail,v235103":"version,v1" +13:54:37.443515 version@stat F·[0 1] S·772KiB[0B 772KiB] Sc·[0.00 0.01] +13:54:37.450421 table@compaction committed F-1 S-16KiB Ke·0 D·730 T·35.579233ms +13:54:37.450796 table@remove removed @83 +13:54:37.451019 table@remove removed @82 +=============== Jul 13, 2018 (BST) =============== +13:57:11.212091 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:57:11.212882 version@stat F·[0 1] S·772KiB[0B 772KiB] Sc·[0.00 0.01] +13:57:11.212955 db@open opening +13:57:11.213215 journal@recovery F·1 +13:57:11.220864 journal@recovery recovering @84 +13:57:11.305053 memdb@flush created L0@87 N·3132 S·113KiB "n:\x00..ail,v255171":"n:\xff..ing,v256390" +13:57:11.312835 version@stat F·[1 1] S·885KiB[113KiB 772KiB] Sc·[0.25 0.01] +13:57:11.334674 db@janitor F·4 G·0 +13:57:11.334790 db@open done T·121.757337ms +13:57:11.370088 table@compaction L0·1 -> L1·1 S·885KiB Q·258123 +13:57:11.401172 table@build created L1@90 N·17944 S·848KiB "n:\x00..ail,v235103":"version,v1" +13:57:11.401249 version@stat F·[0 1] S·848KiB[0B 848KiB] Sc·[0.00 0.01] +13:57:11.412346 table@compaction committed F-1 S-37KiB Ke·0 D·1571 T·42.186121ms +13:57:11.412485 table@remove removed @87 +13:57:11.412711 table@remove removed @86 +=============== Jul 13, 2018 (BST) =============== +14:14:58.851035 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:14:58.851219 version@stat F·[0 1] S·848KiB[0B 848KiB] Sc·[0.00 0.01] +14:14:58.851233 db@open opening +14:14:58.851274 journal@recovery F·1 +14:14:58.853147 journal@recovery recovering @88 +14:14:58.930188 memdb@flush created L0@91 N·18217 S·488KiB "n:\x00..ing,v272680":"n:\xff..ing,v259302" +14:14:58.932029 version@stat F·[1 1] S·1MiB[488KiB 848KiB] Sc·[0.25 0.01] +14:14:58.951250 db@janitor F·4 G·0 +14:14:58.951279 db@open done T·100.037464ms +14:14:59.236427 table@compaction L0·1 -> L1·1 S·1MiB Q·276382 +14:14:59.290345 table@build created L1@94 N·23452 S·1MiB "n:\x00..ail,v235103":"version,v1" +14:14:59.290583 version@stat F·[0 1] S·1MiB[0B 1MiB] Sc·[0.00 0.01] +14:14:59.297982 table@compaction committed F-1 S-189KiB Ke·0 D·12709 T·61.475181ms +14:14:59.300378 table@remove removed @91 +14:14:59.300707 table@remove removed @90 +=============== Jul 13, 2018 (BST) =============== +14:34:10.197079 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:34:10.197845 version@stat F·[0 1] S·1MiB[0B 1MiB] Sc·[0.00 0.01] +14:34:10.197930 db@open opening +14:34:10.198164 journal@recovery F·1 +14:34:10.206290 journal@recovery recovering @92 +14:34:10.304595 memdb@flush created L0@95 N·15756 S·365KiB "n:\x00..ail,v280370":"n:\xff..ong,v283459" +14:34:10.310007 version@stat F·[1 1] S·1MiB[365KiB 1MiB] Sc·[0.25 0.01] +14:34:10.328427 db@janitor F·4 G·0 +14:34:10.328528 db@open done T·130.556877ms +14:34:10.453233 table@compaction L0·1 -> L1·1 S·1MiB Q·292146 +14:34:10.490415 table@build created L1@98 N·25961 S·1MiB "n:\x00..ail,v280370":"version,v1" +14:34:10.490499 version@stat F·[0 1] S·1MiB[0B 1MiB] Sc·[0.00 0.01] +14:34:10.497891 table@compaction committed F-1 S-216KiB Ke·0 D·13247 T·44.607513ms +14:34:10.498081 table@remove removed @95 +14:34:10.498424 table@remove removed @94 diff --git a/poa-network/single-peer/node1/geth/nodes/MANIFEST-000097 b/poa-network/single-peer/node1/geth/nodes/MANIFEST-000097 new file mode 100644 index 0000000000000000000000000000000000000000..452f7ab1386c5bb89f8d68240c7ca132d6948b1e GIT binary patch literal 862 zcmX?q!ri=#iIGt%C$%g!CnZVGsj?)sJhM2}IX|}`u_&=5zlbS;Ifn2!6gl zZPAuD@3+`2W53j)G3TFEN@j6#epzafRZe1YNkL{_I^(l1%nU%l&Jh3TjTq1h1|~bh ze&z0uRYf)b&API_=jxX|-{60K(v|)1S#>AZFxg0CTV9D=kdtTJkr}I`Du40KYx_4* z8a5?u?R%NDzh@$>NXyJiNlVPkVKj1Q0a*cZ{{_7z(i^VZaL(VXyfXTw`APY!A{{ei z%Z|>ec<}kshL5&WODZ}xXMX=VSJ*~3`@4G952kOz7F>po@@x7s-Z`})35DyIUf8tsf8?pV#f!9b!>eykI&Fmw+B0C!Vj@Bjb+ literal 0 HcmV?d00001 diff --git a/poa-network/single-peer/node1/geth/transactions.rlp b/poa-network/single-peer/node1/geth/transactions.rlp new file mode 100755 index 0000000000000000000000000000000000000000..2f6e1f63ed690ec6b0262c286eab7f610ea83b09 GIT binary patch literal 637035 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

    (eXz+%? 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%0AT@Gyg^YS@JLa!0E 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