diff --git a/unittests/README.md b/unittests/README.md new file mode 100644 index 0000000..4b2b48a --- /dev/null +++ b/unittests/README.md @@ -0,0 +1,5 @@ +To run the tests: + 1. `npm install` to get Node.js dependencies + 2. `./start_conflux.sh` in a separate terminal, and start Ganache (for Ethereum tests) + - Be sure to clone the `conflux-rust` repo, and within `start_conflux.sh`, set `conflux` to the location of your repo clone. + 3. `./run_unittests.sh` diff --git a/unittests/address_test.js b/unittests/address_test.js deleted file mode 100755 index 2ec699f..0000000 --- a/unittests/address_test.js +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env node - -// const net = require('net'); -// const solc = require('solc'); - -const bytecodeFilename = "address.bytecode"; -const abiFilename = "address.abi"; - -const fs = require('fs'); -const ethers = require("ethers"); - -const endpoint = "http://localhost:8545"; -const provider = new ethers.providers.JsonRpcProvider(endpoint); - -const bytecode = fs.readFileSync(bytecodeFilename).toString().replace(/\n|\t|\r| /g, ""); -const abi = JSON.parse(fs.readFileSync(abiFilename).toString()); -const signer = provider.getSigner(0); -const creator = signer.getAddress(); - -function printTest(name, success) { - console.log(name +": " + (success? "pass✅" : "fail❌")); -} - -async function deploy() { - //console.log("sending creation transaction...") - let factory = new ethers.ContractFactory(abi, bytecode, signer); - let contract = await factory.deploy(); - await contract.deployed(); - // console.log("contract address: " + contract.address); - // console.log("transaction hash: " + contract.deployTransaction.hash); - // let deployedBytecode = await provider.getCode(contract.address); - // console.log("deployed bytecode: " + deployedBytecode); - - await contract.init(); - - let getval = await contract.get(); - printTest("init value: ", getval == "0x000000000000000000000000000000000000efca"); - //console.log(getval); - - let setv = "0xd115bffabbdd893a6f7cea402e7338643ced44a6"; // 160-bit address format - await contract.set(setv); - - getval = await contract.get(); - printTest("set value: ", getval == ethers.utils.getAddress(setv)); - //console.log(getval); -} - -deploy(); diff --git a/unittests/asserts_test.js b/unittests/asserts_test.js deleted file mode 100755 index 10586d5..0000000 --- a/unittests/asserts_test.js +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env node - -unittest = require("./test-unittest"); - -const testFunctions = [{name: "f", args: [], expectSuccess: true}, - {name: "g", args: [], expectSuccess: false}, - {name: "h", args: [], expectSuccess: false}, - {name: "i", args: [], expectSuccess: true}, - {name: "j", args: [], expectSuccess: false}]; - -unittest.deploy("asserts.bytecode", "asserts.abi", testFunctions); diff --git a/unittests/builtins.ds b/unittests/builtins.ds index e751e34..eba79ce 100644 --- a/unittests/builtins.ds +++ b/unittests/builtins.ds @@ -8,6 +8,8 @@ object signature OS = { const get_coinbase : unit -> uint; const get_timestamp : unit -> uint; const get_number : unit -> uint; + (* const get_chainid : unit -> uint; *) (*Not supported by our ethereum test yet*) + (* const get_selfbalance : unit -> uint; *) const get_balance_this : unit -> uint; const get_blockhash_prev : unit -> uint } @@ -20,6 +22,8 @@ object O : OS { let _coinbase : uint := 0u0 let _timestamp : uint := 0u0 let _number : uint := 0u0 + (* let _chainid : uint := 0u0 *) + (* let _selfbalance : uint := 0u0 *) let _balance_this : uint := 0u0 let _blockhash_prev : uint := 0u0 @@ -31,6 +35,8 @@ object O : OS { let get_coinbase () = let x = _coinbase in x let get_timestamp () = let x = _timestamp in x let get_number () = let x = _number in x + (* let get_chainid () = let x = _chainid in x *) + (* let get_selfbalance () = let x = _selfbalance in x *) let get_balance_this () = let x = _balance_this in x let get_blockhash_prev () = let x = _blockhash_prev in x @@ -42,6 +48,8 @@ object O : OS { _coinbase := block_coinbase; _timestamp := block_timestamp; _number := block_number; + (* _chainid := chain_id; *) + (* _selfbalance := self_balance; *) _balance_this := balance(this_address); _blockhash_prev := blockhash(block_number-0u1); true diff --git a/unittests/builtins_test.js b/unittests/builtins_test.js deleted file mode 100755 index c884b58..0000000 --- a/unittests/builtins_test.js +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env node - -// const net = require('net'); -// const solc = require('solc'); -const fs = require('fs'); -const ethers = require("ethers"); - -const endpoint = "http://localhost:8545"; -const provider = new ethers.providers.JsonRpcProvider(endpoint); - -const bytecodeFilename = "builtins.bytecode"; -const abiFilename = "builtins.abi"; - -const bytecode = fs.readFileSync(bytecodeFilename).toString().replace(/\n|\t|\r| /g, ""); -const abi = JSON.parse(fs.readFileSync(abiFilename).toString()); - -const signer = provider.getSigner(0); - -function printTest(name, success) { - console.log(name +": " + (success? "pass✅" : "fail❌")); -} - -async function deploy() { - let factory = new ethers.ContractFactory(abi, bytecode, signer); - let creator = await signer.getAddress(); - let contract = await factory.deploy(); - let tx = await contract.deployed(); - - let VALUE = ethers.utils.parseEther('0.1'); - - tx = await contract.f({value: VALUE}); - - let _address = await contract.get_address(); - let _origin = await contract.get_origin(); - let _caller = await contract.get_caller(); - let _callvalue = await contract.get_callvalue(); - let _coinbase = await contract.get_coinbase(); - let _timestamp = await contract.get_timestamp(); - let _number = await contract.get_number(); - let _balance_this = await contract.get_balance_this(); - let _blockhash_prev = await contract.get_blockhash_prev(); - - - blockNumber = await provider.getBlockNumber(); - block = await provider.getBlock (blockNumber) - - printTest("address", _address == contract.address); - printTest("origin", _origin == creator); - printTest("caller", _caller == creator); - printTest("callvalue", _callvalue.eq(VALUE)); - printTest("timestamp", _timestamp.eq(block.timestamp)); - printTest("number", _number.eq(blockNumber)); - printTest("balance(this_address)", _balance_this.eq(VALUE)); - printTest("blockhash(parent)", _blockhash_prev.eq(block.parentHash)); // the hash of the current block is not available, you just get 0x0 if you try, so we query the parent -} - -deploy(); diff --git a/unittests/builtins_test.ts b/unittests/builtins_test.ts new file mode 100644 index 0000000..983a5ca --- /dev/null +++ b/unittests/builtins_test.ts @@ -0,0 +1,45 @@ +import { Chain } from './chain' +import { printTest } from './utils' + +export async function runTest(chain: Chain) { + await chain.deployContract('builtins') + + const _value = 5; + + let blockNumber = await chain.callMethod('f', [], {value: _value}) + + const [ + _address, + _origin, + _caller, + _callvalue, + _coinbase, + _timestamp, + _number, + _balance_this, + _blockhash_prev + ] = await Promise.all([ + chain.callMethod('get_address'), + chain.callMethod('get_origin'), + chain.callMethod('get_caller'), + chain.callMethod('get_callvalue'), + chain.callMethod('get_coinbase'), + chain.callMethod('get_timestamp'), + chain.callMethod('get_number'), + chain.callMethod('get_balance_this'), + chain.callMethod('get_blockhash_prev') + ]) + + printTest("address", _address == chain.getContractAddress()); + printTest("origin", _origin == chain.getAccountAddress()); + printTest("caller", _caller == chain.getAccountAddress()); + printTest("callvalue", _callvalue == _value); + printTest("timestamp", _timestamp == await chain.getBlockTimestamp(blockNumber)); + printTest("number", _number == blockNumber); + printTest("balance(this_address)", _balance_this == _value); + printTest("blockhash(parent)", chain.hashToString(_blockhash_prev) + == await chain.getBlockParentHash(blockNumber)); + // the hash of the current block is not available, you just get 0x0 if you try, so we query the parent +} + +export default { runTest } diff --git a/unittests/chain.ts b/unittests/chain.ts new file mode 100644 index 0000000..8f1c58d --- /dev/null +++ b/unittests/chain.ts @@ -0,0 +1,17 @@ +export interface Chain { + deployContract(jsonFilename: string, constructorArgs?: any[]): void + callMethod(func: string, args?: any[], options?: {}): any + + getContractAddress(): string + getAccountAddress(): string + getBlockTimestamp(blockNumber: number): Promise + getBlockParentHash(blockNumber: number): Promise + getEvents(): Promise + + hashToString(hash: any): string +} + +export interface Event { + signature: string + args: {} +} diff --git a/unittests/clean-json.py b/unittests/clean-json.py new file mode 100644 index 0000000..07c8e32 --- /dev/null +++ b/unittests/clean-json.py @@ -0,0 +1,11 @@ +import sys +import json + +s = sys.stdin.read() +obj = json.loads(s) +contracts = obj[list(obj)[0]] +first_contract = contracts[list(contracts)[0]] +first_contract['bytecode'] = '0x' + first_contract['bin'] +del first_contract['bin'] +first_contract['abi'] = json.loads(first_contract['abi']) +print(json.dumps(first_contract)) diff --git a/unittests/conflux-chain.ts b/unittests/conflux-chain.ts new file mode 100644 index 0000000..5ac9623 --- /dev/null +++ b/unittests/conflux-chain.ts @@ -0,0 +1,121 @@ +import { Conflux, Account } from 'js-conflux-sdk' +import { Chain, Event } from './chain' +import { getJsonFilename } from './utils' +import _ from 'lodash' + + +export class ConfluxChain implements Chain { + private _conflux: Conflux + private _contract + private _genesisAccount: Account + private _abi: any[] + + constructor(verbose=false) { + let logger = this.getLogger(verbose) + + this._conflux = new Conflux({ + url: 'http://localhost:12537', + // defaultGasPrice: 1000, + // defaultGas: 1000, + // logger: this._logger, + logger: logger, + }) + + const genesisPrivateKey = + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + this._genesisAccount = this._conflux.wallet.addPrivateKey(genesisPrivateKey) + } + private getLogger(verbose: boolean): Logger { + if (verbose) + return console + + let logger: Logger = { + info: function() {}, // Output nothing. + error: function() {} + } + return logger + } + + async deployContract(jsonFilename: string, constructorArgs=[]){ + const {abi, bytecode} = require(getJsonFilename(jsonFilename)) + this._contract = this._conflux.Contract({ abi, bytecode }) + this._abi = abi + + const receipt = await this._contract + .constructor(...constructorArgs) + .sendTransaction({ from: this._genesisAccount }) + .executed(); + this._contract.address = receipt.contractCreated; + } + + async callRead(func: string, args=[]){ + return await this._contract[func](...args) + } + + async callWrite(func: string, args=[], options={}) { + // console.log("func: " + func) + // console.log("args: " + args) + // console.log("options: " + JSON.stringify(options)) + let receipt = await this._contract[func](...args) + .sendTransaction({ from: this._genesisAccount, ...options }) + .executed(); + return receipt.epochNumber + } + + isRead(func: string): boolean { + const f = this._abi.find(element => element.name == func) + let readStates = [ "view", "pure" ] + return readStates.includes(f.stateMutability) + } + + async callMethod(func: string, args=[], options={}) { + if (this.isRead(func)) { + if (!_.isEmpty(options)) + throw Error("Options specified but ignored.") + return this.callRead(func, args) // returns the read value + } else + return this.callWrite(func, args, options) // returns the block number + } + + // Getter functions + getContractAddress(): string { + return this._contract.address + } + getAccountAddress(): string { + return this._genesisAccount.toString() + } + async getBlockTimestamp(blockNumber: number): Promise { + let receipt: any = await this._conflux.getBlockByEpochNumber(blockNumber) + return receipt.timestamp + } + async getBlockParentHash(blockNumber: number): Promise { + let receipt: any = await this._conflux.getBlockByEpochNumber(blockNumber) + return receipt.parentHash + } + + hashToString(hash: any): string { + return hash + } + + async getEvents(): Promise { + const logs = await this._conflux.getLogs({address: this._contract.address}) + let decoded = logs.map(l => this._contract.abi.decodeLog(l)) + return decoded.map(o => { + if (!o) return o + let substitutions = {type: "signature", object: "args"} + for (const old_key in substitutions) { + const new_key = substitutions[old_key] + Object.defineProperty(o, new_key, + Object.getOwnPropertyDescriptor(o, old_key)) + delete o[old_key]; + } + return o + } + ) + } +} + +interface Logger { + info() + error() +} diff --git a/unittests/constructor2_test.js b/unittests/constructor2_test.js deleted file mode 100755 index bf9929b..0000000 --- a/unittests/constructor2_test.js +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env node - -unittest = require("./test-unittest"); - -const testFunctions = [{name: "test_upper", args: [], expectSuccess: true}, - {name: "get_w", args: [], expectValue: 9}]; - -unittest.deploy("constructor2.bytecode", "constructor2.abi", testFunctions, [6, 7, 8, 9]); diff --git a/unittests/constructor_test.js b/unittests/constructor_test.js deleted file mode 100755 index 8bff97d..0000000 --- a/unittests/constructor_test.js +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env node - -unittest = require("./test-unittest"); - -const testFunctions = [{name: "get", args: [], expectSuccess: true}]; - -unittest.deploy("constructor.bytecode", "constructor.abi", testFunctions, [100, 321]); diff --git a/unittests/ethereum-chain.ts b/unittests/ethereum-chain.ts new file mode 100644 index 0000000..2d8b7f7 --- /dev/null +++ b/unittests/ethereum-chain.ts @@ -0,0 +1,83 @@ +import { ethers } from 'ethers' +import { Chain, Event } from './chain' +import { getJsonFilename } from './utils' +import _ from 'lodash' + + +export class EthereumChain implements Chain { + private _provider: ethers.providers.JsonRpcProvider + private _contract: ethers.Contract + private _abi: any[] + private _signer: ethers.providers.JsonRpcSigner + private _creator: string + + constructor() { + const endpoint = "http://localhost:8545"; + this._provider = new ethers.providers.JsonRpcProvider(endpoint); + + this._signer = this._provider.getSigner(0); + } + + async deployContract(jsonFilename: string, constructorArgs=[]) { + this._creator = await this._signer.getAddress(); + + const {abi, bytecode} = require(getJsonFilename(jsonFilename)) + this._abi = abi + + let factory = new ethers.ContractFactory(abi, bytecode, this._signer); + this._contract = await (factory.deploy.apply(factory, constructorArgs)); + await this._contract.deployed(); + } + + async callRead(func: string, args) { + return await this._contract[func](...args) + } + + async callWrite(func: string, args=[], options={}) { + let receipt = await this._contract[func](...args, options) + return receipt.blockNumber + } + + isRead(func: string): boolean { + const f = this._abi.find(element => element.name == func) + let readStates = [ "view", "pure" ] + return readStates.includes(f.stateMutability) + } + + async callMethod(func: string, args=[], options={}) { + if (this.isRead(func)) { + if (!_.isEmpty(options)) + throw Error("Options specified but ignored.") + return this.callRead(func, args) // returns the read value + } else + return this.callWrite(func, args, options) // returns the block number + } + + getContractAddress(): string { + return this._contract.address + } + + getAccountAddress(): string { + return this._creator + } + + async getBlockTimestamp(blockNumber: number): Promise { + let block = await this._provider.getBlock(blockNumber) + return block.timestamp + } + + async getBlockParentHash(blockNumber: number): Promise { + let block = await this._provider.getBlock(blockNumber) + return block.parentHash + } + + hashToString(hash: any): string { + return hash.toHexString() + } + + async getEvents(): Promise { + const logs = await this._provider.getLogs({address: this._contract.address}); + let iface = new ethers.utils.Interface(this._abi); + return logs.map((log) => iface.parseLog(log)) + } +} diff --git a/unittests/events.ds b/unittests/events.ds index 30116c0..b035bee 100644 --- a/unittests/events.ds +++ b/unittests/events.ds @@ -1,3 +1,6 @@ +event + | E0 + event | E1 (v : uint) @@ -18,6 +21,7 @@ object signature OS = { object O : OS { let f () = + emit E0(); emit E1(0u42); emit E2(0u1, false); emit IE1(0u13); diff --git a/unittests/events_test.js b/unittests/events_test.js deleted file mode 100755 index 1476cfd..0000000 --- a/unittests/events_test.js +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env node - -const bytecodeFilename = "events.bytecode"; -const abiFilename = "events.abi"; - -const fs = require('fs'); -const ethers = require("ethers"); - -const endpoint = "http://localhost:8545"; -const provider = new ethers.providers.JsonRpcProvider(endpoint); - -const bytecode = fs.readFileSync(bytecodeFilename).toString().replace(/\n|\t|\r| /g, ""); -const abi = JSON.parse(fs.readFileSync(abiFilename).toString()); - -const signer = provider.getSigner(0); - -function printTest(name, success) { - console.log(name +": " + (success? "pass✅" : "fail❌")); -} - -async function deploy() { - let factory = new ethers.ContractFactory(abi, bytecode, signer); - let iface = new ethers.utils.Interface(abi); - let contract = await factory.deploy(); - let tx = await contract.deployed(); - - retval = await contract.f(); - //console.log(x, retval, x_hash, x_hash2); - - let filter = { - address: contract.address - }; - - const logs = await provider.getLogs(filter); - let events = logs.map((log) => iface.parseLog(log)) - //console.log(retval); - //console.log(logs); - //console.log(events); - - printTest("E1 signature", events[0].signature == "E1(uint256)"); - printTest("E1 values", events[0].args['v'] == 42); - printTest("E2 signature", events[1].signature == "E2(uint256,bool)"); - printTest("E2 values", events[1].args['v1'] == 1 - && events[1].args['v2'] == false); - printTest("IE1 signature", events[2].signature == "IE1(uint256)"); - printTest("IE1 values", events[2].args['v'] == 13); - printTest("IE2 signature", events[3].signature == "IE2(uint256,bool)"); - printTest("IE2 values", events[3].args['v1'] == 2 - && events[3].args['v2'] == false); - printTest("Transfer signature", events[4].signature == "Transfer(uint256,uint256,uint256)"); - printTest("Transfer values", events[4].args['fromA'] == 1 - && events[4].args['toA'] == 2 - && events[4].args['value'] == 42); - printTest("Approval signature", events[5].signature == "Approval(uint256,uint256,uint256)"); - printTest("Approval values", events[5].args['owner'] == 1 - && events[5].args['spender'] == 2 - && events[5].args['value'] == 42); -} - -deploy(); diff --git a/unittests/events_test.ts b/unittests/events_test.ts new file mode 100644 index 0000000..e1bd900 --- /dev/null +++ b/unittests/events_test.ts @@ -0,0 +1,32 @@ +import { Chain } from './chain' +import { printTest } from './utils' + +export async function runTest(chain: Chain) { + await chain.deployContract('events') + + await chain.callMethod("f"); + + let events = await chain.getEvents(); + + printTest("E0 signature", events[0].signature == "E0()"); + printTest("E1 signature", events[1].signature == "E1(uint256)"); + printTest("E1 values", events[1].args['v'] == 42); + printTest("E2 signature", events[2].signature == "E2(uint256,bool)"); + printTest("E2 values", events[2].args['v1'] == 1 + && events[2].args['v2'] == false); + printTest("IE1 signature", events[3].signature == "IE1(uint256)"); + printTest("IE1 values", events[3].args['v'] == 13); + printTest("IE2 signature", events[4].signature == "IE2(uint256,bool)"); + printTest("IE2 values", events[4].args['v1'] == 2 + && events[4].args['v2'] == false); + printTest("Transfer signature", events[5].signature == "Transfer(uint256,uint256,uint256)"); + printTest("Transfer values", events[5].args['fromA'] == 1 + && events[5].args['toA'] == 2 + && events[5].args['value'] == 42); + printTest("Approval signature", events[6].signature == "Approval(uint256,uint256,uint256)"); + printTest("Approval values", events[6].args['owner'] == 1 + && events[6].args['spender'] == 2 + && events[6].args['value'] == 42); +} + +export default { runTest } diff --git a/unittests/forloop_test.js b/unittests/forloop_test.js deleted file mode 100755 index 9fe3a9c..0000000 --- a/unittests/forloop_test.js +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env node - -unittest = require("./test-unittest"); - -const bytecodeFilename = "forloop.bytecode"; -const abiFilename = "forloop.abi"; - -const testFunctions = [{name: "multiply", args: [3, 5], expectSuccess: true}, - {name: "multiply", args: [100, 5], expectSuccess: true}, -/* Negative values will underflow to huge 256-bit values, so this would take a while... Also, ethers will complain about passing a negative value to a uint arg. - {name: "multiply", args: [1000, -5], expectSuccess: true}, - {name: "multiply", args: [-3, 7], expectSuccess: true}*/]; - -unittest.deploy(bytecodeFilename, abiFilename, testFunctions); diff --git a/unittests/genesis_secrets.txt b/unittests/genesis_secrets.txt new file mode 100644 index 0000000..93f308c --- /dev/null +++ b/unittests/genesis_secrets.txt @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/unittests/keccak256_test.js b/unittests/keccak256_test.js deleted file mode 100755 index 5fbe32c..0000000 --- a/unittests/keccak256_test.js +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env node - -const bytecodeFilename = "keccak256.bytecode"; -const abiFilename = "keccak256.abi"; - -// const net = require('net'); -// const solc = require('solc'); -const fs = require('fs'); -const ethers = require("ethers"); - -const endpoint = "http://localhost:8545"; -const provider = new ethers.providers.JsonRpcProvider(endpoint); - -const bytecode = fs.readFileSync(bytecodeFilename).toString().replace(/\n|\t|\r| /g, ""); -const abi = JSON.parse(fs.readFileSync(abiFilename).toString()); -const signer = provider.getSigner(0); - -function printTest(name, success) { - console.log(name +": " + (success? "pass✅" : "fail❌")); -} - -async function deploy() { - let factory = new ethers.ContractFactory(abi, bytecode, signer); - let contract = await factory.deploy(); - let tx = await contract.deployed(); - - let x = "0x000000000000000000000000000000000000000000000000000000000000002a"; - let x_hash = await contract.hash1(x); - printTest("hash1", x_hash.eq(ethers.utils.keccak256(x))); - - let y = "0x000000000000000000000000000000000000000000000000000000000000002b"; - let xy_hash = await contract.hash2(x,y); - printTest("hash2", xy_hash.eq(ethers.utils.keccak256(ethers.utils.concat([x,y])))); - - let xy_hash_1 = await contract.hash2_1(x,y); - printTest("hash2_1", xy_hash_1.eq(ethers.utils.keccak256(ethers.utils.concat([x,y])))); - - let xy_hash_2 = await contract.hash2_2(x,y); - printTest("hash2_2", xy_hash_2.eq(ethers.utils.keccak256(ethers.utils.concat([x,y])))); - - let xy_hash_3 = await contract.hash2_3(x,y); - printTest("hash2_3", xy_hash_3.eq(ethers.utils.keccak256(ethers.utils.concat([x,y])))); - - // Note that below, we get different results for the hashes of addresses than Solidity would give, - // becuase we have more zero-padding. - - let xa = ethers.utils.getAddress("0x000000000000000000000000000000000000002a"); - let xa_hash = await contract.hash1a(xa); - printTest("hash1a", xa_hash.eq(ethers.utils.keccak256(x))); //note: x, not xa. - - let xy_hash_1a = await contract.hash2_1a(xa,y); - printTest("hash2_1a", xy_hash_1.eq(ethers.utils.keccak256(ethers.utils.concat([x,y])))); //note: x, not xa - -} - -deploy(); diff --git a/unittests/keccak256_test.ts b/unittests/keccak256_test.ts new file mode 100644 index 0000000..c971b2e --- /dev/null +++ b/unittests/keccak256_test.ts @@ -0,0 +1,41 @@ +import { ethers } from 'ethers' +import { Chain } from './chain' +import { printTest } from './utils' + +function checkHash(chain: Chain, hash1, vals: string[]) { + return chain.hashToString(hash1) == ethers.utils.keccak256(ethers.utils.concat(vals)) +} + +export async function runTest(chain: Chain) { + await chain.deployContract('keccak256') + + let x = "0x000000000000000000000000000000000000000000000000000000000000002a"; + let x_hash = await chain.callMethod("hash1", [x]) + printTest("hash1", checkHash(chain, x_hash, [x])) + + let y = "0x000000000000000000000000000000000000000000000000000000000000002b"; + let xy_hash = await chain.callMethod("hash2", [x,y]); + printTest("hash2", checkHash(chain, xy_hash, [x,y])) + + let xy_hash_1 = await chain.callMethod("hash2_1", [x,y]); + printTest("hash2_1", checkHash(chain, xy_hash_1, [x,y])) + + let xy_hash_2 = await chain.callMethod("hash2_2", [x,y]); + printTest("hash2_2", checkHash(chain, xy_hash_2, [x,y])) + + let xy_hash_3 = await chain.callMethod("hash2_3", [x,y]); + printTest("hash2_3", checkHash(chain, xy_hash_3, [x,y])) + + // Note that below, we get different results for the hashes of addresses than Solidity would give, + // becuase we have more zero-padding. + + let xa = ethers.utils.getAddress("0x000000000000000000000000000000000000002a"); + let xa_hash = await chain.callMethod("hash1a", [xa]); + printTest("hash1a", checkHash(chain, xa_hash, [x])) //note: x, not xa. + + let xy_hash_1a = await chain.callMethod("hash2_1a", [xa,y]); + printTest("hash2_1a", checkHash(chain, xy_hash_1, [x,y])) //note: x, not xa. + +} + +export default { runTest } diff --git a/unittests/layers1_test.js b/unittests/layers1_test.js deleted file mode 100755 index 0941c0f..0000000 --- a/unittests/layers1_test.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node - -unittest = require("./test-unittest"); - -const bytecodeFilename = "layers1.bytecode"; -const abiFilename = "layers1.abi"; - -const testFunctions = [{name: "f", args: [], expectSuccess: true}]; - -unittest.deploy(bytecodeFilename, abiFilename, testFunctions); diff --git a/unittests/match-int_test.js b/unittests/match-int_test.js deleted file mode 100755 index 33b46e1..0000000 --- a/unittests/match-int_test.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node - -unittest = require("./test-unittest"); - -const bytecodeFilename = "match-int.bytecode"; -const abiFilename = "match-int.abi"; - -const testFunctions = [{name: "f", args: [], expectSuccess: true}]; - -unittest.deploy(bytecodeFilename, abiFilename, testFunctions); diff --git a/unittests/package-lock.json b/unittests/package-lock.json new file mode 100644 index 0000000..82d67cb --- /dev/null +++ b/unittests/package-lock.json @@ -0,0 +1,1700 @@ +{ + "name": "unittests", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/runtime": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@ethersproject/abi": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.9.tgz", + "integrity": "sha512-ily2OufA2DTrxkiHQw5GqbkMSnNKuwZBqKsajtT0ERhZy1r9w2CpW1bmtRMIGzaqQxCdn/GEoFogexk72cBBZQ==", + "requires": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "@ethersproject/abstract-provider": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.7.tgz", + "integrity": "sha512-NF16JGn6M0zZP5ZS8KtDL2Rh7yHxZbUjBIHLNHMm/0X0BephhjUWy8jqs/Zks6kDJRzNthgmPVy41Ec0RYWPYA==", + "requires": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/networks": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/web": "^5.0.6" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.9.tgz", + "integrity": "sha512-CM5UNmXQaA03MyYARFDDRjHWBxujO41tVle7glf5kHcQsDDULgqSVpkliLJMtPzZjOKFeCVZBHybTZDEZg5zzg==", + "requires": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3" + } + }, + "@ethersproject/address": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.8.tgz", + "integrity": "sha512-V87DHiZMZR6hmFYmoGaHex0D53UEbZpW75uj8AqPbjYUmi65RB4N2LPRcJXuWuN2R0Y2CxkvW6ArijWychr5FA==", + "requires": { + "@ethersproject/bignumber": "^5.0.10", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/rlp": "^5.0.3" + } + }, + "@ethersproject/base64": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.6.tgz", + "integrity": "sha512-HwrGn8YMiUf7bcdVvB4NJ+eWT0BtEFpDtrYxVXEbR7p/XBSJjwiR7DEggIiRvxbualMKg+EZijQWJ3az2li0uw==", + "requires": { + "@ethersproject/bytes": "^5.0.4" + } + }, + "@ethersproject/basex": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.6.tgz", + "integrity": "sha512-Y/8dowRxBF3bsKkqEp7XN4kcFFQ0o5xxP1YyopfqkXejaOEGiD7ToQdQ0pIZpAJ5GreW56oFOTDDSO6ZcUCNYg==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/properties": "^5.0.3" + } + }, + "@ethersproject/bignumber": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.12.tgz", + "integrity": "sha512-mbFZjwthx6vFlHG9owXP/C5QkNvsA+xHpDCkPPPdG2n1dS9AmZAL5DI0InNLid60rQWL3MXpEl19tFmtL7Q9jw==", + "requires": { + "@ethersproject/bytes": "^5.0.8", + "@ethersproject/logger": "^5.0.5", + "bn.js": "^4.4.0" + } + }, + "@ethersproject/bytes": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.8.tgz", + "integrity": "sha512-O+sJNVGzzuy51g+EMK8BegomqNIg+C2RO6vOt0XP6ac4o4saiq69FnjlsrNslaiMFVO7qcEHBsWJ9hx1tj1lMw==", + "requires": { + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/constants": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.7.tgz", + "integrity": "sha512-cbQK1UpE4hamB52Eg6DLhJoXeQ1plSzekh5Ujir1xdREdwdsZPPXKczkrWqBBR0KyywJZHN/o/hj0w8j7scSGg==", + "requires": { + "@ethersproject/bignumber": "^5.0.7" + } + }, + "@ethersproject/contracts": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.8.tgz", + "integrity": "sha512-PecBL4vnsrpuks2lzzkRsOts8csJy338HNDKDIivbFmx92BVzh3ohOOv3XsoYPSXIHQvobF959W+aSk3RCZL/g==", + "requires": { + "@ethersproject/abi": "^5.0.5", + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3" + } + }, + "@ethersproject/hash": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.9.tgz", + "integrity": "sha512-e8/i2ZDeGSgCxXT0vocL54+pMbw5oX5fNjb2E3bAIvdkh5kH29M7zz1jHu1QDZnptIuvCZepIbhUH8lxKE2/SQ==", + "requires": { + "@ethersproject/abstract-signer": "^5.0.6", + "@ethersproject/address": "^5.0.5", + "@ethersproject/bignumber": "^5.0.8", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.4", + "@ethersproject/strings": "^5.0.4" + } + }, + "@ethersproject/hdnode": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.7.tgz", + "integrity": "sha512-89tphqlji4y/LNE1cSaMQ3hrBtJ4lO1qWGi2hn54LiHym85DTw+zAKbA8QgmdSdJDLGR/kc9VHaIPQ+vZQ2LkQ==", + "requires": { + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/basex": "^5.0.3", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/pbkdf2": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/wordlists": "^5.0.4" + } + }, + "@ethersproject/json-wallets": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.9.tgz", + "integrity": "sha512-EWuFvJd8nu90dkmJwmJddxOYCvFvMkKBsZi8rxTme2XEZsHKOFnybVkoL23u7ZtApuEfTKmVcR2PTwgZwqDsKw==", + "requires": { + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hdnode": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/pbkdf2": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "@ethersproject/keccak256": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.6.tgz", + "integrity": "sha512-eJ4Id/i2rwrf5JXEA7a12bG1phuxjj47mPZgDUbttuNBodhSuZF2nEO5QdpaRjmlphQ8Kt9PNqY/z7lhtJptZg==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "js-sha3": "0.5.7" + } + }, + "@ethersproject/logger": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.8.tgz", + "integrity": "sha512-SkJCTaVTnaZ3/ieLF5pVftxGEFX56pTH+f2Slrpv7cU0TNpUZNib84QQdukd++sWUp/S7j5t5NW+WegbXd4U/A==" + }, + "@ethersproject/networks": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.6.tgz", + "integrity": "sha512-2Cg1N5109zzFOBfkyuPj+FfF7ioqAsRffmybJ2lrsiB5skphIAE72XNSCs4fqktlf+rwSh/5o/UXRjXxvSktZw==", + "requires": { + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/pbkdf2": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.6.tgz", + "integrity": "sha512-CUYciSxR/AaCoKMJk3WUW+BDhR41G3C+O9lOeZ4bR1wDhLKL2Z8p0ciF5XDEiVbmI4CToW6boVKybeVMdngRrg==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/sha2": "^5.0.3" + } + }, + "@ethersproject/properties": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.6.tgz", + "integrity": "sha512-a9DUMizYhJ0TbtuDkO9iYlb2CDlpSKqGPDr+amvlZhRspQ6jbl5Eq8jfu4SCcGlcfaTbguJmqGnyOGn1EFt6xA==", + "requires": { + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/providers": { + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.17.tgz", + "integrity": "sha512-bJnvs5X7ttU5x2ekGJYG7R3Z+spZawLFfR0IDsbaMDLiCwZOyrgk+VTBU7amSFLT0WUhWFv8WwSUB+AryCQG1Q==", + "requires": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/basex": "^5.0.3", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/networks": "^5.0.3", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/strings": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/web": "^5.0.6", + "bech32": "1.1.4", + "ws": "7.2.3" + } + }, + "@ethersproject/random": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.6.tgz", + "integrity": "sha512-8nsVNaZvZ9OD5NXfzE4mmz8IH/1DYJbAR95xpRxZkIuNmfn6QlMp49ccJYZWGhs6m0Zj2+FXjx3pzXfYlo9/dA==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/rlp": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.6.tgz", + "integrity": "sha512-M223MTaydfmQSsvqAl0FJZDYFlSqt6cgbhnssLDwqCKYegAHE16vrFyo+eiOapYlt32XAIJm0BXlqSunULzZuQ==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/sha2": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.6.tgz", + "integrity": "sha512-30gypDLkfkP5gE3llqi0jEuRV8m4/nvzeqmqMxiihZ7veFQHqDaGpyFeHzFim+qGeH9fq0lgYjavLvwW69+Fkw==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "hash.js": "1.1.3" + }, + "dependencies": { + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + } + } + }, + "@ethersproject/signing-key": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.7.tgz", + "integrity": "sha512-JYndnhFPKH0daPcIjyhi+GMcw3srIHkQ40hGRe6DA0CdGrpMfgyfSYDQ2D8HL2lgR+Xm4SHfEB0qba6+sCyrvg==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "elliptic": "6.5.3" + } + }, + "@ethersproject/solidity": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.7.tgz", + "integrity": "sha512-dUevKUZ06p/VMLP/+cz4QUV+lA17NixucDJfm0ioWF0B3R0Lf+6wqwPchcqiAXlxkNFGIax7WNLgGMh4CkQ8iw==", + "requires": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/sha2": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "@ethersproject/strings": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.7.tgz", + "integrity": "sha512-a+6T80LvmXGMOOWQTZHtGGQEg1z4v8rm8oX70KNs55YtPXI/5J3LBbVf5pyqCKSlmiBw5IaepPvs5XGalRUSZQ==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/transactions": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.8.tgz", + "integrity": "sha512-i7NtOXVzUe+YSU6QufzlRrI2WzHaTmULAKHJv4duIZMLqzehCBXGA9lTpFgFdqGYcQJ7vOtNFC2BB2mSjmuXqg==", + "requires": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/rlp": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4" + } + }, + "@ethersproject/units": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.8.tgz", + "integrity": "sha512-3O4MaNHFs05vC5v2ZGqVFVWtO1WyqFejO78M7Qh16njo282aoMlENtVI6cn2B36zOLFXRvYt2pYx6xCG53qKzg==", + "requires": { + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/logger": "^5.0.5" + } + }, + "@ethersproject/wallet": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.9.tgz", + "integrity": "sha512-GfpQF56PO/945SJq7Wdg5F5U6wkxaDgkAzcgGbCW6Joz8oW8MzKItkvYCzMh+j/8gJMzFncsuqX4zg2gq3J6nQ==", + "requires": { + "@ethersproject/abstract-provider": "^5.0.4", + "@ethersproject/abstract-signer": "^5.0.4", + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/hdnode": "^5.0.4", + "@ethersproject/json-wallets": "^5.0.6", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/random": "^5.0.3", + "@ethersproject/signing-key": "^5.0.4", + "@ethersproject/transactions": "^5.0.5", + "@ethersproject/wordlists": "^5.0.4" + } + }, + "@ethersproject/web": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.11.tgz", + "integrity": "sha512-x03ihbPoN1S8Gsh9WSwxkYxUIumLi02ZEKJku1C43sxBfe+mdprWyvujzYlpuoRNfWRgNhdRDKMP8JbG6MwNGA==", + "requires": { + "@ethersproject/base64": "^5.0.3", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "@ethersproject/wordlists": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.7.tgz", + "integrity": "sha512-ZjQtYxm41FmHfYgpkdQG++EDcBPQWv9O6FfP6NndYRVaXaQZh6eq3sy7HQP8zCZ8dznKgy6ZyKECS8qdvnGHwA==", + "requires": { + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "@types/node": { + "version": "14.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.12.tgz", + "integrity": "sha512-ASH8OPHMNlkdjrEdmoILmzFfsJICvhBsFfAum4aKZ/9U4B6M6tTmTPh+f3ttWdD74CEGV5XvXWkbyfSdXaTd7g==" + }, + "aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "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.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "bufferutil": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.2.tgz", + "integrity": "sha512-AtnG3W6M8B2n4xDQ5R+70EXvOpnXsFYg/AK2yTZd+HQ/oxAdz+GI+DvjmhBw3L0ole+LJ0ngqY4JMbDzkfNzhA==", + "requires": { + "node-gyp-build": "^4.2.0" + } + }, + "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.1", + "safe-buffer": "^5.0.1" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + }, + "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.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "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.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "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.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "ethers": { + "version": "5.0.24", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.24.tgz", + "integrity": "sha512-77CEtVC88fJGEhxGXRvQqAEH6e2A+ZFiv2FBT6ikXndlty5sw6vMatAhg1v+w3CaaGZOf1CP81jl4Mc8Zrj08A==", + "requires": { + "@ethersproject/abi": "5.0.9", + "@ethersproject/abstract-provider": "5.0.7", + "@ethersproject/abstract-signer": "5.0.9", + "@ethersproject/address": "5.0.8", + "@ethersproject/base64": "5.0.6", + "@ethersproject/basex": "5.0.6", + "@ethersproject/bignumber": "5.0.12", + "@ethersproject/bytes": "5.0.8", + "@ethersproject/constants": "5.0.7", + "@ethersproject/contracts": "5.0.8", + "@ethersproject/hash": "5.0.9", + "@ethersproject/hdnode": "5.0.7", + "@ethersproject/json-wallets": "5.0.9", + "@ethersproject/keccak256": "5.0.6", + "@ethersproject/logger": "5.0.8", + "@ethersproject/networks": "5.0.6", + "@ethersproject/pbkdf2": "5.0.6", + "@ethersproject/properties": "5.0.6", + "@ethersproject/providers": "5.0.17", + "@ethersproject/random": "5.0.6", + "@ethersproject/rlp": "5.0.6", + "@ethersproject/sha2": "5.0.6", + "@ethersproject/signing-key": "5.0.7", + "@ethersproject/solidity": "5.0.7", + "@ethersproject/strings": "5.0.7", + "@ethersproject/transactions": "5.0.8", + "@ethersproject/units": "5.0.8", + "@ethersproject/wallet": "5.0.9", + "@ethersproject/web": "5.0.11", + "@ethersproject/wordlists": "5.0.7" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" + } + } + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" + }, + "ganache-cli": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.12.1.tgz", + "integrity": "sha512-zoefZLQpQyEJH9jgtVYgM+ENFLAC9iwys07IDCsju2Ieq9KSTLH89RxSP4bhizXKV/h/+qaWpfyCBGWnBfqgIQ==", + "requires": { + "ethereumjs-util": "6.2.1", + "source-map-support": "0.5.12", + "yargs": "13.2.4" + }, + "dependencies": { + "@types/bn.js": { + "version": "4.11.6", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "14.11.2", + "bundled": true + }, + "@types/pbkdf2": { + "version": "3.1.0", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/secp256k1": { + "version": "4.0.1", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "ansi-regex": { + "version": "4.1.0", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "base-x": { + "version": "3.0.8", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "blakejs": { + "version": "1.1.0", + "bundled": true + }, + "bn.js": { + "version": "4.11.9", + "bundled": true + }, + "brorand": { + "version": "1.1.0", + "bundled": true + }, + "browserify-aes": { + "version": "1.2.0", + "bundled": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "bs58": { + "version": "4.0.1", + "bundled": true, + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "bundled": true, + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "buffer-from": { + "version": "1.1.1", + "bundled": true + }, + "buffer-xor": { + "version": "1.0.3", + "bundled": true + }, + "camelcase": { + "version": "5.3.1", + "bundled": true + }, + "cipher-base": { + "version": "1.0.4", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cliui": { + "version": "5.0.0", + "bundled": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "create-hash": { + "version": "1.2.0", + "bundled": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "bundled": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "elliptic": { + "version": "6.5.3", + "bundled": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "bundled": true + }, + "end-of-stream": { + "version": "1.4.4", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "ethereum-cryptography": { + "version": "0.1.3", + "bundled": true, + "requires": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "ethereumjs-util": { + "version": "6.2.1", + "bundled": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "ethjs-util": { + "version": "0.1.6", + "bundled": true, + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "bundled": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "hash-base": { + "version": "3.1.0", + "bundled": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "bundled": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "bundled": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-hex-prefixed": { + "version": "1.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "keccak": { + "version": "3.0.1", + "bundled": true, + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "bundled": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mem": { + "version": "4.3.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "bundled": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "bundled": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "node-addon-api": { + "version": "2.0.2", + "bundled": true + }, + "node-gyp-build": { + "version": "4.2.3", + "bundled": true + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "2.1.0", + "bundled": true + }, + "p-limit": { + "version": "2.3.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "bundled": true + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "pbkdf2": { + "version": "3.1.1", + "bundled": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "randombytes": { + "version": "2.1.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "bundled": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "2.0.0", + "bundled": true + }, + "ripemd160": { + "version": "2.0.2", + "bundled": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.6", + "bundled": true, + "requires": { + "bn.js": "^4.11.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "bundled": true + }, + "scrypt-js": { + "version": "3.0.1", + "bundled": true + }, + "secp256k1": { + "version": "4.0.2", + "bundled": true, + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "semver": { + "version": "5.7.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "setimmediate": { + "version": "1.0.5", + "bundled": true + }, + "sha.js": { + "version": "2.4.11", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.3", + "bundled": true + }, + "source-map": { + "version": "0.6.1", + "bundled": true + }, + "source-map-support": { + "version": "0.5.12", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "string-width": { + "version": "3.1.0", + "bundled": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "bundled": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-hex-prefix": { + "version": "1.0.0", + "bundled": true, + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "5.1.0", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yargs": { + "version": "13.2.4", + "bundled": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + }, + "yargs-parser": { + "version": "13.1.2", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "js-conflux-sdk": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-conflux-sdk/-/js-conflux-sdk-1.1.6.tgz", + "integrity": "sha512-ujZ0VZ5t6Iu2AdarZZttsfcEA1Iea2qcz5DqsWGOoBhhFsXY1dlyFjHhy0EooBgPNc+q/ZwsTjlQ/VOmI+Dvag==", + "requires": { + "@babel/runtime": "^7.8.4", + "big.js": "^5.2.2", + "keccak": "^2.0.0", + "lodash": "^4.17.19", + "scrypt-js": "^3.0.1", + "secp256k1": "^3.7.1", + "superagent": "^5.1.0", + "websocket": "^1.0.31" + } + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "keccak": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", + "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", + "requires": { + "bindings": "^1.5.0", + "inherits": "^2.0.4", + "nan": "^2.14.0", + "safe-buffer": "^5.2.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "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.0", + "inherits": "^2.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + }, + "secp256k1": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", + "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", + "requires": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.5.2", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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.1", + "safe-buffer": "^5.0.1" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "superagent": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", + "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "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" + } + }, + "typescript": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz", + "integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==" + }, + "utf-8-validate": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.3.tgz", + "integrity": "sha512-jtJM6fpGv8C1SoH4PtG22pGto6x+Y8uPprW0tw3//gGFhDDTiuksgradgFN6yRayDP4SyZZa6ZMGHLIa17+M8A==", + "requires": { + "node-gyp-build": "^4.2.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "websocket": { + "version": "1.0.33", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.33.tgz", + "integrity": "sha512-XwNqM2rN5eh3G2CUQE3OHZj+0xfdH42+OFK6LdC2yqiC0YU8e5UK0nYre220T0IyyN031V/XOvtHvXozvJYFWA==", + "requires": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "ws": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", + "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==" + }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/unittests/package.json b/unittests/package.json new file mode 100644 index 0000000..a3cd11b --- /dev/null +++ b/unittests/package.json @@ -0,0 +1,17 @@ +{ + "name": "unittests", + "version": "1.0.0", + "dependencies": { + "@types/node": "^14.14.9", + "ethers": "^5.0.20", + "ganache-cli": "^6.12.1", + "js-conflux-sdk": "^1.1.1", + "js-yaml": "^3.14.0", + "lodash": "^4.17.20", + "typescript": "^4.1.2" + }, + "scripts": { + "ganache": "ganache-cli", + "tsc": "tsc" + } +} diff --git a/unittests/run_unittests.sh b/unittests/run_unittests.sh index 3920b5c..c14044d 100755 --- a/unittests/run_unittests.sh +++ b/unittests/run_unittests.sh @@ -1,51 +1,12 @@ #!/bin/bash -EDSGER=../binaries/MacOS/dsc +edsger=../binaries/MacOS/dsc -# Delete the generated files before running a test again. -function rmtest { - input=$1 - if [ -f ${input}.bytecode ]; then - rm ${input}.bytecode - fi - if [ -f ${input}.abi ]; then - rm ${input}.abi - fi - if [ -d ${input} ]; then - rm -r ${input} - fi -} +if [[ ! -d build ]]; then mkdir build; fi -function coq_runtest { - input=$1 - echo "$input" ------------------------------ - ${EDSGER} ${input}.ds coq >/dev/null || echo edsger faild - (cd "$input"; coq_makefile -f _CoqProject -o Makefile) >/dev/null 2>&1 || echo coq_makefile failed - (cd "$input"; make) > /dev/null 2>&1 || echo make failed - cp ../backend/extraction/Asm.ml $input/extraction/ - cp ../backend/extraction/*Ext.ml $input/extraction/ - (cd $input/extraction; ocamlbuild Tester.byte) || echo ocamlbuild failed - $input/extraction/Tester.byte bytecode > ${input}.bytecode || echo bytecode compilation failed - ${EDSGER} ${input}.ds abi > ${input}.abi - ./${input}_test.js -} +for deepsea in *.ds; do + $edsger $deepsea combined-json | python3 clean-json.py > build/${deepsea%.ds}.json +done -function runtest { - input=$1 - echo "$input" ------------------------------ - ${EDSGER} ${input}.ds bytecode > ${input}.bytecode - ${EDSGER} ${input}.ds abi > ${input}.abi - ./${input}_test.js -} - - -if [ "$#" -eq 0 ]; then - tests=(*_test.js) -else - tests=("$@") -fi - -# You can replace "runtest" with "coq_runtest" below to use the -# Coq compilation path. -for i in "${tests[@]}"; do rmtest ${i%_test.js}; done -for i in "${tests[@]}"; do runtest ${i%_test.js}; done +npm run tsc +node build/tests.js diff --git a/unittests/start_conflux.sh b/unittests/start_conflux.sh new file mode 100755 index 0000000..ba4d016 --- /dev/null +++ b/unittests/start_conflux.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Set this to the location of the conflux repo. +conflux=~/Documents/conflux-rust + +cp ./tethys.toml ./genesis_secrets.txt $conflux/run +cd $conflux/run +./clear_state.sh +$conflux/target/release/conflux --config tethys.toml diff --git a/unittests/struct.ds b/unittests/struct.ds index 4669479..45dbc82 100644 --- a/unittests/struct.ds +++ b/unittests/struct.ds @@ -1,32 +1,32 @@ type addr := int object signature OS = { - initialize : int * int -> unit; - hasOwner : unit -> unit; - hasSupply : int -> unit; + initialize : int * int -> unit; + hasOwner : unit -> unit; + hasSupply : int -> unit; } type Token = { - totalSupply : int; - owner : addr + totalSupply : int; + owner : addr } object O : OS { - let token : Token := { totalSupply=0; owner=0 } + let token : Token := { totalSupply=0; owner=0 } - let initialize (_totalSupply, _owner) = - token.totalSupply := _totalSupply; - token.owner := _owner; - () + let initialize (_totalSupply, _owner) = + token.totalSupply := _totalSupply; + token.owner := _owner; + () - let hasOwner () = - let _owner = token.owner in - assert (_owner <> 0) + let hasOwner () = + let _owner = token.owner in + assert (_owner <> 0) - let hasSupply (amount) = - let _totalSupply = token.totalSupply in - assert (_totalSupply >= amount) - + let hasSupply (amount) = + let _totalSupply = token.totalSupply in + assert (_totalSupply >= amount) + } layer L = { diff --git a/unittests/struct_test.js b/unittests/struct_test.js deleted file mode 100755 index 9c3c32e..0000000 --- a/unittests/struct_test.js +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env node - -unittest = require("./test-unittest"); - -const bytecodeFilename = "struct.bytecode"; -const abiFilename = "struct.abi"; - -const testFunctions = [{name: "initialize", args: [0, 0], expectSuccess: true}, - {name: "hasOwner", args: [], expectSuccess: false}, - {name: "hasSupply", args: [5], expectSuccess: false}, - {name: "initialize", args: [5, 17], expectSuccess: true}, - {name: "hasSupply", args: [4], expectSuccess: true}, - {name: "hasSupply", args: [5], expectSuccess: true}, - {name: "hasSupply", args: [6], expectSuccess: false}, - {name: "hasOwner", args: [], expectSuccess: true}]; - -unittest.deploy(bytecodeFilename, abiFilename, testFunctions); diff --git a/unittests/test-unittest b/unittests/test-unittest deleted file mode 100755 index 3564358..0000000 --- a/unittests/test-unittest +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); -const ethers = require("ethers"); - -async function deploy(bytecodeFilename, abiFilename, testFunctions, constructorArgs=[], verbose=false) { - - const endpoint = "http://localhost:8545"; - const provider = new ethers.providers.JsonRpcProvider(endpoint); - - const bytecode = fs.readFileSync(bytecodeFilename).toString().replace(/\n|\t|\r| /g, ""); - const abi = JSON.parse(fs.readFileSync(abiFilename).toString()); - - const signer = provider.getSigner(0); - const creator = signer.getAddress(); - - //console.log("sending creation transaction...") - let factory = new ethers.ContractFactory(abi, bytecode, signer); - // TODO: params. For now, when testing constructor, using 100, 321 - let contract = await (factory.deploy.apply(factory,constructorArgs)); - await contract.deployed(); - //console.log("contract address: " + contract.address); - //console.log("transaction hash: " + contract.deployTransaction.hash); - //let deployedBytecode = await provider.getCode(contract.address); - //console.log("deployed bytecode: " + deployedBytecode); - - for (const func of testFunctions) { - await contract[func.name].apply(null, func.args).then((result) => { - if (func.expectValue) { - if (result == func.expectValue) - console.log(func.name + ": pass✅ (with correct value)"); - else - console.log(func.name + ": fail❌ (expected " - + func.expectValue - + " but got " + result + ")"); - } else if (func.expectSuccess) console.log(func.name + ": pass✅"); - else console.log(func.name + ": fail❌"); - - if (verbose) console.log(JSON.stringify(result, null, 2)); - - }, (error) => { - - if (!func.expectSuccess) console.log(func.name + ": pass✅"); - else console.log(func.name + ": fail❌"); - - if (verbose) console.log(JSON.stringify(error, null, 2)); - - }) - } - -} - -module.exports = { deploy } diff --git a/unittests/test-unittest.ts b/unittests/test-unittest.ts new file mode 100644 index 0000000..5102e98 --- /dev/null +++ b/unittests/test-unittest.ts @@ -0,0 +1,36 @@ +import { Chain } from './chain' +import { padName } from './utils' + +export async function runTest( + chain: Chain, name: string, calls: any[], constructorArgs=[], verbose=false) { + + await chain.deployContract(name, constructorArgs) + + for (const func of calls) { + let padded = padName(func.name) + await chain.callMethod(func.name, func.args, func.options) + .then((result) => { + if (func.expectValue) { + if (result == func.expectValue) + console.log(padded, "pass✅ (with correct value)"); + else + console.log(padded, "fail❌ (expected " + + func.expectValue + + " but got " + result + ")"); + } + else if (func.expectSuccess) + console.log(padded, "pass✅"); + else + console.log(padded, "fail❌"); + + if (verbose) console.log(JSON.stringify(result, null, 2)); + }, (error) => { + if (!func.expectSuccess) + console.log(padded, "pass✅"); + else + console.log(padded, "fail❌"); + + if (verbose) console.log(JSON.stringify(error, null, 2)); + }) + } +} diff --git a/unittests/tests.ts b/unittests/tests.ts new file mode 100644 index 0000000..4ff0204 --- /dev/null +++ b/unittests/tests.ts @@ -0,0 +1,46 @@ +import { ConfluxChain } from './conflux-chain' +import { EthereumChain } from './ethereum-chain' +import { runTest } from './test-unittest' +import yaml from 'js-yaml' +import fs from 'fs' + +import builtin from './builtins_test' +import keccak256 from './keccak256_test' +import events from './events_test' + +async function main() { + const tests = yaml.safeLoad(fs.readFileSync('./tests.yml')) + + const chains = [ + new EthereumChain, + new ConfluxChain + ] + + const specialTests = { + builtin: builtin, + keccak256: keccak256, + events: events, + } + + for (const chain of chains) { + console.log(chain.constructor.name.padEnd(37, '*')) + + // Special tests each have their own file, because they have results that + // need to be checked against non-constant values, or they look at event + // logs. + for (const t in specialTests) { + console.log(t.padEnd(30, '-')) + await specialTests[t].runTest(chain) + } + + // These are tests that can be described in the `tests.json` file. They + // either check whether a method call passes/reverts or the result of a + // method's return value against a constant expected value. + for (const t in tests) { + console.log(t.padEnd(30, '-')) + await runTest(chain, t, tests[t].calls, tests[t].constructorArgs); + } + } +} + +main() diff --git a/unittests/tests.yml b/unittests/tests.yml new file mode 100644 index 0000000..693efc2 --- /dev/null +++ b/unittests/tests.yml @@ -0,0 +1,103 @@ +address: + calls: + - args: [] + expectSuccess: true + name: init + - args: [] + expectValue: 0x000000000000000000000000000000000000efca + name: get + - args: ["0xd115bffabbdd893a6f7cea402e7338643ced44a6"] + expectSuccess: true + name: set + - args: [] + expectValue: 0xd115bffabbdd893a6f7cea402e7338643ced44a6 + name: get +asserts: + calls: + - args: [] + expectSuccess: true + name: f + - args: [] + expectSuccess: false + name: g + - args: [] + expectSuccess: false + name: h + - args: [] + expectSuccess: true + name: i + - args: [] + expectSuccess: false + name: j +constructor: + calls: + - args: [] + expectSuccess: true + name: get + constructorArgs: [100, 321] +constructor2: + calls: + - args: [] + expectSuccess: true + name: test_upper + - args: [] + expectValue: 9 + name: get_w + constructorArgs: [6, 7, 8, 9] +forloop: + calls: + - args: + - 3 + - 5 + expectSuccess: true + name: multiply + - args: + - 100 + - 5 + expectSuccess: true + name: multiply +layers1: + calls: + - args: [] + expectSuccess: true + name: f + constructorArgs: [] +match-int: + calls: + - args: [] + expectSuccess: true + name: f +struct: + calls: + - args: + - 0 + - 0 + expectSuccess: true + name: initialize + - args: [] + expectSuccess: false + name: hasOwner + - args: + - 5 + expectSuccess: false + name: hasSupply + - args: + - 5 + - 17 + expectSuccess: true + name: initialize + - args: + - 4 + expectSuccess: true + name: hasSupply + - args: + - 5 + expectSuccess: true + name: hasSupply + - args: + - 6 + expectSuccess: false + name: hasSupply + - args: [] + expectSuccess: true + name: hasOwner diff --git a/unittests/tethys.toml b/unittests/tethys.toml new file mode 100644 index 0000000..32866fa --- /dev/null +++ b/unittests/tethys.toml @@ -0,0 +1,458 @@ +# bootnodes is a list of nodes that a conflux node trusts, and will be used to sync the blockchain when a node starts. +# The value is a string divided by comma without space, and every entry is a node +# A node is identified by cfxnode://NODEID@PUBLICIP:PORT +# By default, no bootnodes are provided. What's provided here is a list of nodes that Conflux Team maintains across the world. + +# bootnodes="cfxnode://dc79bc70833e797ba41eff5bda67c0484abca4918ef38289b5f96acd3daa890eadc85d46fc71f250a8ac51b0c4ab70b3812b1ed3c8f10a9e996b6663be34f1f1@47.88.79.174:32323,cfxnode://28d3cdf07b7deb41bb52dee0a952fc599f46f6b89cc513ecfd1020d5a66e73e7cfe68543e64962aefbcae7123a6c390a43144f5900f0bc181c3c89ffdf9ff81b@39.97.225.254:32323,cfxnode://9991bd3f5d0e614a3fcc8640fdfcbefbc0e95de7fa68baff4cb95f8614fa162b080a497bca5037196920bf68ed2554605f29b38ba2390b4bc8de91dac91eab34@35.177.114.1:32323,cfxnode://f94343e4c806b2968c5e4bf4cbc49736d04af03fab4b797bc11aea2af2cb23d706d1d9c5dfae430a2df1d7fe6a6a988aff43c50898dc087161e51fa69d603997@13.69.186.42:32323,cfxnode://ce6c447f1e6f8e43e07f9ee8d5b49180663ad934f7fffa0db654e69522a234628f966fc8ea0285c4357285885f188804ae09b5303a6c8e627149c2a41d5156a3@52.68.192.218:32323,cfxnode://012d0f7e59f62220e2a90e458cf0d65e5690d09dad59ce05f03f5878a7142bef9f412decdbefa7716e8331e94d68f05c2ce943db4ffa5440e496f2130d3feb50@23.96.108.96:32323,cfxnode://4eb526348481292722188664543d3dc80a5f2a35b578b2d72d54293ccc400fa87efb69e728dc56ef924be708ec8b33fa3648eca2a81e9e95f44cd0b3252fea77@34.201.56.239:32323,cfxnode://72d0736cc9fffc21306f097b8ce5099f62d72ec05bd94ceff5bd6ec6783801f2f7ad17a16f57499243925ed9633654081d3b4cb95bab7474144e92ffe39c9cc4@34.216.73.138:32323,cfxnode://7e2e4918d3aff819afdb8782c13544ea63193d82d9529dfbab3efb101754b322fc161c771a784e1b0420da8f78dbb127fbac24d1d626b634b462542ad8953bd7@52.231.28.50:32323,cfxnode://448839f2900f4a22ce611bd66a4fc93f8fa02a4b185679ba89078c0bf9c6c9328d3df77c4c8451fca12f2a8daab53b8f38762c14d6f24ba6897a9ddd79988474@18.228.10.237:32323,cfxnode://54e1d46b03527d79986e3c884e6ef6cec09cfc548f7ad20d8f0c996396cbe04bead6f689822eae2ab78b08e2be360371679d94f41fc75645ae166c557c3cd7e4@15.185.81.4:32323,cfxnode://5ec498fd7c8ff5389024f6a6e80ed75539c89dda8e655cae48c8ae883590acb940d856a601e7f788d5a2cf417eb5dee0fa9ae6c0a2ac8e6d8253cb7ac986a651@18.163.111.230:32323,cfxnode://8949669b26e015acd6c3e1ba5f87e2a7242a8611eec224428d5553005e45b4c6b2e352721be6334a445340441c8d6f8dfeab20472fbb0ce9733c293f0c1c781c@13.67.73.51:32323,cfxnode://3a25050e4d896b22a265170a8795ae5b22c48822a81c0c4a43fd3856f979b03c20abadaec90ffd083abac278cfc38087ef6902b1825b7f7c2fcc639f9e931bfb@13.209.20.158:32323,cfxnode://af63f3129791ab9afb1f74aeb0c9cf5931f8fb18f905f783c4bc7dff0421bfc83acc56ff41e3904bf0ad0477fb13d06cacbb8f337dcab10b9ae7efe787c02809@13.112.176.199:32323,cfxnode://c2b7613cdece4dd73f5107ab77c5c30663ac67366177bd4d4349b882e64cd6f62dd379d31e534b168421a76d3e84b9213894e58687b8c659718ce97d7a2148e7@50.18.129.125:32323,cfxnode://4c0a46dee4e1d2db9e0e1ce935f41edccfe0602efa7823713d93aea55bb5174ca957fcd27e1aa1b4d8d020565183ebc53674a73eb800ecc741d7aa853ab845eb@18.197.60.158:32323,cfxnode://4ff47d5a384f945628530a5015e766855f4085655fcb3bb1bbaa4048941cdac30924b2ba5b4a42445748bc64cc4fc04375e9a6f8a3a9f5833ef7b61c155a5176@13.94.59.99:32323,cfxnode://3ec541c53224053294900568366e2c89851ff83f23aa45c8cafd3eb250cf1202afdf0bb62966e013176861c9165b6871e3cc522011074b20be863a43951af91c@35.178.198.71:32323,cfxnode://f31e7d2fdcffa1b25a6a6c9c1357a6804f8f426caf81ccda16291200055c46affdbfbfebebcca996ea7861631c9a0b11d70f07afeed71efa0a4f12aa8acfb55e@54.255.160.38:32323,cfxnode://d3c11b60ff63c959db2aa5e2946fea7a12fb8967faff00e9a233ed6973dff13ac78429d77fab7d49ea0927362c367b648f9ba0cd9db3e65748f5647820aaf7a9@35.183.19.30:32323,cfxnode://49ff58db6b4c5f92c2145e69ea0625134cbe35885f0e5979191ba9c67e4c9374234ed7fbeb65f82d4d197568110a4f100f078bfbac896f391b362bec77be19ea@212.64.63.38:32323,cfxnode://97497107e94ac463f6bad526d74e0058d46154e97cbf758edaf3d360e2f3347ae5946ca337eb0d201df8f625e7ae5bfc32e8394d2ce37bd2dc35fa5a4bcecd01@8.131.69.64:32323,cfxnode://c22ad0736f5cc2cc3b11ce5f43345213c2e44994dfaa5e3b0cebe8bd9c78cc52e1a22949ff5953aea80476f648e42b502172e04629c172f4400a0af4caf97efb@8.131.68.192:32323,cfxnode://04cee414977f68a0c2f0215199dde4ec1c27350e447ea855ce000054336f4ccb1c43f0c5ebe8172ad51c7d7b88ac98c037a85ae949e79734449ac38a23fd1d60@212.64.62.252:32323,cfxnode://f1750b818c5828fc5f22667f4b45d4a39b17a1cf40f71ae8f74b6195485a93bf16892a3785bda36132ebae64b83b91b216eaccb7a02185a01f37c7ad89c513ad@101.132.133.254:32323,cfxnode://72a21ec3d2d7c5545b4a46656eaca6ab4ec3ac85628f665bd205e7c52273d345d1583efface277b967fca963a81fbf8b7a81ae97f0a46234cd5fb34853c95fd2@47.101.39.91:32323,cfxnode://b7aeba1f1b2b3e5dfdc7ac93df4281a440ccbdc89894444e094f15242ffa1578d90f9fd447b899be89a57542616e26a82180bd2bfb3b81f82a4dffdfe180f44e@8.210.110.149:32323,cfxnode://07faaf8be8bff4243b496363fb02bd0a21be97e291febcd9aabb29996de90d0a10065f3383beff09f05cb0bdfaa9655d90550c8abcbf97be0658ce6efd8f9b64@47.254.67.249:32323" + +# Some preset develepment configurations. +# It should not be set in production environment. +# +# For both `test` and `dev` modes, we will +# * Set initial difficulty to 4 +# * Allow calling test and debug rpc from public port +# +# `test` mode is for Conflux testing and debugging, we will +# * Add latency to peer connections +# * Skip handshake encryption check +# * Skip header timestamp verification +# * Handle NewBlockHash even in catch-up mode +# * Allow data propagation test +# * Allow setting genesis accounts and generate tx from secrets +# +# `dev` mode is for users to run a single node that automatically +# generates blocks with fixed intervals +# * Open port 12535 for ws rpc if `jsonrpc_ws_port` is not provided. +# * Open port 12536 for tcp rpc if `jsonrpc_tcp_port` is not provided. +# * Open port 12537 for http rpc if `jsonrpc_http_port` is not provided. +# * generate blocks automatically without PoW +# * Skip catch-up mode even there is no peer +# +# mode = "" + +# If you want to setup a single node running Conflux for development. You should +# COMMENT the bootnodes setting and you should use the following parameters: +# +mode = "dev" + +# Note that ``dev_block_interval_ms'' controls the mining rate in the dev mode. +# +dev_block_interval_ms = 250 + +# ----------------- Mining Configuration ----------------- + +# `mining_author` is the address to receive mining rewards. +# If set, `mining_type` will be "stratum" by default. +# The value is a 40-digit hex string. +# By default, the value is not set. +# +# mining_author="1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + +# `mining_type` controls whether the mining process goes through the +# stratum protocol, uses CPU-mining, or disable mining. +# Possible values are "stratum", "cpu", and "disable". +# The default value is "stratum" if `mining_author` is set. +# If the value is set and not "disable", `mining_author` must be set. +# +# mining_type = "stratum" + +# Listen address for stratum +# +# stratum_listen_address = "127.0.0.1" + +# Port for stratum. +# +# stratum_port = 32525 + +# Window size for PoW manager +# +# pow_problem_window_size = 1 + +# Secret key for stratum. +# The value is 64-digit hex string. +# If not set, the RPC subscription will not check the authorization. +# +# stratum_secret = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + +# -------------- Log-related Configuration ------------- + +# `log_conf` the path of the log4rs configuration file. The configuration in the file will overwrite the value set by `log_level`. +# By default, the value is not set. +# +log_conf="log.yaml" + +# `log_file` is the path of the log file" +# If not set, the log will only be printed to stdout, and not persisted to files. +# By default, the value is not set. +# +# log_file="conflux.log" + +# `log_level` is the printed log level. +# The value should be one of "error", "warn", "info", "debug", "trace", "off" +# +# log_level="info" + +# -------------- Network Configuration ------------- + +# `public_address` is the address of this node used for other nodes to connect to. +# If not set, the process will try to find out the public IP with best effort, and use `tcp_port` as public port. +# However, it's HIGHLY RECOMMENDED to set the value manually, especially for machines with IP translated by NAT. +# +# public_address="1.1.1.1" + +# `tcp_port` is the TCP port that the process listens for P2P messages. The default is 32323. +# +# tcp_port=32323 + +# `public_tcp_port` is the public TCP port that other nodes should connect to. It might be different from +# the tcp_port in case the machine is behind a NAT. The default is as same as `tcp_port`. +# +# public_tcp_port=32323 + +# `udp_port` is the UDP port used for node discovery. +# If not set, it will be the same as `port`. +# +# udp_port=32323 + +# `jsonrpc_http_keep_alive` is used to control whether to set KeepAlive for rpc HTTP connections. +# +# jsonrpc_http_keep_alive=false + +# `jsonrpc_cors` is used to control the rpc domain validation policies. +# The value should be "none", "all", or a list string split by commas without space. +# If not set, domain validation is disabled. +# By default, the values are not set. +# +# jsonrpc_cors="all" + +# The following parameters are the ports for the node to provide rpc service. If not set, +# the node will not start rpc services. By default, the `jsonrpc_local_http_port` is set, +# so as to support the Conflux CLI subcommands. What's provided here is the recommended +# value if you want to start rpc services for other front-end applications. +# Note that to serve transaction-related RPCs, `persist_tx_index` should also be set to `true` or +# the node will only be able to handle very recent transactions. +# +# jsonrpc_ws_port=12535 +# jsonrpc_tcp_port=12536 +# jsonrpc_http_port=12537 +# jsonrpc_local_tcp_port=12538 +jsonrpc_local_http_port=12539 + +# --------------- Performance-related Network Parameters ---------------------- + +# Timeout for block-related requests (GetBlock, GetCmpctBlock, GetBlockTxn) +# +# blocks_request_timeout_ms = 20_000 + +# Time interval to check timeout requests periodically. +# +# check_request_period_ms=5000 + +# Chunk size for snapshot retrieval +# +# chunk_size_byte = 4194304 + +# Control whether to demote peers to unstrusted +# +# demote_peer_for_timeout = false + +# Maximum network queue size. When reached, the queue will refuse any new data. +# The unit is MB. +# +# egress_queue_capacity = 256 + +# Minimum queue size for throttling in manner of ratio. +# The unit is MB. +# +# egress_min_throttle = 10 + +# Maximum queue size for throttling in manner of ratio. +# The unit is MB. +# +# egress_max_throttle = 10 + +# Time interval to to garbage-collect not block-graph-ready blocks periodically. +# +# expire_block_gc_period_s = 900 + +# Timeout for header-related requests (GetBlockHeaders) +# +# headers_request_timeout_ms=10_000 + +# Time interval to broadcast Status as heartbeat periodically +# +# heartbeat_period_interval_ms = 30_000 + +# Time to maintain transaction digests inflight status. +# +# inflight_pending_tx_index_maintain_timeout_ms = 30_000 + +# Maximum number of timeout allowed in `timeout_observing_period_s`. +# If the max is reached, the peer will be disconnected. +# `demote_peer_for_timeout` controls if the peer will be demoted in this case. +# +# max_allowed_timeout_in_observing_period = 10 + +# Maximum number of peers to download state chunks from. +# +# max_download_state_peers = 8 + +# Maximum number of handshaking sessions at the same time. +# +# max_handshakes = 64 + +# Maximum number of incoming connections. +# +# max_incoming_peers = 64 + +# Maximum number of outgoing connections. +# +# max_outgoing_peers = 16 + +# Maximum number of outgoing connections to archive nodes. 0 represents +# not required to connect to archive nodes. E.g. light node or full node +# need not to connect to archive nodes. +# +# max_outgoing_peers_archive = 0 + +# Maximum number of inflight requests for each peer. +# If the max is reached, requests will be buffered until inflight requests are responded or timeout. +# +# max_inflight_request_count = 64 + +# Maximum number of peers to broadcast transaction digests. +# +# max_peers_tx_propagation = 128 + +# Maximum cached received block size waiting to be processed. +# +# max_unprocessed_block_size_mb = 128 + +# Minimum number of peers to broadcast transaction digests. +# +# min_peers_tx_propagation = 8 + +# The time to maintain received transactions to avoid duplicated requests. +# +# received_tx_index_maintain_timeout_ms = 300_000 + +# Whether to request blocks with public key during catch-up to avoid recovering +# the public keys for transactions. +# +# request_block_with_public = false + +# Time interval to broadcast transaction digests periodically. +# +# send_tx_period_ms = 1300 + +# Timeout for requesting snapshot candidate. +# +# snapshot_candidate_request_timeout_ms = 10_000 + +# Timeout for requesting snapshot chunks. +# +# snapshot_chunk_request_timeout_ms = 30_000 + +# Timeout for requesting snapshot manifests. +# +# snapshot_manifest_request_timeout_ms = 30_000 + +# `throttling_conf` is configuration file in TOML format to throttle RPCs, P2P messages. +# Throttling is enabled only when the parameter specified. +# +# throttling_conf="throttling.toml" + +# The time period to observe if a peers has too many timeouts. +# +# timeout_observing_period_s = 600 + +# Timeout for transaction requests. +# +# transaction_request_timeout_ms = 30_000 + +# Time to maintain information of sent-out transactions for answering requests. +# +# tx_maintained_for_peer_timeout_ms = 600_000 + +# --------------- Peer Management Parameters ------------- + +# Timeout duration for refreshing discovery protocol when there are NOT enough outgoing connections. +# +# discovery_fast_refresh_timeout_ms = 10_000 + +# Timeout duration for initiating peer connection management. +# +# discovery_housekeeping_timeout_ms = 1_000 + +# Period between consecutive rounds of the same current discovery process. +# +# discovery_round_timeout_ms = 500 + +# `enable_discovery` is used to control whether the node will ask its neighbors for new peers +# and whether it will respond to other nodes' discovery requests. +# +# enable_discovery=true + +# `netconf_dir` is the directory to store network related persistent data, including `net_key`, +# a list of trusted nodes and a list of untrusted nodes. +# +# netconf_dir="./net_config" + +# `net_key` is the 256-bit private key to generate a unique node id for this node. +# The value is a 64-digit hex string. +# If not set, the node will try to read from the file "key" under the directory `netconf_dir`. +# If the file is not found, the node will generate a random key. +# By default, the value is not set. +# If a node is restarted, it's suggested to keep the key unchanged. +# +# net_key="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + +# Timeout duration for persisting node table. +# +# node_table_timeout_s = 300 + +# Connection lifetime threshold for promotion. +# +# node_table_promotion_timeout_s = 259200 + + +# `session_ip_limits` limits the number of TCP connections per IP address or subnet for security consideration. +# Its format is "n1,n2,n3,n4", where n1 is the quota of TCP connections for a single IP address, and n2/n3/n4 +# are the quotas for subnet a/b/c. The default value is "1,8,4,2", which means: +# 1) Only 1 TCP connection allowed for a single IP address. +# 2) 8 TCP connections allowd for subnet a, e.g. 192.xxx.xxx.xxx/8 +# 3) 4 TCP connections allowd for subnet b, e.g. 192.168.xxx.xxx/16 +# 4) 2 TCP connections allowd for subnet c, e.g. 192.169.0.xxx/24 +# Note, 0 represents unlimited. +# +# session_ip_limits="1,8,4,2" + +# `subnet_quota` limits the number of nodes for a subnet B (e.g. 192.168.xxx.xxx/16) stored in database. +# Nodes in database are used to establish outgoing TCP connections for P2P communications. +# Note, 0 represents unlimited. +# +# subnet_quota=32 + +# ---------------- Transaction Cache Parameters ----------------- + +# Whether to persist transaction indices. +# This only needs to be enabled if you want to reliably answer transaction-related RPCs. +# +# persist_tx_index = false + +# Time to keep transactions in in-memory transaction cache. +# +# tx_cache_index_maintain_timeout_ms = 300_000 + +# Maximum number of transactions allowed in the transaction pool. +# +# tx_pool_size = 500_000 + +# Minimum allowed transaction gas price in the transaction pool. +# +# tx_pool_min_tx_gas_price = 1 + +# ------------------ Storage Parameters ---------------------- + +# The number of additional snapshot before the current stable checkpoint that we will maintain. +# If it's 0, all snapshot before stable genesis will be deleted and the states are unavailable. +# +# additional_maintained_snapshot_count = 0 + +# Time interval to evict old data from in-memory data cache. +# +# block_cache_gc_period_ms = 5_000 + +# Database type to store block-related data. +# Supported: rocksdb, sqlite. +# +# block_db_type = "rocksdb" + +# The root directory of all data (block data, state data, log files, node database). +# +# conflux_data_dir = "./" + +# The directory to store block-related data. +# +# block_db_dir = "./blockchain_db" + +# Maximum size of cached ledger data (block, receipts, e.t.c.) +# The unit is MB. +# +# ledger_cache_size = 1024 + +# Rocksdb cache size. +# Only applies if `block_db_type = "rocksdb"`. +# +# rocksdb_cache_size = 128 + +# Rocksdb compaction file path. +# Only applies if `block_db_type = "rocksdb"`. +# If not set, compaction configuration will be set automatically by rocksdb. +# +# rocksdb_compaction_profile = "./compact_file.conf" + +# State storage parameters. +# Refer to the documentation for details. +# +# storage_delta_mpts_cache_recent_lfu_factor=4.0 +# storage_delta_mpts_cache_size=20000000 +# storage_delta_mpts_cache_start_size=1000000 +# storage_delta_mpts_node_map_vec_size=80000000 +# storage_delta_mpts_slab_idle_size=200000 + +# ------------------ Light Node Parameters ---------------------- + +# Header sync parameters. +# ln_header_request_batch_size = 30 +# ln_header_request_timeout_sec = 2 +# ln_max_headers_in_flight = 1000 + +# Epoch sync parameters. +# ln_epoch_request_batch_size = 100 +# ln_epoch_request_timeout_sec = 2 +# ln_max_parallel_epochs_to_request = 10 +# ln_num_epochs_to_request = 200 +# ln_num_waiting_headers_threshold = 1000 + +# -------------------- Others ------------------- + +# Time (in milliseconds) after which accounts are re-read from disk. +# +# account_provider_refresh_time_ms = 1000 + +# Whether to allow execution without deferring if the execution thread is idle. +# +# enable_optimistic_execution = true + +# Maximum number of blocks whose timestamp is in the near future is maintained in memory. +# +# future_block_buffer_capacity = 32768 + +# Maximum number of log entries returned from cfx_getLogs. +# If not set, cfx_getLogs will not limit the number of logs returned. +# +# get_logs_filter_max_limit = 10 + +# Epoch batch size used in log filtering. +# Larger batch sizes may improve performance but might also prevent consensus from making progress under high RPC load. +# +# get_logs_epoch_batch_size = 32 + +# The maximal allowed number of epochs between `from_epoch` and `to_epoch` in the filter to call `cfx_getLogs`. +# If not set, there is no limit on the gap. +# By default it is not set. +# +# get_logs_filter_max_epoch_range = 10000 + +# Maximum number of transactions allowed for peers to send to a catch-up node. +# +# max_trans_count_received_in_catch_up = 60_000 + +# The chain_id of conflux network +# 1 for testnet +# 1029 for Tethys +# +chain_id = 1029 + +genesis_secrets = "genesis_secrets.txt" diff --git a/unittests/tsconfig.json b/unittests/tsconfig.json new file mode 100644 index 0000000..45e6ee4 --- /dev/null +++ b/unittests/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions" : { + "target": "esnext", + "module": "commonjs", + "outDir": "build", + "watch" : false, + "resolveJsonModule": true, + "esModuleInterop": true, + "skipLibCheck": true + } +} diff --git a/unittests/utils.ts b/unittests/utils.ts new file mode 100644 index 0000000..ac9e306 --- /dev/null +++ b/unittests/utils.ts @@ -0,0 +1,16 @@ +export function getJsonFilename(filename: string): string { + if (!filename.startsWith('./')) + filename = './' + filename + if (!filename.endsWith('.json')) + filename = filename + '.json' + return filename +} + + +export function padName(name: string): string { + return (" " + name + ":").padEnd(30, ' ') +} + +export function printTest(name: string, success: boolean) { + console.log(padName(name), (success? "pass✅" : "fail❌")); +}