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/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e492a7b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,43 @@ +os: linux +dist: trusty + +matrix: + include: + - name: "Javascript Contract Tests" + services: + - docker + + before_script: + - npm install + - npm run testrpc & + + script: + - 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: "Ion-CLI Tests" + language: go + 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 + - 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 + + before_install: + - sudo add-apt-repository ppa:ethereum/ethereum -y + - sudo apt-get update + - sudo apt-get install solc -y + + +notifications: + slack: + 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/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/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..c3a75cb 100644 --- a/README.md +++ b/README.md @@ -1,196 +1,209 @@ -# Ion Interoperability Protocol +# Ion Interoperability Framework +The Ion Interoperability Framework is a library that provides an interface for the development of general cross-chain smart contracts. -The Ion Interoperability Protocol provides mechanisms to perform atomic swaps and currency transfers -across multiple turing-complete blockchains. +## Introduction -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. +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. -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. +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. -Check out the [Wiki](https://github.com/clearmatics/ion/wiki) for more detailed explanations. +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. -## Cross-chain payment +### Contents +* [Getting Started](#getting-started) +* [Interoperate with Rinkeby!](#interoperate-with-rinkeby) +* [Develop on Ion](#develop-on-ion) +* [Ion CLI](#ion-cli) +* [Contribute!](#contribute) -Cross-chain payment flow of two different tokens on their respective blockchains with Alice and Bob as the parties involved is as follows: +## Getting Started -Chain A: Alice's chain -Chain B: Bob's chain +Clone the repository and ensure that all the components work out of the box. -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. +You will need [`nodejs`](https://nodejs.org/en/) and [`golang`](https://golang.org/) installed. -Note that withdrawing is blocked for both chains until funds are deposited into the escrow of the opposite chain. +Run: -### Caveats +``` +$ npm install +``` +``` +$ npm run testrpc +``` +``` +$ npm run test +``` -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. +to test the full stack of contracts including our example flow. -## Install and Test +The tests should pass as below: +``` + ... -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`. + 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) -``` -$ make build ``` -### Testing +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. -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`. +We'll now use these example contracts to show you exactly how interoperation with Rinkeby looks like. -Test: -``` -$ make test -``` +## Interoperate with Rinkeby! -This will run both the Javascript tests for the smart contracts and the Python tests for the Lithium RPC relay. +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. -Additionally contributors to this project should use linting tools when making commits, for both solidity and python code. +We've already deployed some contracts to the Rinkeby test network for you to play around with! -``` -$ make python-lint -$ make solidity-lint -``` +Ion: `0xFEA947D9979c96d65CE7a514B3FeBbA67E54CD18` -## Setup +Clique: `0x9D94343187a5Fcd4e4552060874d4B1ad25c8c3D` -To perform cross-chain payments, the contracts must be deployed on each chain. +Ethereum Block Store: `0x2d8B459E4b331c53a4C30Ff34fd129E890BaAF57` -Deploy two testrpc networks, if necessary, in separate terminals: -``` -$ npm run testrpca -$ npm run testrpcb -``` +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. -Compile and deploy the contracts on to the relevant networks: -``` -$ npm run compile -$ npm run deploya -$ npm run deployb -``` +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. +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` +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` + * `_path`: `0x04` + * `_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! -## Tutorial +### Try out your own functions! -The following tutorial describes how to perform token transfer between two accounts on separate blockchains. +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. -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 -``` +You can now also attempt to write your own functional smart contracts using the similar skeleton to the `Function.sol` contract. -This tutorial leverages Ganache and Truffle but could easily be performed on other test networks. +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. -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. +## Develop on Ion -ALICE=0x22d491bde2303f2f43325b2108d26f1eaba1e32b +Develop your own cross-chain smart contracts using the Ion interface! -BOB=0xffcf8fdee72ac11b5c542428b35eef5769c409f0 +### Core Concept -TOKEN=0x254dffcd3277c0b1660f6d42efbb754edababc2b +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. -IONLOCK=0xc89ce4735882c9f0f0fe26686c53074e09b0d550 +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 -IONLINK=0xcfeb869f69431e42cdb54a4f4f105c19c080a601 +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. -IP=127.0.0.1 +#### State Validation -PORT_A=8545 +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. -PORT_B=8546 +#### State Transition Verification -API_PORT_A=8555 +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. -API_PORT_B=8556 +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. -It is recommended to use an isolated python environment. -### Step 1: Deploy event listeners +### Interoperating Betweeen Ethereum Chains -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 -``` +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. -### Step 2: Mint token on each chain +To write a smart contract that depends on particular state transitions there are pre-requisites: +* Event Verifier contracts -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 -``` +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. -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 -``` +`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 -### Step 3: Escrow funds and get proof on chain A +All Event Verifier contracts should perform the same way. The differences will simply be in the event signature and parameters checks of the event. -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 -``` +`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. -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 -``` +### Testing -### Step 4: Escrow funds and get proof on chain B +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: -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 -``` +* Core functionality of smart contracts +* Integration with Ion Interface -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 -``` +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. -### Step 5: Withdraw funds using proof on chain B +Study the tests in the repository to discover how we've unit-tested the entire integrated stack of smart contracts. -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 -``` +## Ion CLI -### Step 6: Withdraw funds using proof on chain A +The Ion Command-Line Interface is a tool built in Golang to provide functions to facilitate the use of the Ion framework. -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 -``` +The Command-Line Interface reference can be found [here](./ion-cli) + +## How Ion works + +Please see our [wiki](https://github.com/clearmatics/ion/wiki) for more detailed information about the design philosophy of Ion. + +# Contribute! + +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. + +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. + +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. 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/EventVerifier.sol b/contracts/EventVerifier.sol new file mode 100644 index 0000000..9bf271b --- /dev/null +++ b/contracts/EventVerifier.sol @@ -0,0 +1,61 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +import "./libraries/RLP.sol"; +import "./libraries/SolidityUtils.sol"; + +/* + 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. +*/ + +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]); + + /* 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. + */ + for (uint i = 0; i < logs.length; i++) { + RLP.RLPItem[] memory log = RLP.toList(logs[i]); + RLP.RLPItem[] memory topics = RLP.toList(log[1]); + + 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 = SolUtils.BytesToBytes20(RLP.toData(log[0]), 0); + assert( b20_emissionSource == _contractEmittedAddress); + return log; + } + } + assert( false ); + } + +} diff --git a/contracts/Ion.sol b/contracts/Ion.sol new file mode 100644 index 0000000..39d5454 --- /dev/null +++ b/contracts/Ion.sol @@ -0,0 +1,73 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +import "./libraries/ECVerify.sol"; +import "./libraries/RLP.sol"; +import "./libraries/PatriciaTrie.sol"; +import "./libraries/SolidityUtils.sol"; +import "./storage/BlockStore.sol"; + +contract Ion { + + bytes32 public chainId; + mapping (address => bool) public m_registered_validation; + address[] public validation_modules; + + /* + * 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; + } + + /* + * 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() { + 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"); + _; + } + + // 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); + } + + + 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) onlyRegisteredValidation public { + BlockStore store = BlockStore(_storageAddress); + store.addChain(_chainId); + } + + /* + * storeBlock + * param: + * + */ + 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); + + store.addBlock(_chainId, _blockHash, _blockBlob); + } +} \ No newline at end of file diff --git a/contracts/IonCompatible.sol b/contracts/IonCompatible.sol index d16ac04..0b98a61 100644 --- a/contracts/IonCompatible.sol +++ b/contracts/IonCompatible.sol @@ -1,19 +1,14 @@ // 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); -} - +pragma solidity ^0.4.0; +import "./Ion.sol"; 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); + /* 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; - event IonBurn(uint256 value, bytes32 indexed ref); + constructor(address _ionAddr) public { + ion = Ion(_ionAddr); + } } 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/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/Migrations.sol b/contracts/Migrations.sol index ef239dd..3a3cc99 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,7 +1,6 @@ // Copyright (c) 2016-2017 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ - -pragma solidity ^0.4.18; +pragma solidity ^0.4.23; contract Migrations { address public owner; 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/contracts/functional/Function.sol b/contracts/functional/Function.sol new file mode 100644 index 0000000..9eac1c6 --- /dev/null +++ b/contracts/functional/Function.sol @@ -0,0 +1,95 @@ + // Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +import "../storage/EthereumStore.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 + 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 { + 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. */ + TriggerEventVerifier verifier; + + /* Custom event that fires when execution is performed successfully. */ + event Executed(); + + /* Constructor. Requires Ion contract address and all used event verifier contract addresses. In this case we only + use one verifier. */ + constructor(address _storeAddr, address _verifierAddr) public { + blockStore = EthereumStore(_storeAddr); + verifier = TriggerEventVerifier(_verifierAddr); + } + + /* This is the function that is intended to be executed upon successful verification of proofs */ + function execute() internal { + emit Executed(); + } + + /* + 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 { + assert( blockStore.CheckRootsProof(_chainId, _blockHash, _txNodes, _receiptNodes) ); + assert( blockStore.CheckTxProof(_chainId, _blockHash, _tx, _txNodes, _path) ); + assert( blockStore.CheckReceiptProof(_chainId, _blockHash, _receipt, _receiptNodes, _path) ); + + require( verifier.verify(_contractEmittedAddress, _receipt, _expectedAddress), "Event verification failed." ); + execute(); + } +} + diff --git a/contracts/functional/Trigger.sol b/contracts/functional/Trigger.sol new file mode 100644 index 0000000..3536d72 --- /dev/null +++ b/contracts/functional/Trigger.sol @@ -0,0 +1,27 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +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 + `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. +*/ + +contract Trigger { + event Triggered(address caller); + + function fire() public { + emit Triggered(msg.sender); + } +} diff --git a/contracts/functional/TriggerEventVerifier.sol b/contracts/functional/TriggerEventVerifier.sol new file mode 100644 index 0000000..33f0b78 --- /dev/null +++ b/contracts/functional/TriggerEventVerifier.sol @@ -0,0 +1,47 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +import "../libraries/RLP.sol"; +import "../libraries/SolidityUtils.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 = SolUtils.BytesToBytes20(data, data.length - 20); + return b20_address == _expectedAddress; + } + +} diff --git a/contracts/ECVerify.sol b/contracts/libraries/ECVerify.sol similarity index 88% rename from contracts/ECVerify.sol rename to contracts/libraries/ECVerify.sol index 622dd6b..288da23 100644 --- a/contracts/ECVerify.sol +++ b/contracts/libraries/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/libraries/PatriciaTrie.sol b/contracts/libraries/PatriciaTrie.sol new file mode 100644 index 0000000..09200d5 --- /dev/null +++ b/contracts/libraries/PatriciaTrie.sol @@ -0,0 +1,167 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +import "./RLP.sol"; + +library PatriciaTrie { + + 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); + + bytes32 currentNodeKey = _root; + + uint traversedNibbles = 0; + bytes memory path = toNibbleArray(_path, false); + + for (uint i = 0; i < parentNodes.length; i++) { + if (currentNodeKey != keccak256(RLP.toBytes(parentNodes[i]))) { + return false; + } + + RLP.RLPItem[] memory currentNode = RLP.toList(parentNodes[i]); + + if (currentNode.length == 17) { + // Branch Node + (currentNodeKey, traversedNibbles) = processBranchNode(currentNode, traversedNibbles, path, _value); + } else if (currentNode.length == 2) { + // Extension/Leaf Node + (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 (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: + + * 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) { + //Nested 'Node' + (currentNodeKey, _traversedNibbles) = processNestedNode(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 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) { + // Branch 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) { + 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) * uint8(2) ** uint8(bits)); + } + + function rightShift(byte i, uint8 bits) private pure returns (byte) { + return byte(uint8(i) / uint8(2) ** uint8(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/libraries/RLP.sol b/contracts/libraries/RLP.sol new file mode 100644 index 0000000..99be918 --- /dev/null +++ b/contracts/libraries/RLP.sol @@ -0,0 +1,427 @@ +pragma solidity ^0.4.23; +/** +* @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 pure returns (RLPItem memory subItem) { + if(hasNext(self)) { + uint ptr = self._unsafe_nextPtr; + uint 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 pure returns (RLPItem memory subItem) { + subItem = next(self); + if(strict && !_validate(subItem)) + revert(); + return; + } + + 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; + } + + /* 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 pure 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 pure returns (RLPItem memory) { + RLPItem memory 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 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 pure 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 pure 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 pure 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 pure 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 pure 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 returns (bytes memory bts) { + uint 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 returns (bytes memory bts) { + if(!isData(self)) + revert(); + uint rStartPos; + uint len; + (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 pure returns (RLPItem[] memory list) { + if(!isList(self)) + revert(); + uint numItems = items(self); + list = new RLPItem[](numItems); + Iterator memory 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 returns (string memory str) { + if(!isData(self)) + revert(); + uint rStartPos; + uint len; + (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 pure returns (uint data) { + if(!isData(self)) + revert(); + uint rStartPos; + uint len; + (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 pure returns (bool data) { + if(!isData(self)) + revert(); + uint rStartPos; + uint len; + (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 pure returns (byte data) { + if(!isData(self)) + revert(); + uint rStartPos; + uint len; + (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 pure 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 pure 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 pure returns (address data) { + if(!isData(self)) + revert(); + uint rStartPos; + uint len; + (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 pure 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 pure 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 pure 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 view { + // 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 pure 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/contracts/SafeMath.sol b/contracts/libraries/SafeMath.sol similarity index 98% rename from contracts/SafeMath.sol rename to contracts/libraries/SafeMath.sol index 3094245..cc0a608 100644 --- a/contracts/SafeMath.sol +++ b/contracts/libraries/SafeMath.sol @@ -1,6 +1,6 @@ // Copyright (c) 2016-2018 Clearmatics Technologies Ltd // SPDX-License-Identifier: LGPL-3.0+ -pragma solidity ^0.4.18; +pragma solidity ^0.4.23; /** diff --git a/contracts/libraries/SolidityUtils.sol b/contracts/libraries/SolidityUtils.sol new file mode 100644 index 0000000..9aa2483 --- /dev/null +++ b/contracts/libraries/SolidityUtils.sol @@ -0,0 +1,62 @@ +// 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 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 input, uint256 buf) internal pure returns (bytes20) { + bytes20 output; + + for (uint i = 0; i < 20; i++) { + output |= bytes20(input[buf + i] & 0xFF) >> (i * 8); + } + 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 + * @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/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/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/contracts/validation/Clique.sol b/contracts/validation/Clique.sol new file mode 100644 index 0000000..c51d350 --- /dev/null +++ b/contracts/validation/Clique.sol @@ -0,0 +1,333 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ +pragma solidity ^0.4.23; + +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; + + /* + * @description persists the last submitted block of a chain being validated + */ + struct BlockHeader { + uint256 blockNumber; + bytes32 blockHash; + bytes32 prevBlockHash; + bytes32 txRootHash; + bytes32 receiptRootHash; + } + + struct Metadata { + address[] validators; + mapping (address => bool) m_validators; + mapping (address => uint256) m_proposals; + uint256 threshold; + } + + event GenesisCreated(bytes32 chainId, bytes32 blockHash); + event BlockSubmitted(bytes32 chainId, bytes32 blockHash); + + /* + * 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 => mapping (bytes32 => bool)) public m_blockhashes; + mapping (bytes32 => mapping (bytes32 => BlockHeader)) public m_blockheaders; + mapping (bytes32 => mapping (bytes32 => Metadata)) public m_blockmetadata; + mapping (bytes32 => bytes32[]) public heads; + + constructor (address _ionAddr) IonCompatible(_ionAddr) public {} + +/* ===================================================================================================================== + + Public Functions + + ===================================================================================================================== +*/ + function register() public returns (bool) { + ion.registerValidationModule(); + return true; + } + + /* + * RegisterChain + * 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 + * + * 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(bytes32 _chainId, address[] _validators, bytes32 _genesisBlockHash, address _storeAddr) public { + require( _chainId != ion.chainId(), "Cannot add this chain id to chain register" ); + + if (chains[_chainId]) { + require( !m_blockhashes[_chainId][_genesisBlockHash], "Chain already exists with identical genesis" ); + } else { + chains[_chainId] = true; + ion.addChain(_storeAddr, _chainId); + } + + addGenesisBlock(_chainId, _validators, _genesisBlockHash, _storeAddr); + } + + /* + * SubmitBlock + * 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. + */ + 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" ); + + // Check header and signedHeader contain the same data + for (uint256 i=0; i= 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]]; + } + } + } + + /* + * 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, + bytes32 _hash, + bytes32 _parentHash, + bytes32 _txRootHash, + bytes32 _receiptRootHash, + uint256 _height, + bytes _rlpBlockHeader, + address _storageAddr + ) internal { + m_blockhashes[_chainId][_hash] = true; + + BlockHeader storage header = m_blockheaders[_chainId][_hash]; + header.blockNumber = _height; + header.blockHash = _hash; + header.prevBlockHash = _parentHash; + header.txRootHash = _txRootHash; + header.receiptRootHash = _receiptRootHash; + + // Add block to Ion + 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[uint(index)]; + chainHeads[uint(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; + } + + function getProposal(bytes32 _chainId, bytes32 _blockHash, address _candidate) constant returns (uint256) { + return m_blockmetadata[_chainId][_blockHash].m_proposals[_candidate]; + } +} 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..e211e66 --- /dev/null +++ b/docker_build/launch_geth.sh @@ -0,0 +1,2 @@ +!#/bin/bash +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/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/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/docs/Roadmap.md b/docs/Roadmap.md new file mode 100644 index 0000000..4cb8cef --- /dev/null +++ b/docs/Roadmap.md @@ -0,0 +1,136 @@ +# 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 + * 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 fortnightly sprints. Note that the sprint objective will remain dynamic and should change as the project continues. + +## 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 6 - Minimal Viabable Ion Stage 2 +Date: 16.07.2018 - 23.07.2018 + +Description: +Various separated components should be integrated with required tooling and documentation. + +Goals: + * Ability to submit and verify proofs against Ion Relay contract + * Execute contract given state transition + +Achieved: + +### Sprint 5 - Off-Chain Proof Generation +Date: 02.07.2018 - 13.07.2018 + +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 + * 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 + +Achieved: + +### 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. + +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 + +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: +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: + + +### 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. + +Goals: + * Project specification. + +Achieved: + * Specification was released + + + 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-cli/.gitignore b/ion-cli/.gitignore new file mode 100644 index 0000000..e51b86e --- /dev/null +++ b/ion-cli/.gitignore @@ -0,0 +1,2 @@ +ion-cli +vendor diff --git a/ion-cli/Gopkg.lock b/ion-cli/Gopkg.lock new file mode 100644 index 0000000..3b3c507 --- /dev/null +++ b/ion-cli/Gopkg.lock @@ -0,0 +1,232 @@ +# 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]] + name = "github.com/aristanetworks/goarista" + packages = ["monotime"] + revision = "ea17b1a17847fb6e4c0a91de0b674704693469b0" + +[[projects]] + name = "github.com/btcsuite/btcd" + packages = ["btcec"] + revision = "2e60448ffcc6bf78332d1fe590260095f554dd78" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/deckarep/golang-set" + packages = ["."] + revision = "504e848d77ea4752b3057b8fb46da0e7f746ccf3" + +[[projects]] + name = "github.com/edsrzf/mmap-go" + packages = ["."] + revision = "935e0e8a636ca4ba70b713f3e38a19e1b77739e8" + +[[projects]] + name = "github.com/ethereum/go-ethereum" + packages = [ + ".", + "accounts", + "accounts/abi", + "accounts/abi/bind", + "accounts/abi/bind/backends", + "accounts/keystore", + "common", + "common/bitutil", + "common/compiler", + "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/secp256k1", + "crypto/sha3", + "eth/filters", + "ethclient", + "ethdb", + "event", + "log", + "metrics", + "p2p/netutil", + "params", + "rlp", + "rpc", + "trie" + ] + revision = "225171a4bfcc16bd12a1906b1e0d43d0b18c353b" + version = "v1.8.13" + +[[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 = "54be5f394ed2c3e19dac9134a40a95ba5a017f7b" + version = "v1.5.4" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" + +[[projects]] + name = "github.com/hashicorp/golang-lru" + packages = [ + ".", + "simplelru" + ] + revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6" + +[[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/pborman/uuid" + packages = ["."] + revision = "1b00554d822231195d1babd97ff4a781231955c9" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/rjeczalik/notify" + packages = ["."] + revision = "c31e5f2cb22b3e4ef3f882f413847669bf2652b9" + +[[projects]] + name = "github.com/rs/cors" + packages = ["."] + revision = "a62a804a8a009876ca59105f7899938a1349f4b3" + version = "v1.0" + +[[projects]] + name = "github.com/rs/xhandler" + packages = ["."] + revision = "d9d9599b6aaf6a058cb7b1f48291ded2cbd13390" + version = "v1.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert"] + revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" + version = "v1.2.2" + +[[projects]] + 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]] + name = "golang.org/x/crypto" + packages = [ + "pbkdf2", + "ripemd160", + "scrypt" + ] + revision = "6a293f2d4b14b8e6d3f0539e383f6d0d30fce3fd" + +[[projects]] + name = "golang.org/x/net" + packages = [ + "context", + "websocket" + ] + revision = "a6577fac2d73be281a500b310739095313165611" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded" + +[[projects]] + name = "golang.org/x/tools" + packages = [ + "go/ast/astutil", + "imports" + ] + revision = "be0fcc31ae2332374e800dfff29b721c585b35df" + +[[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 = "61e6c38a8fde2002db259f4cefff56c1602f61842d325ec011613477dd20a819" + 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..e5da473 --- /dev/null +++ b/ion-cli/Gopkg.toml @@ -0,0 +1,46 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# 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.13" + +[[constraint]] + branch = "master" + name = "github.com/Shirikatsu/go-ethereum" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.2" + +[prune] + go-tests = true + unused-packages = true diff --git a/ion-cli/Makefile b/ion-cli/Makefile new file mode 100644 index 0000000..e91f390 --- /dev/null +++ b/ion-cli/Makefile @@ -0,0 +1,41 @@ +.DEFAULT_GOAL := build +GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*") +PACKAGES = $(shell find ./ -type d -not -path "./vendor" -not -path "./vendor/*" -not -path "./.git" -not -path "./.git/*" -not -path "./config/files") +SHELL=/bin/bash + +clean: + @rm -f ion-cli + +test: + @go test ./... -v -short + +integration-test: + @go test ./... -v + +format: + @gofmt -s -w ${GOFILES_NOVENDOR} + +coverage: + echo "mode: count" > 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: + # Build project + @go get -t -v ./... + @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/README.md b/ion-cli/README.md new file mode 100644 index 0000000..0c24574 --- /dev/null +++ b/ion-cli/README.md @@ -0,0 +1,140 @@ +# Ion CLI + +The Command-Line Interface reference. + +## Building the CLI + +Clean the directory: `make clean`. + +### Requirements + +* [`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`. + +## 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. +``` 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 new file mode 100644 index 0000000..e3234b2 --- /dev/null +++ b/ion-cli/cli/cli.go @@ -0,0 +1,644 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package cli + +import ( + "context" + "fmt" + "math/big" + "strconv" + "errors" + "strings" + + "github.com/ethereum/go-ethereum/common" + "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" +) + +// Launch - definition of commands and creates the interface +func Launch() { + // by default, new shell includes 'exit', 'help' and 'clear' commands. + shell := ishell.New() + + // Create new context + ctx := context.Background() + + 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) + + //--------------------------------------------------------------------------------------------- + // RPC Client Specific Commands + //--------------------------------------------------------------------------------------------- + + shell.AddCmd(&ishell.Cmd{ + 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") + 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("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "addContractInstance", + 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: \taddContractInstance [name] [path/to/solidity/contract]\n") + } else { + err := addContractInstance(c.Args[1], c.Args[0], contracts) + if err != nil { + c.Println(err) + return + } + c.Println("Added!") + } + 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]\n\t\t\t\tdescription: Add account to be used for transactions", + Func: func(c *ishell.Context) { + if len(c.Args) != 2 { + c.Println("Usage: \taddAccount [name] [path/to/keystore]\n") + } else { + 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("===============================================================") + }, + }) + + 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: "deployContract", + 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 \taddContractInstance [name] [path/to/solidity/contract]\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] \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 + } + + /*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, + 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: "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 \taddContractInstance [name] [path/to/solidity/contract] \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 + } + + compiledContract, err := contract.CompileContractWithLibraries(contractInstance.Path, library) + if err != nil { + c.Println(err) + return + } + + binStr, abiStr := contract.GetContractBytecodeAndABI(compiledContract) + + 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: 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") + } 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 \taddContractInstance [name] [path/to/solidity/contract] \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 + } + + amount := new(big.Int) + 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[5], 10, 64) + if err != nil { + c.Err(errors.New("Please enter an integer for ")) + } + + 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 + } + + tx, err := contract.TransactionContract( + ctx, + ethClient.client, + account.Key.PrivateKey, + instance.Contract, + contractDeployedAddress, + amount, + gasLimit, + c.Args[1], + inputs... + ) + if err != nil { + c.Println(err) + return + } else { + 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("===============================================================") + }, + }) + + /*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 from connected client or specified endpoint", + 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 [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 + + if len(c.Args) == 1 { + if ethClient != nil { + _, 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 { + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + _, json, err = getBlockByNumber(client, c.Args[1]) + } else { + 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: \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 + + if len(c.Args) == 1 { + if ethClient != nil { + _, 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 { + client, err := getClient(c.Args[0]) + if err != nil { + c.Println(err) + return + } + _, json, err = getBlockByHash(client, c.Args[1]) + } else { + c.Println("Usage: \tgetBlockByHash [optional rpc url] [hash] \n") + return + } + if err != nil { + c.Println(err) + return + } + c.Printf("Block: %s\n", json) + c.Println("===============================================================") + }, + }) + + shell.AddCmd(&ishell.Cmd{ + Name: "getProof", + 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) == 1 { + if ethClient != nil { + getProof(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 + } + getProof(client, c.Args[1]) + } else { + c.Println("Usage: \tgetProof [optional rpc url] [Transaction hash] \n") + return + } + c.Println("===============================================================") + }, + }) + + //--------------------------------------------------------------------------------------------- + // Clique Specific Commands + //--------------------------------------------------------------------------------------------- + + shell.AddCmd(&ishell.Cmd{ + Name: "getBlockByNumber_Clique", + 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 { + 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 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 { + 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.Run() +} \ No newline at end of file diff --git a/ion-cli/cli/cli_test.go b/ion-cli/cli/cli_test.go new file mode 100644 index 0000000..468d4e2 --- /dev/null +++ b/ion-cli/cli/cli_test.go @@ -0,0 +1,31 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package cli_test + +import ( + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/clearmatics/ion/ion-cli/config" +) + +func Test_Read_ValidSetupJson(t *testing.T) { + path := findPath() + "./test.json" + setup := config.ReadSetup(path) + + 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, "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) +} + +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/core.go b/ion-cli/cli/core.go new file mode 100644 index 0000000..bab440d --- /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 %d 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/rpc.go b/ion-cli/cli/rpc.go new file mode 100644 index 0000000..1cf14c9 --- /dev/null +++ b/ion-cli/cli/rpc.go @@ -0,0 +1,191 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package cli + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "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 +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"` +} + +type EthClient struct { + client *ethclient.Client + rpcClient *rpc.Client + url string +} + +func latestBlock(eth *EthClient) (lastBlock *types.Header) { + // var lastBlock Block + lastBlock, err := eth.client.HeaderByNumber(context.Background(), nil) + if err != nil { + fmt.Println("can't get latest block:", err) + return nil + } + + return +} + +func getBlockByNumber(eth *EthClient, number string) (*types.Header, []byte, error) { + // var blockHeader header + blockNum := new(big.Int) + blockNum.SetString(number, 10) + + block, err := eth.client.HeaderByNumber(context.Background(), blockNum) + if err != nil { + return nil, nil, err + } + // Marshal into a JSON + b, err := json.MarshalIndent(block, "", " ") + if err != nil { + return nil, nil, err + } + return block, b, nil +} + +func getBlockByHash(eth *EthClient, hash string) (*types.Header, []byte, error) { + blockHash := common.HexToHash(hash) + + block, err := eth.client.HeaderByHash(context.Background(), blockHash) + if err != nil { + return nil, nil, err + } + // Marshal into a JSON + b, err := json.MarshalIndent(block, "", " ") + if err != nil { + return nil, nil, err + } + 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) { + // 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 RlpEncode(blockHeader *types.Header) (rlpSignedBlock []byte, rlpUnsignedBlock []byte) { + // Encode the orginal block header + _, 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(blockHeader) + rlpUnsignedBlock = encodeUnsignedBlock(blockHeader) + + return rlpSignedBlock, rlpUnsignedBlock + +} + +// EncodePrefix calculate prefix of the entire signed block +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 + +} + +// EncodePrefix calculate prefix of the entire signed block +func encodeSignedBlock(lastBlock *types.Header) (encodedBlock []byte) { + encodedBlock, err := rlp.EncodeToBytes(&lastBlock) + if err != nil { + fmt.Println("can't RLP encode requested block:", err) + return + } + + return encodedBlock +} + +// 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() + + // 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/cli/rpc_test.go b/ion-cli/cli/rpc_test.go new file mode 100644 index 0000000..83902e8 --- /dev/null +++ b/ion-cli/cli/rpc_test.go @@ -0,0 +1,52 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package cli + +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) { + TestSigned := "f9025ca03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1db861d68301080d846765746886676f312e3130856c696e7578000000000000000000583a78dd245604e57368cb2688e42816ebc86eff73ee219dd96b8a56ea6392f75507e703203bc2cc624ce6820987cf9e8324dd1f9f67575502fe6060d723d0e100a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + ExpectedSignedBytes, _ := hex.DecodeString(TestSigned) + + // 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) + SignedBlock := encodeSignedBlock(blockHeader) + + assert.Equal(t, ExpectedSignedBytes, SignedBlock) +} + +func Test_EncodeUnsignedBlock(t *testing.T) { + TestUnsigned := "f9021aa03471555ab9a99528f02f9cdd8f0017fe2f56e01116acc4fe7f78aee900442f35a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f526f481ffb6c3c56956d596f2b23e1f7ff17c810ba59efb579d9334a1765444a007f36c7ad26564fa65daebda75a23dfa95d660199092510743f6c8527dd72586a0907121bec78b40e8256fac47867d955c560b321e93fc9f046f919ffb5e3823ffb90100224400000200000900000000000000000410000800000080000880000800000002000004000008000000000000004000000000000000000000100000080201020000000000000800000000088000000000000220000000040000000100000000000800000006204004401000102004000820000000000000800400100001000200200000000000000800800000010000000001000004004800000000020000000020000800180000081080001000000000000000000200000500100010040000000001020000400040000000000000000000000044000000000000000000000002080000000004000082000200000040224000000000040002008480000000000283288c8e837295a1832bffa2845b4f6b1da0d68301080d846765746886676f312e3130856c696e7578000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" + ExpectedUnsignedBytes, _ := hex.DecodeString(TestUnsigned) + + // 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) + UnsignedBlock := encodeUnsignedBlock(blockHeader) + + assert.Equal(t, ExpectedUnsignedBytes, UnsignedBlock) + +} diff --git a/ion-cli/cli/test.json b/ion-cli/cli/test.json new file mode 100644 index 0000000..0c6eafb --- /dev/null +++ b/ion-cli/cli/test.json @@ -0,0 +1,9 @@ +{ + "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":"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/config.go b/ion-cli/config/config.go new file mode 100644 index 0000000..34e3322 --- /dev/null +++ b/ion-cli/config/config.go @@ -0,0 +1,82 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package config + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" +) + +// Settings +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"` + Ion string `json:"ion-addr"` + Trigger string `json:"trigger-addr"` + 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) + if err != nil { + fmt.Print(err, "\n") + } + + err = json.Unmarshal(raw, &setup) + + return +} + +// 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 + +} + +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 { + return nil, nil, err + } + + userkey, err = keystore.DecryptKey(keyjson, password) + if err != nil { + return nil, nil, err + } + + // Create an authorized transactor + key := ReadString(privkeystore) + auth, err = bind.NewTransactor(strings.NewReader(key), password) + if err != nil { + return nil, nil, err + } + + return +} diff --git a/ion-cli/config/config_test.go b/ion-cli/config/config_test.go new file mode 100644 index 0000000..5737603 --- /dev/null +++ b/ion-cli/config/config_test.go @@ -0,0 +1,48 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +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_ReadValidKeystore(t *testing.T) { + 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}" + + assert.Equal(t, val, contents) + +} + +func Test_InitUser(t *testing.T) { + keystore := "../keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d" + password := "password1" + expectedFrom := common.HexToAddress("2be5ab0e43b6dc2908d5321cf318f35b80d0c10d") + expectedPrivateKey := "e176c157b5ae6413726c23094bb82198eb283030409624965231606ec0fbe65b" + + auth, userkey, err := config.InitUser(keystore, password) + assert.Equal(t, err, nil) + + 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, "/") + return strings.Trim(path, pathSlice[len(pathSlice)-1]) +} diff --git a/ion-cli/config/test.json b/ion-cli/config/test.json new file mode 100644 index 0000000..1446b0a --- /dev/null +++ b/ion-cli/config/test.json @@ -0,0 +1,10 @@ +{ + "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 new file mode 100644 index 0000000..8b6a787 --- /dev/null +++ b/ion-cli/contracts/contract.go @@ -0,0 +1,275 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +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" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/Shirikatsu/go-ethereum/common/compiler" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" +) + +// ContractInstance is just an util type to output contract and address +type ContractInstance struct { + Contract *compiler.Contract + Abi *abi.ABI + Path string +} + +// GENERIC UTIL FUNCTIONS + +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) + abiContract, err := abi.JSON(strings.NewReader(contractABIStr)) + if err != nil { + log.Fatal("ERROR reading contract ABI ", err) + } + packedABI, err := abiContract.Pack("", constructorArgs...) + if err != nil { + log.Fatal("ERROR packing ABI ", err) + } + payloadBytecode := append(bytecode, packedABI...) + return payloadBytecode +} + +func newTx( + ctx context.Context, + backend bind.ContractBackend, + from, to *common.Address, + amount *big.Int, + gasLimit uint64, + payloadBytecode []byte, +) *types.Transaction { + + nonce, err := backend.PendingNonceAt(ctx, *from) // uint64(0) + if err != nil { + log.Fatal("Error getting pending nonce ", err) + } + gasPrice, err := backend.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) + 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 +} + +// 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 DeployContract( + ctx context.Context, + backend bind.ContractBackend, + userKey *ecdsa.PrivateKey, + payload []byte, + amount *big.Int, + gasLimit uint64, +) (*types.Transaction, error){ + userAddr := crypto.PubkeyToAddress(userKey.PublicKey) + tx := newTx(ctx, backend, &userAddr, nil, amount, gasLimit, payload) + signedTx := signTx(tx, userKey) + + err := backend.SendTransaction(ctx, signedTx) + if err != nil { + return nil, err + } + 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, + client bind.ContractCaller, + contract *compiler.Contract, + from, to common.Address, + methodName string, + out interface{}, + args ...interface{}, +) (res interface{}, err error) { + abiStr, err := json.Marshal(contract.Info.AbiDefinition) + if err != nil { + return nil, err + } + + abiContract, err := abi.JSON(strings.NewReader(string(abiStr))) + if err != nil { + return nil, err + } + + input, err := abiContract.Pack(methodName, args...) + if err != nil { + return nil, err + } + msg := ethereum.CallMsg{From: from, To: &to, Data: input} + output, err := client.CallContract(ctx, msg, nil) + if err != nil { + return nil, err + } + err = abiContract.Unpack(out, methodName, output) + if err != nil { + return nil, err + } + + return out, nil +} + +// TransactionContract execute function in contract +func TransactionContract( + ctx context.Context, + backend bind.ContractBackend, + userKey *ecdsa.PrivateKey, + contract *compiler.Contract, + to common.Address, + amount *big.Int, + gasLimit uint64, + methodName string, + args ...interface{}, +) (*types.Transaction, error) { + + fmt.Print("Marshalling ABI\n") + abiStr, err := json.Marshal(contract.Info.AbiDefinition) + if err != nil { + 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 { + 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 { + 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 { + errStr := fmt.Sprintf("ERROR sending transaction: %s\n", err) + return nil, errors.New(errStr) + } + return signedTx, nil +} + +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("", []string{}, contractPath) + if err != nil { + return nil, err + } + + compiledContract = contracts[basePath+contract+".sol:"+contract] + + return compiledContract, nil +} + +func CompileContractAt(contractPath string) (compiledContract *compiler.Contract, err error) { + 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("", []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])) + + contract, err := compiler.CompileSolidity("", args, contractPath) + if err != nil { + return nil, err + } + + compiledContract = contract[contractPath+":"+strings.Replace(contractName, ".sol", "", -1)] + + return compiledContract, nil +} diff --git a/ion-cli/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d b/ion-cli/keystore/UTC--2018-06-05T09-31-57.109288703Z--2be5ab0e43b6dc2908d5321cf318f35b80d0c10d new file mode 100644 index 0000000..0d2f3cc --- /dev/null +++ b/ion-cli/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/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 new file mode 100644 index 0000000..34c9f0c --- /dev/null +++ b/ion-cli/main.go @@ -0,0 +1,22 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd + +package main + +import ( + "fmt" + "github.com/clearmatics/ion/ion-cli/cli" +) + +func main() { + // Launch the CLI + printWelcome() + cli.Launch() +} + +func printWelcome() { + // display welcome info. + fmt.Println("===============================================================") + fmt.Print("Ion Command Line Interface\n\n") + fmt.Println("Use 'help' to list commands") + fmt.Println("===============================================================") +} diff --git a/ion-cli/rinkeby.json b/ion-cli/rinkeby.json new file mode 100644 index 0000000..bce18c8 --- /dev/null +++ b/ion-cli/rinkeby.json @@ -0,0 +1,15 @@ +{ + "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":"0xb9fd43a71c076f02d1dbbf473c389f0eacec559f", + "function-addr":"0x93981af8db02c7ef40d0ed61caef2726a79eb903", + "validation-addr":"0x9abefbe4cca994c5d1934dff50c6a863edcf5f52", + "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/ion-cli/utils/client.go b/ion-cli/utils/client.go new file mode 100644 index 0000000..35062cc --- /dev/null +++ b/ion-cli/utils/client.go @@ -0,0 +1,87 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package utils + +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/utils/client_test.go b/ion-cli/utils/client_test.go new file mode 100644 index 0000000..3990c99 --- /dev/null +++ b/ion-cli/utils/client_test.go @@ -0,0 +1,71 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package utils_test + +import ( + "context" + "math/big" + "testing" + + "github.com/clearmatics/ion/ion-cli/utils" +) + +const URL = "https://mainnet.infura.io" + +// NOTE: This tests depend on an external network (not really good) + +func TestClient(t *testing.T) { + client := utils.Client(URL) + client.Close() +} + +func TestGetReceipts(t *testing.T) { + expectedTotalReceipts := 92 + + client := utils.Client(URL) + defer client.Close() + + blockNumber := big.NewInt(6021002) + block, err := client.BlockByNumber(context.Background(), blockNumber) + if err != nil { + t.Error(err) + } + + receiptArr := utils.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 := utils.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 := utils.ClientRPC(URL) + defer clientRPC.Close() + + bNumber, _, err := utils.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/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/proof.go b/ion-cli/utils/proof.go new file mode 100644 index 0000000..e8f6748 --- /dev/null +++ b/ion-cli/utils/proof.go @@ -0,0 +1,52 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package utils + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" +) + +func GenerateProof(ctx context.Context, client *rpc.Client, txHash common.Hash) (txTriggerPath []byte, txTriggerRLP []byte, txTriggerProofArr []byte, receiptTrigger []byte, receiptTriggerProofArr []byte) { + blockNumberStr, txTrigger, err := BlockNumberByTransactionHash(ctx, client, txHash) + if err != nil { + fmt.Printf("Error: couldn't find block by tx hash: %s\n", err) + } + + // Convert returned blocknumber + var blockNumber big.Int + blockNumber.SetString((*blockNumberStr)[2:], 16) + + clientETH := ethclient.NewClient(client) + eventTxBlockNumber := blockNumber + block, err := clientETH.BlockByNumber(ctx, &eventTxBlockNumber) + if err != nil { + fmt.Printf("Error: retrieving block: %s\n", err) + } + + var idx byte + tx := block.Transactions() + txTrie := TxTrie(tx) + blockReceipts := GetBlockTxReceipts(clientETH, block) + receiptTrie := ReceiptTrie(blockReceipts) + + // Calculate transaction index) + for i := 0; i < len(tx); i++ { + if txHash == tx[i].Hash() { + idx = byte(i) + } + } + + txTriggerPath = append(txTriggerPath, idx) + txTriggerRLP, _ = rlp.EncodeToBytes(txTrigger) + txTriggerProofArr = Proof(txTrie, txTriggerPath[:]) + receiptTrigger, _ = rlp.EncodeToBytes(blockReceipts[txTriggerPath[0]]) + receiptTriggerProofArr = Proof(receiptTrie, txTriggerPath[:]) + + return +} diff --git a/ion-cli/utils/proof_test.go b/ion-cli/utils/proof_test.go new file mode 100644 index 0000000..e7b613b --- /dev/null +++ b/ion-cli/utils/proof_test.go @@ -0,0 +1,35 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package utils_test + +import ( + "context" + "encoding/hex" + "testing" + + "github.com/clearmatics/ion/ion-cli/utils" + "github.com/stretchr/testify/assert" +) + +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) { + ctx := context.Background() + + // CONTRACT_ADDR, _ := utils.StringToBytes32("61621bcf02914668f8404c1f860e92fc1893f74c") + TXHASH, _ := utils.StringToBytes32("afc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e") + + // Connect to the RPC Client + client := utils.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)) +} 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..758a78a --- /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 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(TESTBLOCK), &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(TESTBLOCK), &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(TESTBLOCK), &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/ion-cli/utils/trie.go b/ion-cli/utils/trie.go new file mode 100644 index 0000000..6ee67cc --- /dev/null +++ b/ion-cli/utils/trie.go @@ -0,0 +1,112 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package utils + +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/utils/type.go b/ion-cli/utils/type.go new file mode 100644 index 0000000..ce67f00 --- /dev/null +++ b/ion-cli/utils/type.go @@ -0,0 +1,517 @@ +// Copyright (c) 2018 Clearmatics Technologies Ltd +package utils + +import ( + "errors" + "fmt" + "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 %d 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: + 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 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/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 5317345..df0499d 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,17 +1,23 @@ -const IonLink = artifacts.require("IonLink"); -const IonLock = artifacts.require("IonLock"); -const Token = artifacts.require("Token"); +const Ion = artifacts.require("Ion"); +const Clique = artifacts.require("Clique"); +const EthereumStore = artifacts.require("EthereumStore"); +const EventFunction = artifacts.require("Function"); +const EventVerifier = artifacts.require("TriggerEventVerifier"); 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, "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") + .then(() => Ion.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)) + .then(() => EventFunction.deployed) } catch(err) { console.log('ERROR on deploy:',err); } -}; +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d2de8a8..09dce8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,33 +4,96 @@ "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==", - "dev": true + "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=", - "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" + }, + "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=", - "dev": true, "requires": { - "mime-types": "2.1.18", + "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=" + } + } + }, + "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", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.1.0", @@ -38,11 +101,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 +119,37 @@ "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 + "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": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "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" - } + "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.2.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", - "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=", - "dev": true + "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", @@ -93,11 +162,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.6" + } + }, "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 +188,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 +195,27 @@ "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==" + }, + "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=", - "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,50 +223,60 @@ "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.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=", - "dev": true + "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 + "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.3", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", - "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==", - "dev": true + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "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", @@ -196,26 +288,27 @@ "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=" + }, + "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=", - "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 + "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", @@ -223,16 +316,16 @@ "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", "dev": true, "requires": { - "babel-core": "6.26.0", + "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.15.1", + "commander": "2.11.0", "convert-source-map": "1.5.1", "fs-readdir-recursive": "1.1.0", "glob": "7.1.2", - "lodash": "4.17.5", + "lodash": "4.17.10", "output-file-sync": "1.1.2", "path-is-absolute": "1.0.1", "slash": "1.0.0", @@ -240,12 +333,6 @@ "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", @@ -262,50 +349,12 @@ "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=", - "dev": true, + "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", @@ -320,7 +369,7 @@ "convert-source-map": "1.5.1", "debug": "2.6.9", "json5": "0.5.1", - "lodash": "4.17.5", + "lodash": "4.17.10", "minimatch": "3.0.4", "path-is-absolute": "1.0.1", "private": "0.1.8", @@ -328,17 +377,10 @@ "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==", - "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-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -346,14 +388,13 @@ "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", "babel-types": "6.26.0", "detect-indent": "4.0.0", "jsesc": "1.3.0", - "lodash": "4.17.5", + "lodash": "4.17.10", "source-map": "0.5.7", "trim-right": "1.0.1" }, @@ -361,14 +402,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 +415,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 +425,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 +435,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,19 +446,17 @@ "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", "babel-types": "6.26.0", - "lodash": "4.17.5" + "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=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -433,7 +467,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 +478,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 +490,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 +499,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 +508,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,18 +517,16 @@ "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", - "lodash": "4.17.5" + "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=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -512,7 +539,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 +552,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 +569,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 +576,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 +632,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 +642,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 +652,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 +662,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 +673,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 +685,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 +693,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,20 +701,18 @@ "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", "babel-traverse": "6.26.0", "babel-types": "6.26.0", - "lodash": "4.17.5" + "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=", - "dev": true, "requires": { "babel-helper-define-map": "6.26.0", "babel-helper-function-name": "6.24.1", @@ -724,7 +729,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 +738,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 +746,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 +755,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 +763,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 +773,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,17 +781,16 @@ "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-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.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=", + "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", @@ -804,7 +802,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 +812,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 +822,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 +831,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 +844,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 +853,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 +861,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 +871,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 +879,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 +887,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 +897,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 +907,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 +916,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 +925,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 +934,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" } @@ -971,7 +954,7 @@ "dev": true, "requires": { "babel-runtime": "6.26.0", - "core-js": "2.5.3", + "core-js": "2.5.7", "regenerator-runtime": "0.10.5" }, "dependencies": { @@ -984,9 +967,9 @@ } }, "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==", + "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", @@ -1003,7 +986,7 @@ "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-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", @@ -1016,16 +999,15 @@ "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", + "browserslist": "3.2.8", "invariant": "2.2.4", - "semver": "5.5.0" + "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=", - "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", "babel-plugin-transform-es2015-arrow-functions": "6.22.0", @@ -1039,7 +1021,7 @@ "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-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", @@ -1059,14 +1041,13 @@ "integrity": "sha1-CDWZRRckiYWinRj21GXasWu4p9g=", "requires": { "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.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=", - "dev": true, "requires": { "babel-plugin-transform-class-constructor-call": "6.24.1", "babel-plugin-transform-export-extensions": "6.22.0", @@ -1077,7 +1058,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 +1069,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,13 +1081,12 @@ "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-core": "6.26.3", "babel-runtime": "6.26.0", - "core-js": "2.5.3", + "core-js": "2.5.7", "home-or-tmp": "2.0.0", - "lodash": "4.17.5", + "lodash": "4.17.10", "mkdirp": "0.5.1", "source-map-support": "0.4.18" }, @@ -1116,14 +1094,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" } @@ -1135,7 +1111,7 @@ "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", + "core-js": "2.5.7", "regenerator-runtime": "0.11.1" } }, @@ -1148,14 +1124,7 @@ "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==" - } + "lodash": "4.17.10" } }, "babel-traverse": { @@ -1171,14 +1140,7 @@ "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==" - } + "lodash": "4.17.10" } }, "babel-types": { @@ -1188,27 +1150,89 @@ "requires": { "babel-runtime": "6.26.0", "esutils": "2.0.2", - "lodash": "4.17.5", + "lodash": "4.17.10", "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==", - "dev": true + "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=", - "dev": true + "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==" + } + } + }, + "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.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, + "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" @@ -1217,12 +1241,12 @@ "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": "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", @@ -1234,53 +1258,69 @@ "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.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" + } + }, + "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.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true + "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.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, + "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.2", - "iconv-lite": "0.4.19", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", + "qs": "6.5.2", + "raw-body": "2.3.3", "type-is": "1.6.16" } }, - "boom": { - "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" - } - }, "brace-expansion": { "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 +1330,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 +1339,173 @@ "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.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=", - "dev": true, "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": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "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.30000823", - "electron-to-chromium": "1.3.42" + "caniuse-lite": "1.0.30000865", + "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", + "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-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", + "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 + "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=" + }, + "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=", - "dev": true, "requires": { "clone-response": "1.0.2", "get-stream": "3.0.0", @@ -1359,31 +1514,53 @@ "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": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true + "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.30000823", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000823.tgz", - "integrity": "sha512-3rrhqUxwBgrwNlWVUEwIJfqdZNwLPX18eTo7MGXb3gueDpbOFW6w5OXyHscdBd6IJcu9wnKmKVd7nSl+r7fmgw==", + "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=", - "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", @@ -1420,21 +1597,21 @@ "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, + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { - "ansi-styles": "3.2.1", + "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "5.3.0" + "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=", - "dev": true + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" }, "check-error": { "version": "1.0.2", @@ -1451,7 +1628,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", - "fsevents": "1.2.3", + "fsevents": "1.2.4", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -1460,11 +1637,55 @@ "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", + "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=", - "dev": true, "requires": { "restore-cursor": "2.0.0" } @@ -1472,14 +1693,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 +1706,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,265 +1714,277 @@ "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" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "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" - } - }, - "string-width": { - "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", - "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=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } + "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=", - "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, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", "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=", - "dev": true + "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=", - "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" + "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=", - "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", - "readable-stream": "2.3.5" + "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=", - "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=" + }, + "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.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, + "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.3" + "color-name": "1.1.1" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" }, "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 + "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=", - "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=" + }, + "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=", - "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.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=", - "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=" + }, + "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.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + "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=", - "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.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": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, + "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": { - "nice-try": "1.0.4", - "path-key": "2.0.1", - "semver": "5.5.0", + "lru-cache": "4.1.3", "shebang-command": "1.2.0", - "which": "1.3.0" + "which": "1.3.1" } }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, + "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": { - "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==", - "dev": true, - "requires": { - "hoek": "4.2.1" - } - } + "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 + "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", "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 +1992,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,22 +2015,100 @@ "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": { + "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", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, "requires": { - "mimic-response": "1.0.0" + "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": { @@ -1816,151 +2121,325 @@ } }, "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 + "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=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, - "delayed-stream": { + "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=", - "dev": true + "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=", - "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.1" + } }, "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" } }, + "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==" + }, + "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=", - "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, + "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" + "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==", - "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 + "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.42", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz", - "integrity": "sha1-lcM78B0MxAVVauyJn+Yf1NduoPk=", + "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=", - "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", + "bn.js": "4.11.8", "brorand": "1.1.0", - "hash.js": "1.1.3", + "hash.js": "1.1.5", "hmac-drbg": "1.0.1", "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", + "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=", - "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=" + }, + "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", + "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, + "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==", - "dev": true, "requires": { "prr": "1.0.1" } @@ -1969,17 +2448,22 @@ "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" + }, + "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.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, + "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" } @@ -1987,8 +2471,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 +2482,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 +2493,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 +2511,153 @@ } } }, + "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.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "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": "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", @@ -2046,49 +2667,249 @@ "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-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.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, + "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", + "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.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", + "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==", - "dev": true, "requires": { - "source-map-support": "0.5.4", - "webpack-cli": "2.0.12" + "source-map-support": "0.5.6", + "webpack-cli": "2.1.5" } }, - "ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "dev": true, + "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": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" + "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=" + } } }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "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" + } + }, + "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", + "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=", - "dev": true, "requires": { "cross-spawn": "5.1.0", "get-stream": "3.0.0", @@ -2097,32 +2918,17 @@ "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=", - "dev": true, - "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=", - "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 +2937,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" + "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=", - "dev": true, "requires": { "homedir-polyfill": "1.0.1" } @@ -2149,7 +2958,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", @@ -2170,7 +2978,7 @@ "on-finished": "2.3.0", "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.3", + "proxy-addr": "2.0.4", "qs": "6.5.1", "range-parser": "1.2.0", "safe-buffer": "5.1.1", @@ -2183,28 +2991,110 @@ "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==", - "dev": true + "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=", - "dev": true + "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.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", - "dev": true, + "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.19", + "iconv-lite": "0.4.23", "tmp": "0.0.33" } }, @@ -2212,7 +3102,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,51 +3109,366 @@ "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-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=", - "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=" + }, + "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", "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" + } + }, + "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", - "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, + "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": "1.1.7", + "randomatic": "3.0.0", "repeat-element": "1.1.2", "repeat-string": "1.6.1" } @@ -2273,7 +3477,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", @@ -2282,52 +3485,65 @@ "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": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "requires": { - "locate-path": "2.0.0" + "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=", - "dev": true, "requires": { - "readable-stream": "2.3.5" + "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.68.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.68.0.tgz", - "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=", - "dev": true + "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.2", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", - "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", - "dev": true, + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "requires": { - "is-function": "1.0.1" + "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=", - "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,56 +3551,85 @@ "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", - "mime-types": "2.1.18" + "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=", - "dev": true + "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=", - "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" + "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=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "jsonfile": "2.4.0", "klaw": "1.3.1", "path-is-absolute": "1.0.1", - "rimraf": "2.2.8" + "rimraf": "2.6.2" } }, - "fs-readdir-recursive": { + "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", "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", @@ -2393,18 +3638,17 @@ "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==", + "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.9.1" + "node-pre-gyp": "0.10.0" }, "dependencies": { "abbrev": { @@ -2485,7 +3729,7 @@ } }, "deep-extend": { - "version": "0.4.2", + "version": "0.5.1", "bundled": true, "dev": true, "optional": true @@ -2663,7 +3907,7 @@ } }, "node-pre-gyp": { - "version": "0.9.1", + "version": "0.10.0", "bundled": true, "dev": true, "optional": true, @@ -2674,7 +3918,7 @@ "nopt": "4.0.1", "npm-packlist": "1.1.10", "npmlog": "4.1.2", - "rc": "1.2.6", + "rc": "1.2.7", "rimraf": "2.6.2", "semver": "5.5.0", "tar": "4.4.1" @@ -2772,12 +4016,12 @@ "optional": true }, "rc": { - "version": "1.2.6", + "version": "1.2.7", "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "0.4.2", + "deep-extend": "0.5.1", "ini": "1.3.5", "minimist": "1.2.0", "strip-json-comments": "2.0.1" @@ -2925,21 +4169,50 @@ } } }, + "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", + "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==", + "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.4", - "webpack-cli": "2.0.12" + "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.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true + "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", @@ -2950,14 +4223,17 @@ "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=" + }, + "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=", - "dev": true, "requires": { "assert-plus": "1.0.0" } @@ -2966,7 +4242,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 +4251,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", @@ -2985,10 +4259,10 @@ "is-retry-allowed": "1.1.0", "is-stream": "1.1.0", "isurl": "1.0.0", - "lowercase-keys": "1.0.0", + "lowercase-keys": "1.0.1", "p-cancelable": "0.3.0", "p-timeout": "1.2.1", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "timed-out": "4.0.1", "url-parse-lax": "1.0.0", "url-to-options": "1.0.1" @@ -2997,14 +4271,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 +4284,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 +4313,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,17 +4326,20 @@ "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" }, "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=", - "dev": true, "requires": { "minimist": "0.1.0" } @@ -3074,7 +4350,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,16 +4359,19 @@ "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" } }, + "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=", - "dev": true, "requires": { "min-document": "2.19.0", "process": "0.5.2" @@ -3103,7 +4381,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,13 +4391,12 @@ "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", "ini": "1.3.5", "is-windows": "1.0.2", - "which": "1.3.0" + "which": "1.3.1" } }, "globals": { @@ -3129,31 +4405,22 @@ "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=", - "dev": true, + "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" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } } }, "got": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.0.tgz", - "integrity": "sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==", - "dev": true, + "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", @@ -3163,49 +4430,51 @@ "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", + "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.1", + "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=", - "dev": true + "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 + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, "grouped-queue": { "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" + "lodash": "4.17.10" } }, "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true + "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=", - "dev": true, "requires": { "async": "1.5.2", "optimist": "0.6.1", @@ -3213,11 +4482,15 @@ "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=", - "dev": true, "requires": { "amdefine": "1.0.1" } @@ -3227,14 +4500,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" @@ -3246,92 +4517,127 @@ "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=", - "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" } }, - "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, + "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", - "minimalistic-assert": "1.0.0" + "safe-buffer": "5.1.2" } }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, + "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": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" + "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=", - "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", + "hash.js": "1.1.5", + "minimalistic-assert": "1.0.1", "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==", - "dev": true - }, "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,71 +4647,102 @@ "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" } }, "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 + "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==", - "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, + "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.1", + "depd": "1.1.2", "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=", - "dev": true - } + "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=", - "dev": true, "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", - "sshpk": "1.14.1" + "sshpk": "1.14.2" } }, "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 + "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" + } + }, + "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", + "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=", - "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 +4751,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,47 +4759,98 @@ "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, + "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", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "external-editor": "2.1.0", + "external-editor": "2.2.0", "figures": "2.0.0", - "lodash": "4.17.5", + "lodash": "4.17.10", "mute-stream": "0.0.7", "run-async": "2.3.0", - "rxjs": "5.5.7", + "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=", - "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" @@ -3474,26 +4861,31 @@ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "requires": { - "loose-envify": "1.3.1" + "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=", - "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 + "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=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "1.0.1", @@ -3508,29 +4900,55 @@ "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" } }, + "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=", - "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,41 +4956,38 @@ "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" } }, "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 + "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=", - "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 +4995,17 @@ "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-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", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -3595,61 +5013,93 @@ "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, + "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": "0.2.4" + "symbol-observable": "1.2.0" }, "dependencies": { "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 + "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=", - "dev": true + "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=", - "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,59 +5107,62 @@ "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 + "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=", - "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" + }, + "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=", - "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,27 +5170,30 @@ "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", "resolve": "1.1.7", "supports-color": "3.2.3", - "which": "1.3.0", + "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=", - "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 +5205,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 +5226,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 +5236,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,50 +5252,53 @@ "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" + "esprima": "4.0.1" } }, "jsbn": { "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, + "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.42", - "colors": "1.2.1", - "flow-parser": "0.68.0", - "lodash": "4.17.5", + "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.0", + "neo-async": "2.5.1", "node-dir": "0.1.8", "nomnom": "1.8.1", - "recast": "0.14.5", + "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=", - "dev": true + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" }, "json-bigint-string": { "version": "1.0.0", @@ -3880,50 +5309,42 @@ "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 + "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=", - "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 - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "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 +5353,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,21 +5360,30 @@ "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=", - "dev": true, "requires": { "browserify-sha3": "0.0.1", - "sha3": "1.2.0" + "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==", - "dev": true, "requires": { "json-buffer": "3.0.0" } @@ -3963,7 +5392,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 +5400,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,39 +5408,251 @@ "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": { + "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-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", + "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=", - "dev": true, "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=", - "dev": true, + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.1.tgz", + "integrity": "sha512-MSMUUVN1f8aRnPi4034RkOqdiUlpYW+FqwFE3aL0uYNPRavkt2S2SsSpDDofn8BDpqv2RNnsdOcCHWsChcq77A==", "requires": { - "chalk": "1.1.3", + "@samverschueren/stream-to-observable": "0.3.0", "cli-truncate": "0.2.1", "figures": "1.7.0", "indent-string": "2.1.0", - "is-observable": "0.2.0", + "is-observable": "1.1.0", "is-promise": "2.1.0", "is-stream": "1.1.0", "listr-silent-renderer": "1.1.1", @@ -4023,41 +5662,14 @@ "log-update": "1.0.2", "ora": "0.2.3", "p-map": "1.2.0", - "rxjs": "5.5.7", - "stream-to-observable": "0.2.0", + "rxjs": "6.2.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=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "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", - "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=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4067,39 +5679,29 @@ "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" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, + "rxjs": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", + "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", "requires": { - "ansi-regex": "2.1.1" + "tslib": "1.9.3" } - }, - "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 } } }, "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", @@ -4111,36 +5713,10 @@ "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=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "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", - "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=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -4149,32 +5725,15 @@ "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" } - }, - "strip-ansi": { - "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": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, @@ -4182,7 +5741,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", @@ -4190,36 +5748,10 @@ "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=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "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", - "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=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -4228,7 +5760,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,61 +5768,35 @@ "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" } - }, - "strip-ansi": { - "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": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, "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=", - "dev": true, + "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": "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=", - "dev": true - } + "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=", - "dev": true, "requires": { "big.js": "3.2.0", "emojis-list": "2.1.0", @@ -4302,105 +5807,68 @@ "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" + }, + "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.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 + "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=", - "dev": true - }, - "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" - } + "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==", - "dev": true, "requires": { - "chalk": "2.3.2" + "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=", - "dev": true, "requires": { "ansi-escapes": "1.4.0", "cli-cursor": "1.0.2" @@ -4409,14 +5877,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 +5890,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,53 +5906,86 @@ "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", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "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.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true + "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.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", - "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "dev": true, + "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.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, + "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=", - "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 +5994,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", @@ -4505,46 +6001,60 @@ } }, "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=", - "dev": true, + "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.4.2", - "ejs": "2.5.7", + "deep-extend": "0.6.0", + "ejs": "2.6.1", "glob": "7.1.2", - "globby": "6.1.0", + "globby": "7.1.1", + "isbinaryfile": "3.0.2", "mkdirp": "0.5.1", "multimatch": "2.1.0", - "rimraf": "2.2.8", + "rimraf": "2.6.2", "through2": "2.0.3", - "vinyl": "2.1.0" + "vinyl": "2.2.0" }, "dependencies": { "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=" + }, + "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=", - "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, + "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", @@ -4556,39 +6066,89 @@ } } }, + "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=", - "dev": true, "requires": { "errno": "0.1.7", - "readable-stream": "2.3.5" + "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=", - "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=" + }, + "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=", - "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,80 +6165,97 @@ "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==", - "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 + "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.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, + "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.33.0" + "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==", - "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 + "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=", - "dev": true, "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=", - "dev": true + "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=", - "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" } }, "minimist": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", - "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=", - "dev": true + "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=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -4686,86 +6263,73 @@ "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=" } } }, + "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": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, + "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.9.0", - "debug": "2.6.8", - "diff": "3.2.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", + "glob": "7.1.2", + "growl": "1.10.3", "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "supports-color": "4.4.0" }, "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, + "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.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" - } + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" }, "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 + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "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": "1.0.0" + "has-flag": "2.0.0" } } } }, + "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", @@ -4775,7 +6339,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 +6349,100 @@ "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=" + }, + "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", - "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=" + }, + "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=", - "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 + "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==", - "dev": true + "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", - "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 +6451,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 +6466,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,11 +6487,10 @@ "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", + "hosted-git-info": "2.7.1", "is-builtin-module": "1.0.0", - "semver": "5.5.0", + "semver": "5.4.1", "validate-npm-package-license": "3.0.3" } }, @@ -4885,7 +6498,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 +6506,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,54 +6516,128 @@ "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", "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" + }, + "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=", - "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-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=", - "dev": true, "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=", - "dev": true, "requires": { "ee-first": "1.1.1" } @@ -4961,7 +6646,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 +6654,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 +6662,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 +6670,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 +6683,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 +6696,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", @@ -5025,36 +6703,10 @@ "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=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "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", - "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=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -5062,33 +6714,16 @@ "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" } - }, - "strip-ansi": { - "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": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, @@ -5101,25 +6736,20 @@ "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, + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "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=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "output-file-sync": { "version": "1.1.2", @@ -5133,16 +6763,14 @@ } }, "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 + "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=", - "dev": true, "requires": { "p-reduce": "1.0.0" } @@ -5150,26 +6778,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, + "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" } @@ -5178,28 +6802,24 @@ "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" + "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==", - "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 +6827,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,71 +6856,80 @@ "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", + "for-each": "0.3.3", "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=", - "dev": true, + "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", - "json-parse-better-errors": "1.0.1" + "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=", - "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=" + }, + "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": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "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=", - "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, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "requires": { - "pify": "3.0.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "pathval": { @@ -5299,126 +6938,200 @@ "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=", - "dev": true + "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", - "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 + "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=", - "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" } }, + "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.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", - "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 + "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=", - "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, + "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.6.0" + "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=", - "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.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=", - "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 + "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==", - "dev": true, "requires": { "decode-uri-component": "0.2.0", "object-assign": "4.1.1", @@ -5426,114 +7139,138 @@ } }, "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, + "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": "3.0.0", - "kind-of": "4.0.0" + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" }, "dependencies": { "is-number": { - "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" - }, - "dependencies": { - "kind-of": { - "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" - } - } - } + "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": "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" - } + "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=", - "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, + "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.2", - "iconv-lite": "0.4.19", + "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=", - "dev": true, "requires": { "pify": "3.0.0", - "safe-buffer": "5.1.1" + "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": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, + "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": "4.0.0", + "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", - "path-type": "3.0.0" + "path-type": "1.1.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=", - "dev": true, + "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": "2.1.0", - "read-pkg": "3.0.0" + "find-up": "1.1.2", + "read-pkg": "1.1.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==", - "dev": true, + "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.1", - "string_decoder": "1.0.3", + "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": { @@ -5545,18 +7282,17 @@ "requires": { "graceful-fs": "4.1.11", "minimatch": "3.0.4", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "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, + "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.3", - "esprima": "4.0.0", + "ast-types": "0.11.5", + "esprima": "4.0.1", "private": "0.1.8", "source-map": "0.6.1" } @@ -5565,16 +7301,14 @@ "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" + "resolve": "1.8.1" } }, "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 + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" }, "regenerator-runtime": { "version": "0.11.1", @@ -5585,7 +7319,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,18 +7329,30 @@ "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" } }, + "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=", - "dev": true, "requires": { - "regenerate": "1.3.3", + "regenerate": "1.4.0", "regjsgen": "0.2.0", "regjsparser": "0.1.5" } @@ -5615,14 +7360,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 +7373,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 +7396,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 +7410,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,64 +7417,72 @@ "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=" } } }, "request": { - "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, + "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.6.0", + "aws4": "1.7.0", "caseless": "0.12.0", "combined-stream": "1.0.6", - "extend": "3.0.1", + "extend": "3.0.2", "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", + "mime-types": "2.1.19", "oauth-sign": "0.8.2", "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", + "qs": "6.5.2", + "safe-buffer": "5.1.2", "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "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=", - "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" + } }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, + "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" } @@ -5747,67 +7491,96 @@ "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" + }, + "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=", - "dev": true, "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=", - "dev": true + "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=", - "dev": true, "requires": { - "lowercase-keys": "1.0.0" + "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=", - "dev": true, "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=", - "dev": true, "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=", - "dev": true + "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=", - "dev": true, "requires": { "is-promise": "2.1.0" } @@ -5815,50 +7588,124 @@ "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" } }, "rxjs": { - "version": "5.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", - "integrity": "sha512-Hxo2ac8gRQjwjtKgukMIwBRbq5+KAeEV5hXM4obYBOAghev41bDQWgFH4svYiU9UnQ5kNww2LgfyBdevCd2HXA==", - "dev": true, + "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.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "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=", - "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": "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", + "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" + } + }, + "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.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "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==", - "dev": true, "requires": { "debug": "2.6.9", "depd": "1.1.2", @@ -5867,19 +7714,25 @@ "escape-html": "1.0.3", "etag": "1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.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==", - "dev": true, "requires": { "encodeurl": "1.0.2", "escape-html": "1.0.3", @@ -5891,20 +7744,18 @@ "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", + "body-parser": "1.18.3", "cors": "2.8.4", "express": "4.16.3", - "request": "2.85.0", - "xhr": "2.4.1" + "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=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-immediate-shim": { "version": "1.0.1", @@ -5913,17 +7764,50 @@ "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" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true + "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.0", - "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.0.tgz", - "integrity": "sha1-aYnxtwpJhwWHajc+LGKs6WqpOZo=", - "dev": true, + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", + "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", "requires": { "nan": "2.10.0" } @@ -5932,7 +7816,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 +7823,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, + "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" } }, - "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, + "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", @@ -5986,240 +7858,164 @@ "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 + "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=", - "dev": true - }, - "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" - } - }, - "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-VusCfWW00tzmyy4tMsTUr8nh1wc=" }, - "solc": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.23.tgz", - "integrity": "sha512-AT7anLHY6uIRg2It6N0UlCHeZ7YeecIkUhnlirrCgCPCUevtnoN48BxvgigN/4jJTRljv5oFhAJtI6gvHzT5DQ==", - "dev": true, + "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": { - "fs-extra": "0.30.0", - "memorystream": "0.3.1", - "require-from-string": "1.2.1", - "semver": "5.5.0", - "yargs": "4.8.1" + "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": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, + "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": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" + "is-descriptor": "0.1.6" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "is-extendable": "0.1.1" } }, - "is-fullwidth-code-point": { + "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/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "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=", - "dev": true, - "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=", - "dev": true, - "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=", - "dev": true, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "requires": { - "error-ex": "1.3.1" + "is-descriptor": "1.0.2" } }, - "path-exists": { - "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" - } - }, - "path-type": { - "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", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "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, + "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": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" + "kind-of": "6.0.2" } }, - "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=", - "dev": true, + "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": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "kind-of": "6.0.2" } }, - "string-width": { + "is-descriptor": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } }, - "strip-ansi": { + "isobject": { "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" - } - }, - "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 - }, - "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 - }, - "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", - "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" - } + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, - "yargs-parser": { - "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" - } + "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.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", + "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.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,441 +8024,195 @@ "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": { - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, + "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": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" + "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" + } + }, + "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": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "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", - "wrap-ansi": "2.1.0" - } - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "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 - }, - "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, + "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": { - "inherits": "2.0.3", - "minimatch": "0.3.0" - } - }, - "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" - } - }, - "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=", - "dev": true, - "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" - } - }, - "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, - "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", - "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" - } - }, - "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" - } - }, - "parse-json": { - "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" - } - }, - "path-exists": { - "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" - } - }, - "path-type": { - "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", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "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", - "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=", - "dev": true, - "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=", - "dev": true, - "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=", - "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 - }, - "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 - }, - "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 - }, - "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", - "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=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" + "is-descriptor": "0.1.6" } } } }, - "sort-keys": { - "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" - } - }, - "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 - }, - "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" - } - }, - "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==", - "dev": true, - "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==", - "dev": true - }, - "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" - } - }, - "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 - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "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", - "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==", - "dev": true - }, - "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" - } + "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=", - "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, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "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==", - "dev": true, - "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=", - "dev": true + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "3.0.0" + "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=", - "dev": true, "requires": { "is-utf8": "0.2.1" } @@ -6671,193 +8221,689 @@ "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" } }, + "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", - "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" } }, - "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" - } - }, - "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 + "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=" }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, - "temp": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", - "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "dev": true, + "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": { - "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=", - "dev": true - }, - "textextensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", - "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { + "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", + "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": { + "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.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", + "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=" + } + } + }, + "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", + "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==" + }, + "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", + "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", + "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=", - "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 + "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==", - "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", - "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.7.tgz", - "integrity": "sha512-fe6BIcD9xo6iIJvV1m6ZhOk56kmB8k38kdoWOKYnPPw7ZUUSupgojeTb2K5e+4qIpIHvEvmET4yLUjSGR+hvwA==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.13.tgz", + "integrity": "sha1-vydYaYi0/4RWPt+/MrR5QUCKdq0=", "dev": true, "requires": { - "mocha": "3.5.3", + "mocha": "4.1.0", "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=", - "dev": true, - "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=", - "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" + "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" + } + } } }, - "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, + "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": { - "source-map": "0.5.7", + "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" + } + } + } + }, + "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" }, @@ -6866,14 +8912,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 +8929,24 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, + "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=", - "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 +8961,146 @@ "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==" + }, + "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", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true + "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=", - "dev": true + "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.2", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz", - "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", - "dev": true + "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=", - "dev": true, "requires": { "prepend-http": "2.0.0" } @@ -6953,14 +9108,17 @@ "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 + "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", @@ -6971,32 +9129,27 @@ "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 + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" }, "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 + "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", @@ -7011,7 +9164,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" @@ -7020,14 +9172,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,102 +9188,1339 @@ "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": "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=", - "dev": true, + "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-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": { + "got": "7.1.0", + "swarm-js": "0.1.37", + "underscore": "1.8.3" + }, + "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=" + }, + "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==", + "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": { + "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-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-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": { + "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-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": { - "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-core": "1.0.0-beta.36", + "web3-core-method": "1.0.0-beta.36", + "web3-utils": "1.0.0-beta.36" }, "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "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": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", - "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", - "dev": true, + "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": { - "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": "1.0.0-beta.35", + "xhr2-cookies": "1.1.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-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-eth-iban": "1.0.0-beta.33", - "web3-utils": "1.0.0-beta.33" + "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=", - "dev": true + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" } } }, - "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, + "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": { - "bn.js": "4.11.6", "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.33", - "web3-utils": "1.0.0-beta.33" + "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=", - "dev": true + "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-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, + "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": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.33" + "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.33", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.33.tgz", - "integrity": "sha1-4JG3mU8JtxSwGYpAV9OtLrjL4jg=", - "dev": true, + "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", @@ -7144,17 +10531,34 @@ "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=", - "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=", - "dev": true + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" } } }, @@ -7162,7 +10566,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 +10573,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 + "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==", - "dev": true, "requires": { "async": "1.5.2", "babel-plugin-transform-flow-strip-types": "6.22.0", @@ -7191,9 +10591,9 @@ "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", + "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", @@ -7202,140 +10602,281 @@ "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==", - "dev": true, + "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": { - "ast-types": "0.10.1", - "core-js": "2.5.3", - "esprima": "4.0.0", - "private": "0.1.8", - "source-map": "0.6.1" + "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" } } } }, - "webpack-cli": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.12.tgz", - "integrity": "sha512-kMi6NquWwUhmQok2IFrtAEIbaVvujzYvtDGb5WElkwylbLboDsCgizv8IjSi/Q6SQRJ8Crayl1JCBnIJ3rU4Rg==", - "dev": true, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", "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" + "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, + "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": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "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.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true + "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=", - "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" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "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" - } - }, - "string-width": { - "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", - "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=", - "dev": true, - "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=", - "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,45 +10887,48 @@ "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", + "safe-buffer": "5.1.2", "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==", - "dev": true, + "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==", - "dev": true, "requires": { "buffer-to-arraybuffer": "0.0.5", "object-assign": "4.1.1", "query-string": "5.1.1", - "simple-get": "2.7.0", + "simple-get": "2.8.1", "timed-out": "4.0.1", "url-set-query": "1.0.0", - "xhr": "2.4.1" + "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=", - "dev": true, "requires": { "xhr-request": "1.1.0" } @@ -7392,126 +10936,233 @@ "xhr2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", - "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=", - "dev": true + "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=", - "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 + "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=", - "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, + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "requires": { - "cliui": "4.0.0", + "cliui": "3.2.0", "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.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": "2.1.1", - "which-module": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", "y18n": "3.2.1", - "yargs-parser": "9.0.2" + "yargs-parser": "2.4.1" } }, "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, + "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" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "requires": { - "camelcase": "4.1.0" + "buffer-crc32": "0.2.13", + "fd-slicer": "1.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==", - "dev": true, + "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.3.2", + "chalk": "2.4.1", + "cross-spawn": "6.0.5", "debug": "3.1.0", "diff": "3.5.0", "escape-string-regexp": "1.0.5", - "globby": "6.1.0", + "globby": "8.0.1", "grouped-queue": "0.3.3", - "inquirer": "3.3.0", + "inquirer": "5.2.0", "is-scoped": "1.0.0", - "lodash": "4.17.5", + "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.2" + "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==", - "dev": true, "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": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.2", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "external-editor": "2.1.0", + "external-editor": "2.2.0", "figures": "2.0.0", - "lodash": "4.17.5", + "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", + "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.3", - "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.3.tgz", - "integrity": "sha512-mODmrZ26a94djmGZZuIiomSGlN4wULdou29ZwcySupb2e9FdvoCl7Ps2FqHFjEHio3kOl/iBeaNqrnx3C3NwWg==", - "dev": true, + "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.0", - "chalk": "2.3.2", + "async": "2.6.1", + "chalk": "2.4.1", "cli-table": "0.3.1", - "cross-spawn": "5.1.0", + "cross-spawn": "6.0.5", "dargs": "5.1.0", "dateformat": "3.0.3", "debug": "3.1.0", @@ -7520,63 +11171,145 @@ "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", + "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.1", + "shelljs": "0.8.2", "text-table": "0.2.0", "through2": "2.0.3", - "yeoman-environment": "2.0.5" + "yeoman-environment": "2.3.1" }, "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, + "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": { - "lodash": "4.17.5" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" } }, "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=", - "dev": true, + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "requires": { - "lru-cache": "4.1.2", + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", "shebang-command": "1.2.0", - "which": "1.3.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==", - "dev": true, "requires": { "ms": "2.0.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "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" + } }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, + "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": { - "glob": "7.1.2" + "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 d6640da..b55209e 100644 --- a/package.json +++ b/package.json @@ -8,15 +8,21 @@ "license": "LGPL-3.0+", "dependencies": { "babel-preset-node6": "^11.0.0", - "solc": "^0.4.23", + "bignumber.js": "^8.0.1", + "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", - "solidity-coverage": "^0.5.0 " + "truffle-assertions": "^0.6.3", + "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", @@ -24,21 +30,22 @@ "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": "^1.0.0-beta.33", "web3-eth-abi": "^1.0.0-beta.33", "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 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", - "deploya": "truffle deploy --network testrpca", - "deployb": "truffle deploy --network testrpcb", "test": "truffle test", + "debug": "truffle debug", "coverage": "solidity-coverage", - "lint": "solhint contracts/**/*.sol" + "lint": "solhint contracts/**/*.sol", + "genbin": "solc --overwrite --bin ./contracts/*.sol -o abi", + "genabi": "solc --overwrite --abi ./contracts/*.sol -o abi" } } diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 285d93a..0000000 --- a/requirements.txt +++ /dev/null @@ -1,19 +0,0 @@ -requests==2.20.0 -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/PatriciaTrieTest.sol b/test/PatriciaTrieTest.sol new file mode 100644 index 0000000..441d909 --- /dev/null +++ b/test/PatriciaTrieTest.sol @@ -0,0 +1,76 @@ +pragma solidity ^0.4.23; + +import "truffle/Assert.sol"; +import "../contracts/libraries/PatriciaTrie.sol"; + +contract PatriciaTrieTest { + constructor() public {} + + function testSucceedVerifyNestedNodes() 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 testFailVerifyNestedNodes() returns (bool) { + bytes32 rootHash = 0xda2e968e25198a0a41e4dcdc6fcb03b9d49274b3d44cb35d921e4ebe3fb5c54c; + + 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" ); + + 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/clique.js b/test/clique.js new file mode 100644 index 0000000..d52a0f5 --- /dev/null +++ b/test/clique.js @@ -0,0 +1,343 @@ +// 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'); +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 rinkeby + let genesisBlock; + let VALIDATORS; + let GENESIS_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); + + genesisBlock = await await rinkeby.eth.getBlock(0); + VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + GENESIS_HASH = genesisBlock.hash; + }) + + it('Deploy Contract', async () => { + let chainId = await ion.chainId(); + + assert.equal(chainId, DEPLOYEDCHAINID); + }) + + describe('Register Chain', () => { + it('Successful Register Chain', async () => { + // Successfully add id of another chain + 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); + + assert(chainExists); + + // 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(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address).should.be.rejected; + }) + + it('Check Validators', async () => { + // Successfully add id of another chain + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + let registeredValidators = await clique.getValidators.call(TESTCHAINID, GENESIS_HASH); + + for (let i = 0; i < VALIDATORS.length; i++) { + let validatorExists = registeredValidators.some(v => { return v == VALIDATORS[i] });; + assert(validatorExists); + } + }) + + it('Check Genesis Hash', async () => { + // Successfully add id of another chain + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + 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 () => { + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + // Fetch block 1 from rinkeby + const block = await 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 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); + + 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 () => { + // Successfully add id of another chain + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + // Fetch block 1 from rinkeby + const block = await 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 () => { + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + // Fetch block 1 from testrpc + const block = await rinkeby.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 () => { + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + // Fetch block 1 from testrpc + const block = await 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 () => { + 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); + assert.equal(voteThreshold, 2); + + let voteProposal = await clique.getProposal.call(TESTCHAINID, ADD_VALIDATORS_GENESIS_HASH, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Fetch block 873982 from rinkeby + let block = await 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 = await 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"); + let submittedEvent = validationReceipt.logs.find(l => { return l.event == 'BlockSubmitted' }); + let blockHash = submittedEvent.args.blockHash; + + // Check proposal is added + voteProposal = await clique.getProposal.call(TESTCHAINID, blockHash, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 1); + + // Fetch block 873984 from rinkeby + block = await 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 = await 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 = await 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"); + submittedEvent = validationReceipt.logs.find(l => { return l.event == 'BlockSubmitted' }); + blockHash = submittedEvent.args.blockHash; + + // Check proposal is added + voteProposal = await clique.getProposal.call(TESTCHAINID, blockHash, VALIDATORS_FINISH[1]); + assert.equal(voteProposal, 0); + + // Check all validators exist + registeredValidators = await clique.getValidators.call(TESTCHAINID, blockHash); + for (let i = 0; i < VALIDATORS_FINISH.length; 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/helpers/encoder.js b/test/helpers/encoder.js new file mode 100644 index 0000000..d735e7c --- /dev/null +++ b/test/helpers/encoder.js @@ -0,0 +1,109 @@ +// Copyright (c) 2016-2018 Clearmatics Technologies Ltd +// SPDX-License-Identifier: LGPL-3.0+ + +const Web3Utils = require('web3-utils'); +const rlp = require('rlp'); +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, + 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); + + return { + unsigned: encodedUnsignedHeader, + signed: encodedSignedHeader, + rawunsigned: unsignedHeader, + rawsigned: signedHeader, + extraDataSignature: extraDataSignature, + extraDataShort: extraDataShort, + extraBytesShort: extraBytesShort + }; +} + +// 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/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/utils.js b/test/helpers/utils.js index fbaf181..74065a7 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,12 @@ 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} +module.exports = utils; \ No newline at end of file diff --git a/test/integration-clique_ethereum.js b/test/integration-clique_ethereum.js new file mode 100644 index 0000000..c884d36 --- /dev/null +++ b/test/integration-clique_ethereum.js @@ -0,0 +1,737 @@ +// 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) => { + let genesisBlock; + let VALIDATORS; + let GENESIS_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); + + genesisBlock = await rinkeby.eth.getBlock(0); + VALIDATORS = encoder.extractValidators(genesisBlock.extraData); + GENESIS_HASH = genesisBlock.hash; + }) + + 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(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); + }) + + it('Fail Register Twice', async () => { + await clique.register(); + + 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(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address).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(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address).should.be.rejected; + }) + }) + + describe('Add Block', () => { + it('Successful Add Block', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + // Fetch block 1 from rinkeby + const block = await 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"); + + 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 () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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 () => { + await clique.register(); +// await clique.RegisterChain(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + // Fetch block 1 from rinkeby + const block = await 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(TESTCHAINID, VALIDATORS, GENESIS_HASH, storage.address); + + // Fetch block 2 from rinkeby instead of block 1 + const block = await 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 = await 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(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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"); + }) + + it('Fail Tx Proof with wrong tx value', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + + it('Fail Tx Proof with wrong tx nodes', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + + it('Fail Tx Proof with wrong path', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + }) + + describe('Check Receipt Proof of Tx 0xafc3ab60059ed38e71c7f6bea036822abe16b2c02fcf770a4f4b5fffcbfe6e7e on Rinkeby', () => { + it('Successful Check Receipt Proof', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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"); + }) + + it('Fail Receipt Proof with wrong receipt value', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + + it('Fail Receipt Proof with wrong receipt nodes', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + + it('Fail Receipt Proof with wrong path', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + }) + + describe('Check Roots Proof', () => { + it('Successful Check Roots Proof', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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"); + }) + + it('Fail Roots Proof with wrong chain id', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + + it('Fail Roots Proof with wrong block hash', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + + it('Fail Roots Proof with wrong tx nodes', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + + it('Fail Roots Proof with wrong receipt nodes', async () => { + await clique.register(); + await clique.RegisterChain(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + }) + }) + + 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(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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()") }); + 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(TESTCHAINID, VALIDATORS_B2657422, TRIG_GENESIS_HASH, storage.address); + + // Fetch block 2657422 from rinkeby + const block = await 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"); + + 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; + + // 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; + }) + }) + + +// 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"; +// 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) { + 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/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/ion.js b/test/ion.js new file mode 100644 index 0000000..cb2b050 --- /dev/null +++ b/test/ion.js @@ -0,0 +1,223 @@ +// 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') +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 Ion = artifacts.require("Ion"); +const MockValidation = artifacts.require("MockValidation"); +const MockStorage = artifacts.require("MockStorage"); + +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('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 () => { + let chainId = await ion.chainId(); + + assert.equal(chainId, DEPLOYEDCHAINID); + }) + + describe('Register Validation', () => { + it('Successful registration', async () => { + // Successfully add id of another chain + let registered = await validation.register.call(); + await validation.register(); + + assert(registered); + }) + + it('Fail second registration', async () => { + // Successfully add id of another chain + let registered = await validation.register.call(); + await validation.register(); + + assert(registered); + + // Fail second attempt to register validation + validation.register.call().should.be.rejected; + }) + + it('Fail registration by non-contract', async () => { + ion.registerValidationModule().should.be.rejected; + }) + }) + + describe('Store Block', () => { + it('Successful Store Block', async () => { + await validation.register(); + + 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"); + }) + + it('Fail Store Block by unregistered validation', async () => { + validation.SubmitBlock(storage.address, TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; + }) + + it('Fail Store Block by non-contract', async () => { + ion.storeBlock(storage.address, TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; + }) + + it('Fail Store Block with non contract storage address', async () => { + ion.storeBlock(accounts[0], TESTCHAINID, TEST_UNSIGNED_HEADER, TEST_SIGNED_HEADER).should.be.rejected; + }) + }) +}) \ No newline at end of file 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/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/storage-ethereum.js b/test/storage-ethereum.js new file mode 100644 index 0000000..489d1cb --- /dev/null +++ b/test/storage-ethereum.js @@ -0,0 +1,408 @@ +// 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') +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 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)); - }); -}); diff --git a/truffle.js b/truffle.js index 2566b29..d4f5e8f 100644 --- a/truffle.js +++ b/truffle.js @@ -3,12 +3,13 @@ module.exports = { development: { host: "localhost", port: 8545, - network_id: "*" // Match any network id + gas: 0xFFFFFFFFFFF, + network_id: "*" }, - ci: { + clique: { host: "localhost", - port: 8545, - network_id: "*" // Match any network id + port: 8501, + network_id: "*" }, coverage: { host: "localhost", @@ -17,16 +18,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,