diff --git a/README.md b/README.md index e9bc2f1..239510f 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,23 @@

-## Intent +Codebase to provide ways for different incentive layers and computation layers to interface with a general purpose verification game. -The goal of this repository is to create a discussion around defining a dispute resolution layer protocol that is general enough to work with Truebit General (WASM) and Truebit Lite (scrypt-interactive) mechanisms. Other possibilities may be different types of verification games (Proof of Steak). - -The idea is that different types of incentive layers can plug in as well as different computation layers. Benefits of this approach are upgradeability and flexibility. In case there are bugs in the incentive layer or dispute resolution layer we could swap them out. The other benefit is flexibility to allow other projects to build with the Truebit system. - -The initial idea for this is that there currently exist two different implemented dispute resolution layers. - -Scrypt-Interactive (Doge-Eth Bridge): -https://github.com/TrueBitFoundation/scrypt-interactive/blob/master/contracts/Verifier.sol - -webasm-solidity (General Truebit): -https://github.com/TrueBitFoundation/webasm-solidity/blob/master/contracts/interactive2.sol +Go [here](https://github.com/TrueBitFoundation/Developer-Resources/blob/master/docs/DisputeResolutionLayer.md) for the Dispute Resolution Layer Overview. ## Installation +Ensure you have truffle and an Ethereum test net like ganache installed ``` npm install -g truffle ganache-cli ``` -## Test +Then install the package's dependencies +``` +npm install +``` + +## Testing After following the above installation instructions you can start up the dev blockchain in a separate tab: ``` diff --git a/contracts/BasicVerificationGame.sol b/contracts/BasicVerificationGame.sol index 8a44631..95cf510 100644 --- a/contracts/BasicVerificationGame.sol +++ b/contracts/BasicVerificationGame.sol @@ -48,7 +48,8 @@ contract BasicVerificationGame { game.lastParticipantTime = block.number; game.lowStep = 0; - game.lowHash = keccak256(0);//initial state hash + bytes32[3] memory initialState = [bytes32(0), bytes32(0), bytes32(0)]; + game.lowHash = game.vm.merklizeState(initialState); game.medStep = 0; game.medHash = bytes32(0); game.highStep = numSteps; @@ -59,6 +60,17 @@ contract BasicVerificationGame { NewGame(gameId, solver, verifier); } + function status(bytes32 gameId) public view returns (uint8) { + return uint8(games[gameId].state); + } + + function gameData(bytes32 gameId) public view returns (uint low, uint med, uint high) { + VerificationGame storage game = games[gameId]; + low = game.lowStep; + med = game.medStep; + high = game.highStep; + } + function query(bytes32 gameId, uint stepNumber) public { VerificationGame storage game = games[gameId]; @@ -148,18 +160,45 @@ contract BasicVerificationGame { } } - function merklizeProof(bytes32[] proof) public returns (bytes32 merkleRoot) { - for (uint i = 0; i < proof.length; i++) { - if (i == 0) - merkleRoot = proof[0]; - else - merkleRoot = keccak256(merkleRoot, proof[i]); + //https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol + function checkProofOrdered(bytes proof, bytes32 root, bytes32 hash, uint256 index) public pure returns (bool) { + // use the index to determine the node ordering + // index ranges 1 to n + + bytes32 el; + bytes32 h = hash; + uint256 remaining; + + for (uint256 j = 32; j <= proof.length; j += 32) { + assembly { + el := mload(add(proof, j)) + } + + // calculate remaining elements in proof + remaining = (proof.length - j + 32) / 32; + + // we don't assume that the tree is padded to a power of 2 + // if the index is odd then the proof will start with a hash at a higher + // layer, so we have to adjust the index to be the index at that layer + while (remaining > 0 && index % 2 == 1 && index > 2 ** remaining) { + index = uint(index) / 2 + 1; + } + if (index % 2 == 0) { + h = keccak256(el, h); + index = index / 2; + } else { + h = keccak256(h, el); + index = uint(index) / 2 + 1; + } } + + return h == root; } + //Should probably replace preValue and postValue with preInstruction and postInstruction - function performStepVerification(bytes32 gameId, bytes32[4] preStepState, bytes32[4] postStepState, bytes32[] proof) public { + function performStepVerification(bytes32 gameId, bytes32[3] lowStepState, bytes32[3] highStepState, bytes proof) public { VerificationGame storage game = games[gameId]; require(game.state == State.Unresolved); @@ -168,20 +207,13 @@ contract BasicVerificationGame { require(game.lowStep + 1 == game.highStep); // ^ must be at the end of the binary search according to the smart contract - require(game.vm.merklizeState(preStepState) == game.lowHash); - require(game.vm.merklizeState(postStepState) == game.highHash); + require(game.vm.merklizeState(lowStepState) == game.lowHash); + require(game.vm.merklizeState(highStepState) == game.highHash); //require that the next instruction be included in the program merkle root - require(game.programMerkleRoot == merklizeProof(proof)); + require(checkProofOrdered(proof, game.programMerkleRoot, keccak256(highStepState[0]), game.highStep)); - uint currentStep = uint(preStepState[3]); - - bytes32[4] memory newState; - if (currentStep % 2 == 0) { - newState = game.vm.runStep(preStepState, proof[0]);//pass in next instruction - } else { - newState = game.vm.runStep(preStepState, proof[1]); - } + bytes32[3] memory newState = game.vm.runStep(lowStepState, game.highStep, highStepState[0]); if (game.vm.merklizeState(newState) == game.highHash) { game.state = State.SolverWon; @@ -190,15 +222,4 @@ contract BasicVerificationGame { } //FinalData(stepOutput, keccak256(stepOutput)); } - - function status(bytes32 gameId) public view returns (uint8) { - return uint8(games[gameId].state); - } - - function gameData(bytes32 gameId) public view returns (bytes32 lowHash, bytes32 medHash, bytes32 highHash) { - VerificationGame storage game = games[gameId]; - lowHash = game.lowHash; - medHash = game.medHash; - highHash = game.highHash; - } } \ No newline at end of file diff --git a/contracts/IComputationLayer.sol b/contracts/IComputationLayer.sol index 22c3d1c..2eac71f 100644 --- a/contracts/IComputationLayer.sol +++ b/contracts/IComputationLayer.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.18; interface IComputationLayer { - function runStep(bytes32[4] currentState, bytes32 nextInput) public pure returns (bytes32[4] newState); - function merklizeState(bytes32[4] state) public pure returns (bytes32 merkleRoot); + function runStep(bytes32[3] currentState, uint stepNumber, bytes32 nextInput) public pure returns (bytes32[3] newState); + function merklizeState(bytes32[3] state) public pure returns (bytes32 merkleRoot); } \ No newline at end of file diff --git a/contracts/IDisputeResolutionLayer.sol b/contracts/IDisputeResolutionLayer.sol index 8de309b..5af8139 100644 --- a/contracts/IDisputeResolutionLayer.sol +++ b/contracts/IDisputeResolutionLayer.sol @@ -1,5 +1,6 @@ pragma solidity ^0.4.18; +//TODO: Should maybe enforce checkProofOrdered interface IDisputeResolutionLayer { function status(bytes32 id) public returns (uint8); //returns State enum } \ No newline at end of file diff --git a/contracts/test/SimpleAdderVM.sol b/contracts/test/SimpleAdderVM.sol index c4916f1..cca7aaa 100644 --- a/contracts/test/SimpleAdderVM.sol +++ b/contracts/test/SimpleAdderVM.sol @@ -8,20 +8,22 @@ contract SimpleAdderVM { //Reg1: Stack1 Accum //Reg2: Stack2 Result //Reg3: StepCounter - function runStep(bytes32[4] currentState, bytes32 nextInput) public pure returns (bytes32[4] newState) { + function runStep(bytes32[3] currentState, uint stepNumber, bytes32 nextInput) public pure returns (bytes32[3] newState) { - newState[0] = nextInput;//Copy input - newState[1] = currentState[2];//Copy last result as new accum + require(currentState[2] == bytes32(stepNumber-1)); - //Use Stack0 and Stack1 registers to compute result - bytes32 sum = bytes32(uint(newState[0]) + uint(currentState[1]));//Add input by the previous state's accum - newState[2] = sum;//Store result in Stack2 register - - newState[3] = bytes32(uint(currentState[3]) + 1);//Increment step counter + if (stepNumber == 0) { + require(currentState[0] == 0x0 && currentState[1] == 0x0 && currentState[2] == 0x0); + return currentState; + } else { + newState[0] = nextInput; + newState[1] = bytes32(uint(currentState[1]) + uint(nextInput)); + newState[2] = bytes32(stepNumber); + } } //Simple list merklization (works like sum) - function merklizeState(bytes32[4] state) public pure returns (bytes32 merkleRoot) { + function merklizeState(bytes32[3] state) public pure returns (bytes32 merkleRoot) { for (uint i = 0; i < state.length; i++) { if (i == 0) { merkleRoot = state[0]; @@ -33,16 +35,18 @@ contract SimpleAdderVM { //Used for generating results for query/response //Run offchain - function runSteps(uint[] program, uint numSteps) public pure returns (bytes32[4] state, bytes32 stateHash) { + function runSteps(bytes32[] program, uint numSteps) public pure returns (bytes32[3] state, bytes32 stateHash) { uint i = 0; - while (i < program.length && i <= numSteps-1) { - bytes32 nextInstruction = bytes32(program[uint(state[3])]); - state = runStep(state, nextInstruction); - i+=1; + while (i < program.length && i <= numSteps) { + if (i > 0) { + bytes32 nextInstruction = program[i-1]; + state = runStep(state, i, nextInstruction); + } + i += 1; } stateHash = merklizeState(state); } - + } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d938127..1f62163 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "requires": { + "xtend": "4.0.1" + } + }, "accepts": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", @@ -13,6 +21,11 @@ "negotiator": "0.6.1" } }, + "aes-js": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-0.2.4.tgz", + "integrity": "sha1-lLiBq3FyhtAV+iGeCPtmcJ3aWj0=" + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -24,6 +37,11 @@ "json-schema-traverse": "0.3.1" } }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -54,6 +72,29 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "requires": { + "async": "2.6.0" + }, + "dependencies": { + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.5" + } + } + } + }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -79,6 +120,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "base-x": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-1.1.0.tgz", + "integrity": "sha1-QtPXF0dPnqAiB/bRqh9CaRPut6w=" + }, "base64-js": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", @@ -93,6 +139,36 @@ "tweetnacl": "0.14.5" } }, + "bignumber.js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.4.0.tgz", + "integrity": "sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg=" + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip39": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", + "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", + "requires": { + "create-hash": "1.1.3", + "pbkdf2": "3.0.14", + "randombytes": "2.0.6", + "safe-buffer": "5.1.1", + "unorm": "1.4.1" + } + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "5.1.1" + } + }, "bl": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", @@ -222,6 +298,23 @@ "parse-asn1": "5.1.0" } }, + "bs58": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-3.1.0.tgz", + "integrity": "sha1-1MJjiL9IBMrHFBQbGUWqR+XrJI4=", + "requires": { + "base-x": "1.1.0" + } + }, + "bs58check": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-1.3.4.tgz", + "integrity": "sha1-xSVABzdJEXcU+gQsMEfrj5FRy/g=", + "requires": { + "bs58": "3.1.0", + "create-hash": "1.1.3" + } + }, "buffer": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz", @@ -246,16 +339,34 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "checkpoint-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", + "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", + "requires": { + "functional-red-black-tree": "1.0.1" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -265,11 +376,47 @@ "safe-buffer": "5.1.1" } }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "coinstring": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/coinstring/-/coinstring-2.3.0.tgz", + "integrity": "sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q=", + "requires": { + "bs58": "2.0.1", + "create-hash": "1.1.3" + }, + "dependencies": { + "bs58": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.1.tgz", + "integrity": "sha1-VZCNWPGYKrogCPob7Y+RmYopv40=" + } + } + }, "combined-stream": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", @@ -394,6 +541,11 @@ "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=" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -410,6 +562,11 @@ "ms": "2.0.0" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -504,6 +661,40 @@ } } }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "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-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + }, + "dependencies": { + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -543,6 +734,16 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6" + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -581,6 +782,14 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -589,6 +798,57 @@ "once": "1.4.0" } }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es-abstract": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz", + "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==", + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "4.2.4" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -613,6 +873,384 @@ "xhr-request-promise": "0.1.2" } }, + "ether-pudding": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ether-pudding/-/ether-pudding-3.2.0.tgz", + "integrity": "sha1-0fncBOBSJTDY93GhAk/l7BfYxQ0=", + "requires": { + "async": "1.5.2", + "ethereumjs-testrpc": "2.2.7", + "lodash": "4.17.5", + "node-dir": "0.1.17", + "solc": "0.3.6", + "web3": "0.15.3" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9" + }, + "solc": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.3.6.tgz", + "integrity": "sha1-7hZ44URwH7wWNe+yEhPHlTzyu6k=", + "requires": { + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "yargs": "4.8.1" + } + }, + "web3": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.15.3.tgz", + "integrity": "sha1-+ZfM2kGfxSjA1sXY1TgiEr+nRig=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9", + "crypto-js": "3.1.8", + "utf8": "2.1.1", + "xmlhttprequest": "1.8.0" + } + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + } + } + }, + "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-account": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.4.tgz", + "integrity": "sha1-+MMCMby3B/RRTYoFLB+doQNiTUc=", + "requires": { + "ethereumjs-util": "4.5.0", + "rlp": "2.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "keccakjs": "0.2.1", + "rlp": "2.0.0", + "secp256k1": "3.5.0" + } + } + } + }, + "ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "requires": { + "async": "2.6.0", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.1.5", + "merkle-patricia-tree": "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==", + "requires": { + "lodash": "4.17.5" + } + } + } + }, + "ethereumjs-testrpc": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/ethereumjs-testrpc/-/ethereumjs-testrpc-2.2.7.tgz", + "integrity": "sha1-/3Mv79s6GJ6C1fCbmZRr/xgUAiQ=", + "requires": { + "async": "1.5.2", + "bignumber.js": "2.4.0", + "bip39": "2.5.0", + "ethereumjs-account": "2.0.4", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "4.5.0", + "ethereumjs-vm": "1.4.1", + "ethereumjs-wallet": "0.6.0", + "fake-merkle-patricia-tree": "1.0.1", + "merkle-patricia-tree": "2.3.1", + "seedrandom": "2.4.3", + "shelljs": "0.6.1", + "web3": "0.16.0", + "web3-provider-engine": "8.6.1", + "yargs": "3.32.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "keccakjs": "0.2.1", + "rlp": "2.0.0", + "secp256k1": "3.5.0" + } + }, + "web3": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.16.0.tgz", + "integrity": "sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9", + "crypto-js": "3.1.8", + "utf8": "2.1.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9" + } + } + } + } + }, + "ethereumjs-tx": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.4.tgz", + "integrity": "sha512-kOgUd5jC+0tgV7t52UDECMMz9Uf+Lro+6fSpCvzWemtXfMEcwI3EOxf5mVPMRbTFkMMhuERokNNVF3jItAjidg==", + "requires": { + "ethereum-common": "0.0.18", + "ethereumjs-util": "5.1.5" + }, + "dependencies": { + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + } + } + }, + "ethereumjs-util": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz", + "integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "ethjs-util": "0.1.4", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.1", + "secp256k1": "3.5.0" + } + }, + "ethereumjs-vm": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-1.4.1.tgz", + "integrity": "sha1-qMOjORfGLXYd4ZUAI5HWym0DjAk=", + "requires": { + "async": "1.5.2", + "async-eventemitter": "0.2.4", + "ethereum-common": "0.0.16", + "ethereumjs-account": "2.0.4", + "ethereumjs-block": "1.7.1", + "ethereumjs-util": "4.5.0", + "fake-merkle-patricia-tree": "1.0.1", + "functional-red-black-tree": "1.0.1", + "merkle-patricia-tree": "2.3.1" + }, + "dependencies": { + "ethereum-common": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.16.tgz", + "integrity": "sha1-mh4Wnq00q3XgifUMpRK/0PvRJlU=" + }, + "ethereumjs-util": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "keccakjs": "0.2.1", + "rlp": "2.0.0", + "secp256k1": "3.5.0" + } + } + } + }, + "ethereumjs-wallet": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz", + "integrity": "sha1-gnY7Fpfuenlr5xVdqd+0my+Yz9s=", + "requires": { + "aes-js": "0.2.4", + "bs58check": "1.3.4", + "ethereumjs-util": "4.5.0", + "hdkey": "0.7.1", + "scrypt.js": "0.2.0", + "utf8": "2.1.1", + "uuid": "2.0.3" + }, + "dependencies": { + "ethereumjs-util": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "keccakjs": "0.2.1", + "rlp": "2.0.0", + "secp256k1": "3.5.0" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" + } + } + }, + "ethjs-abi": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethjs-abi/-/ethjs-abi-0.2.0.tgz", + "integrity": "sha1-0+LCIQEVIPxJm3FoIDbBT8wvWyU=", + "requires": { + "bn.js": "4.11.6", + "js-sha3": "0.5.5", + "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=" + }, + "js-sha3": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" + } + } + }, + "ethjs-contract": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/ethjs-contract/-/ethjs-contract-0.1.9.tgz", + "integrity": "sha1-HCdmiWpW1H7B1tZhgpxJzDilUgo=", + "requires": { + "ethjs-abi": "0.2.0", + "ethjs-filter": "0.1.5", + "ethjs-util": "0.1.3", + "js-sha3": "0.5.5" + }, + "dependencies": { + "ethjs-util": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.3.tgz", + "integrity": "sha1-39XqSkANxeQhqInK9H4IGtp4u1U=", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "js-sha3": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" + } + } + }, + "ethjs-filter": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/ethjs-filter/-/ethjs-filter-0.1.5.tgz", + "integrity": "sha1-ARKvYBfCRnfjK4/esg5hlgGbdZg=" + }, + "ethjs-format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ethjs-format/-/ethjs-format-0.2.2.tgz", + "integrity": "sha1-1zs6YFwuElcHn3B3/VRI6ZjOD80=", + "requires": { + "bn.js": "4.11.6", + "ethjs-schema": "0.1.5", + "ethjs-util": "0.1.3", + "is-hex-prefixed": "1.0.0", + "number-to-bn": "1.7.0", + "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=" + }, + "ethjs-util": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.3.tgz", + "integrity": "sha1-39XqSkANxeQhqInK9H4IGtp4u1U=", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + } + } + }, + "ethjs-provider-http": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-provider-http/-/ethjs-provider-http-0.1.6.tgz", + "integrity": "sha1-HsXZtL4lfvHValALIqdBmF6IlCA=", + "requires": { + "xhr2": "0.1.3" + }, + "dependencies": { + "xhr2": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.3.tgz", + "integrity": "sha1-y/xHWaabSoiOeM9PILBRA4dXvRE=" + } + } + }, + "ethjs-query": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/ethjs-query/-/ethjs-query-0.2.9.tgz", + "integrity": "sha1-om5rTzhpnpLzSyGE51x4lDKcQvE=", + "requires": { + "ethjs-format": "0.2.2", + "ethjs-rpc": "0.1.5" + } + }, + "ethjs-rpc": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/ethjs-rpc/-/ethjs-rpc-0.1.5.tgz", + "integrity": "sha1-CZ4i8n3EwYtpeKSF/DaxsPeWkIA=" + }, + "ethjs-schema": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/ethjs-schema/-/ethjs-schema-0.1.5.tgz", + "integrity": "sha1-WXQOOzl3vNu5sRvDBoIB6Kzquw0=" + }, "ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -629,6 +1267,15 @@ } } }, + "ethjs-util": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.4.tgz", + "integrity": "sha1-HItoeSV0RO9NPz+7rC3tEs2ZfZM=", + "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", @@ -702,6 +1349,14 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, + "fake-merkle-patricia-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", + "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", + "requires": { + "checkpoint-store": "1.1.0" + } + }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", @@ -746,6 +1401,15 @@ } } }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, "for-each": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", @@ -754,6 +1418,11 @@ "is-function": "1.0.1" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -815,6 +1484,21 @@ "rimraf": "2.6.2" } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "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=" + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -895,6 +1579,14 @@ "har-schema": "2.0.0" } }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, "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", @@ -936,6 +1628,15 @@ "sntp": "2.1.0" } }, + "hdkey": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.7.1.tgz", + "integrity": "sha1-yu5L6BqneSHpCbjSKN0PKayu5jI=", + "requires": { + "coinstring": "2.3.0", + "secp256k1": "3.5.0" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -951,6 +1652,11 @@ "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, + "hosted-git-info": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" + }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", @@ -994,6 +1700,11 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1008,11 +1719,47 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, "ipaddr.js": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, "is-function": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", @@ -1038,6 +1785,14 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.1" + } + }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -1048,16 +1803,35 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "1.7.3", + "whatwg-fetch": "2.0.3" + } + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -1117,6 +1891,17 @@ "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.9.2", + "safe-buffer": "5.1.1" + } + }, "keccakjs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", @@ -1126,11 +1911,160 @@ "sha3": "1.2.0" } }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "left-pad": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.2.0.tgz", + "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=" + }, + "level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + }, + "level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "requires": { + "inherits": "2.0.3", + "level-errors": "1.0.5", + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "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" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" }, + "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", @@ -1171,11 +2105,86 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "requires": { + "abstract-leveldown": "2.7.2", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + } + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, + "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.1.5", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.4", + "rlp": "2.0.0", + "semaphore": "1.1.0" + } + }, + "merkle-tree-solidity": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/merkle-tree-solidity/-/merkle-tree-solidity-1.0.8.tgz", + "integrity": "sha1-xNx72tAycMoWxyytyLDmFt/Dp3o=", + "requires": { + "es6-promisify": "5.0.0", + "ether-pudding": "3.2.0", + "ethereumjs-util": "5.1.5", + "ethjs-contract": "0.1.9", + "ethjs-provider-http": "0.1.6", + "ethjs-query": "0.2.9", + "left-pad": "1.2.0", + "solc": "0.4.21", + "web3": "0.17.0-beta" + }, + "dependencies": { + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + }, + "web3": { + "version": "0.17.0-beta", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.17.0-beta.tgz", + "integrity": "sha1-V684JFv/ejIJn3zleA+tW7wA2ls=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "crypto-js": "3.1.8", + "utf8": "2.1.1", + "xmlhttprequest": "1.8.0" + } + } + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -1300,6 +2309,39 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, + "node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=", + "requires": { + "minimatch": "3.0.4" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.3" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, "number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -1326,6 +2368,16 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-inspect": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.5.0.tgz", + "integrity": "sha512-UmOFbHbwvv+XHj7BerrhVq+knjceBdkvU5AriwLMvhv2qi+e7DJzxfBeFpILEjVzCp+xA+W/pIf06RGPWlZNfw==" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, "oboe": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", @@ -1350,6 +2402,14 @@ "wrappy": "1.0.2" } }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", @@ -1389,21 +2449,52 @@ "trim": "0.0.1" } }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.1" + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, "pbkdf2": { "version": "3.0.14", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", @@ -1468,6 +2559,11 @@ "ipaddr.js": "1.6.0" } }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, "public-encrypt": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", @@ -1538,6 +2634,25 @@ "unpipe": "1.0.0" } }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, "readable-stream": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", @@ -1581,6 +2696,37 @@ "uuid": "3.2.1" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "2.3.8" + } + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -1598,6 +2744,16 @@ "inherits": "2.0.3" } }, + "rlp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.0.0.tgz", + "integrity": "sha1-nbOE/0uJqPYVY9kjldhiWxjzr7A=" + }, + "rustbn.js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.1.2.tgz", + "integrity": "sha512-bAkNqSHYdJdFsBC7Z11JgzYktL31HIpB2o70jZcGiL1U1TVtPyvaVhDrGWwS8uZtaqwW2k6NOPGZCqW/Dgh5Lg==" + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -1628,6 +2784,26 @@ "pbkdf2": "3.0.14" } }, + "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.1.3", + "drbg.js": "1.0.1", + "elliptic": "6.4.0", + "nan": "2.9.2", + "safe-buffer": "5.1.1" + } + }, + "seedrandom": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz", + "integrity": "sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw=" + }, "seek-bzip": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", @@ -1636,6 +2812,16 @@ "commander": "2.8.1" } }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, "send": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", @@ -1686,6 +2872,11 @@ "xhr": "2.4.1" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -1713,6 +2904,11 @@ "nan": "2.9.2" } }, + "shelljs": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", + "integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=" + }, "simple-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", @@ -1736,6 +2932,81 @@ "hoek": "4.2.1" } }, + "solc": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.21.tgz", + "integrity": "sha512-8lJmimVjOG9AJOQRWS2ph4rSctPMsPGZ4H360HLs5iI+euUlt7iAvUxSLeFZZzwk0kas4Qta7HmlMXNU3yYwhw==", + "requires": { + "fs-extra": "0.30.0", + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "semver": "5.4.1", + "yargs": "4.8.1" + }, + "dependencies": { + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + } + } + }, + "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==" + }, "sshpk": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", @@ -1761,6 +3032,26 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.11.0", + "function-bind": "1.1.1" + } + }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", @@ -1774,6 +3065,22 @@ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, "strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -1810,6 +3117,33 @@ "xhr-request-promise": "0.1.2" } }, + "tape": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.0.tgz", + "integrity": "sha512-j0jO9BiScfqtPBb9QmPLL0qvxXMz98xjkMb7x8lKipFlJZwNJkqkWPou+NU4V6T9RnVh1kuSthLE8gLrN8bBfw==", + "requires": { + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.2", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.5.0", + "resolve": "1.5.0", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "tar": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", @@ -1956,6 +3290,11 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" }, + "unorm": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.4.1.tgz", + "integrity": "sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA=" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1999,6 +3338,15 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2231,6 +3579,69 @@ "web3-utils": "1.0.0-beta.30" } }, + "web3-provider-engine": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz", + "integrity": "sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs=", + "requires": { + "async": "2.6.0", + "clone": "2.1.2", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.1.5", + "ethereumjs-vm": "2.3.3", + "isomorphic-fetch": "2.2.1", + "request": "2.83.0", + "semaphore": "1.1.0", + "solc": "0.4.21", + "tape": "4.9.0", + "web3": "0.16.0", + "xhr": "2.4.1", + "xtend": "4.0.1" + }, + "dependencies": { + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.5" + } + }, + "bignumber.js": { + "version": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9" + }, + "ethereumjs-vm": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.3.tgz", + "integrity": "sha512-yIWJqTEcrF9vJTCvNMxacRkAx6zIZTOW0SmSA+hSFiU1x8JyVZDi9o5udwsRVECT5RkPgQzm62kpL6Pf4qemsw==", + "requires": { + "async": "2.6.0", + "async-eventemitter": "0.2.4", + "ethereum-common": "0.2.0", + "ethereumjs-account": "2.0.4", + "ethereumjs-block": "1.7.1", + "ethereumjs-util": "5.1.5", + "fake-merkle-patricia-tree": "1.0.1", + "functional-red-black-tree": "1.0.1", + "merkle-patricia-tree": "2.3.1", + "rustbn.js": "0.1.2", + "safe-buffer": "5.1.1" + } + }, + "web3": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.16.0.tgz", + "integrity": "sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk=", + "requires": { + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9", + "crypto-js": "3.1.8", + "utf8": "2.1.1", + "xmlhttprequest": "1.8.0" + } + } + } + }, "web3-providers-http": { "version": "1.0.0-beta.30", "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.30.tgz", @@ -2301,6 +3712,30 @@ "yaeti": "0.0.6" } }, + "whatwg-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", + "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2354,16 +3789,61 @@ "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, "yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + } + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + }, "yauzl": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", diff --git a/test/basic_verification_game.js b/test/basic_verification_game.js index 197d68e..90b5da0 100644 --- a/test/basic_verification_game.js +++ b/test/basic_verification_game.js @@ -1,6 +1,8 @@ const BasicVerificationGame = artifacts.require("./BasicVerificationGame.sol") const SimpleAdderVM = artifacts.require("./test/SimpleAdderVM.sol") const web3 = require('web3') +const merkleTree = require('./helpers/merkleTree') +const sha3 = require('ethereumjs-util').sha3 const toResult = (data) => { return { @@ -24,19 +26,26 @@ contract('BasicVerificationGame query to high step', function(accounts) { "0x0000000000000000000000000000000000000000000000000000000000000009" ] - let programLength = program.length - 1 + let programLength = program.length let output = 45 - let step = programLength - 1 + let step = 1 let responseTime = 20 + let checkProofOrderedSolidity + let mtree + let hashes = program.map(e => sha3(e)) + let root before(async () => { basicVerificationGame = await BasicVerificationGame.deployed() simpleAdderVM = await SimpleAdderVM.deployed() + checkProofOrderedSolidity = merkleTree.checkProofOrderedSolidityFactory(basicVerificationGame.checkProofOrdered) + // Set flag to true to be ordered + mtree = new merkleTree.MerkleTree(hashes, true) + root = mtree.getRoot() }) it("should create a new verification game", async () => { - let programMerkleRoot = await basicVerificationGame.merklizeProof.call(program) - let tx = await basicVerificationGame.newGame(accounts[1], accounts[2], programMerkleRoot, web3.utils.soliditySha3(output), programLength, responseTime, SimpleAdderVM.address) + let tx = await basicVerificationGame.newGame(accounts[1], accounts[2], merkleTree.bufToHex(root), web3.utils.soliditySha3(output), programLength, responseTime, SimpleAdderVM.address) const result = tx.logs[0].args gameId = result.gameId assert.equal(result.solver, accounts[1]) @@ -62,28 +71,28 @@ contract('BasicVerificationGame query to high step', function(accounts) { assert.equal(response.gameId, gameId) }) - //This needs to be fixed as it is rather awkward.... - it("should query a step again...", async () => { + it("should query next step down", async () => { //query final step to make verification game short - let tx = await basicVerificationGame.query(gameId, step, {from: accounts[2]}) + let tx = await basicVerificationGame.query(gameId, step-1, {from: accounts[2]}) let query = tx.logs[0].args - assert.equal(query.stepNumber.toNumber(), step) + assert.equal(query.stepNumber.toNumber(), step-1) assert.equal(query.gameId, gameId) }) it("should perform step verification", async () => { - let preStep = toResult(await simpleAdderVM.runSteps.call(program, step)) - let postStep = await simpleAdderVM.runStep.call(preStep.state, program[step+1]) + let lowStepState = toResult(await simpleAdderVM.runSteps.call(program, step-1)).state - let merkleProof = [ - await basicVerificationGame.merklizeProof.call(program.slice(0, -1)), - "0x0000000000000000000000000000000000000000000000000000000000000009" - ] + let highStep = step + let highStepIndex = step-1 + let highStepState = await simpleAdderVM.runStep.call(lowStepState, highStep, program[highStepIndex]) - tx = await basicVerificationGame.performStepVerification(gameId, preStep.state, postStep, merkleProof, {from: accounts[1]}) - //assert.equal(1, (await basicVerificationGame.status.call(gameId)).toNumber()) - }) -}) + let proof = mtree.getProofOrdered(hashes[highStepIndex], highStep) + const newProof = '0x' + proof.map(e => e.toString('hex')).join('') -//TODO: Make test where game queries to low step \ No newline at end of file + assert(await checkProofOrderedSolidity(proof, root, hashes[highStepIndex], highStep)) + + tx = await basicVerificationGame.performStepVerification(gameId, lowStepState, highStepState, newProof, {from: accounts[1]}) + assert.equal(1, (await basicVerificationGame.status.call(gameId)).toNumber()) + }) +}) \ No newline at end of file diff --git a/test/helpers/merkleTree.js b/test/helpers/merkleTree.js new file mode 100644 index 0000000..55446cf --- /dev/null +++ b/test/helpers/merkleTree.js @@ -0,0 +1,207 @@ +//https://github.com/ameensol/merkle-tree-solidity/blob/master/js/merkle.js + +// https://github.com/raiden-network/raiden/blob/master/raiden/mtree.py +// Create a merkle root from a list of elements +// Elements are assumed to be 32 bytes hashes (Buffers) +// (but may be expressed as 0x prefixed hex strings of length 66) +// The bottom layer of the tree (leaf nodes) are the elements +// All layers above are combined hashes of the element pairs + +// Two strategies for creating tree and checking proofs (preserveOrder flag) +// 1. raiden - sort the leaves of the tree, and also sort each pair of +// pre-images, which allows you to verify the proof without the index +// 2. storj - preserve the order of the leaves and pairs of pre-images, and use +// the index to verify the proof + +// The MerkleTree is a 2d array of layers +// [ elements, combinedHashes1, combinedHashes2, ... root] +// root is a length 1 array + +const sha3 = require('ethereumjs-util').sha3 + +// Expects elements to be Buffers of length 32 +// Empty string elements will be removed prior to the buffer check +// by default, order is not preserved +function MerkleTree(elements, preserveOrder) { + if (!(this instanceof MerkleTree)) { + return new MerkleTree(elements, preserveOrder) + } + + // remove empty strings + this.elements = elements.filter(a => a) + + // check buffers + if (this.elements.some((e) => !(e.length == 32 && Buffer.isBuffer(e)))) { + throw new Error('elements must be 32 byte buffers') + } + + // if we are not preserving order, dedup and sort + this.preserveOrder = !!preserveOrder + if (!this.preserveOrder) { + this.elements = bufDedup(this.elements) + this.elements.sort(Buffer.compare) + } + + this.layers = getLayers(this.elements, this.preserveOrder) +} + +MerkleTree.prototype.getRoot = function() { + return this.layers[this.layers.length - 1][0] +} + +MerkleTree.prototype.getProof = function(element, hex) { + const index = getBufIndex(element, this.elements) + if (index == -1) { + throw new Error('element not found in merkle tree') + } + return getProof(index, this.layers, hex) +} + +// Expects 1-n index, converts it to 0-n index internally +MerkleTree.prototype.getProofOrdered = function(element, index, hex) { + if (!(element.equals(this.elements[index - 1]))) { + throw new Error('element does not match leaf at index in tree') + } + return getProof(index - 1, this.layers, hex) +} + +const checkProofOrdered = function(proof, root, element, index) { + // use the index to determine the node ordering + // index ranges 1 to n + + let tempHash = element + + for (let i = 0; i < proof.length; i++) { + let remaining = proof.length - i + + // we don't assume that the tree is padded to a power of 2 + // if the index is odd then the proof will start with a hash at a higher + // layer, so we have to adjust the index to be the index at that layer + while (remaining && index % 2 === 1 && index > Math.pow(2, remaining)) { + index = Math.round(index / 2) + } + + if (index % 2 === 0) { + tempHash = combinedHash(proof[i], tempHash, true) + } else { + tempHash = combinedHash(tempHash, proof[i], true) + } + index = Math.round(index / 2) + } + + return tempHash.equals(root) +} + +const checkProof = function(proof, root, element) { + return root.equals(proof.reduce((hash, pair) => { + return combinedHash(hash, pair) + }, element)) +} + +const merkleRoot = function(elements, preserveOrder) { + return (new MerkleTree(elements, preserveOrder)).getRoot() +} + +// converts buffers from MerkleRoot functions into hex strings +// merkleProof is the contract abstraction for MerkleProof.sol +const checkProofSolidityFactory = function(checkProofContractMethod) { + return function(proof, root, hash) { + proof = '0x' + proof.map(e => e.toString('hex')).join('') + root = bufToHex(root) + hash = bufToHex(hash) + return checkProofContractMethod(proof, root, hash) + } +} + +const checkProofOrderedSolidityFactory = function(checkProofOrderedContractMethod) { + return function(proof, root, hash, index) { + proof = '0x' + proof.map(e => e.toString('hex')).join('') + root = bufToHex(root) + hash = bufToHex(hash) + return checkProofOrderedContractMethod(proof, root, hash, index) + } +} + +module.exports = { + MerkleTree: MerkleTree, + checkProofOrdered: checkProofOrdered, + checkProofOrderedSolidityFactory: checkProofOrderedSolidityFactory, + bufToHex: bufToHex +} + +function combinedHash(first, second, preserveOrder) { + if (!second) { return first } + if (!first) { return second } + if (preserveOrder) { + return sha3(bufJoin(first, second)) + } else { + return sha3(bufSortJoin(first, second)) + } +} + +function getNextLayer(elements, preserveOrder) { + return elements.reduce((layer, element, index, arr) => { + if (index % 2 == 0) { layer.push(combinedHash(element, arr[index + 1], preserveOrder)) } + return layer + }, []) +} + +function getLayers(elements, preserveOrder) { + if (elements.length == 0) { + return [['']] + } + const layers = [] + layers.push(elements) + while (layers[layers.length - 1].length > 1) { + layers.push(getNextLayer(layers[layers.length - 1], preserveOrder)) + } + return layers +} + +function getProof(index, layers, hex) { + const proof = layers.reduce((proof, layer) => { + let pair = getPair(index, layer) + if (pair) { proof.push(pair) } + index = Math.floor(index / 2) + return proof + }, []) + if (hex) { + return '0x' + proof.map(e => e.toString('hex')).join('') + } else { + return proof + } +} + +function getPair(index, layer) { + let pairIndex = index % 2 ? index - 1 : index + 1 + if (pairIndex < layer.length) { + return layer[pairIndex] + } else { + return null + } +} + +function getBufIndex(element, array) { + for (let i = 0; i < array.length; i++) { + if (element.equals(array[i])) { return i } + } + return -1 +} + +function bufToHex(element) { + return Buffer.isBuffer(element) ? '0x' + element.toString('hex') : element +} + +function bufJoin(...args) { + return Buffer.concat([...args]) +} + +function bufSortJoin(...args) { + return Buffer.concat([...args].sort(Buffer.compare)) +} + +function bufDedup(buffers) { + return buffers.filter((buffer, i) => { + return getBufIndex(buffer, buffers) == i + }) +} \ No newline at end of file diff --git a/test/merkle_proofs.js b/test/merkle_proofs.js new file mode 100644 index 0000000..f8c71cd --- /dev/null +++ b/test/merkle_proofs.js @@ -0,0 +1,44 @@ +const BasicVerificationGame = artifacts.require("./BasicVerificationGame.sol") +const web3 = require('web3') +const merkleTree = require('./helpers/merkleTree') +const sha3 = require('ethereumjs-util').sha3 + +contract('Simple test environment for generating merkle trees', function(accounts) { + let basicVerificationGame, gameId + + let program = [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000009" + ] + + let programLength = program.length - 1 + let output = 45 + let step = programLength - 1 + let responseTime = 20 + let checkProofOrderedSolidity + let mtree + let hashes = program.map(e => sha3(e)) + + before(async () => { + basicVerificationGame = await BasicVerificationGame.deployed() + checkProofOrderedSolidity = merkleTree.checkProofOrderedSolidityFactory(basicVerificationGame.checkProofOrdered) + // Set flag to true to be ordered + mtree = new merkleTree.MerkleTree(hashes, true) + }) + + it("should check merkle proof", async () => { + const root = mtree.getRoot() + const index = 0 + const proof = mtree.getProofOrdered(hashes[index], 1-index) + + assert(await checkProofOrderedSolidity(proof, root, hashes[index], 1-index)) + }) + +}) \ No newline at end of file