From 61aab4aafe02e4a40fa91145c5d0182123a11606 Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Mon, 2 Dec 2019 15:20:31 -0800 Subject: [PATCH] feat(validator): elections powered by etcd leases (#31) * feat(validator): elections powered by etcd leases Signed-off-by: Peter Somogyvari * docs: etcd leases, state and deployment diagram Signed-off-by: Peter Somogyvari * fix(quorum): docker-compose network name typo It was copy-pasted from the fabric docker-compose and so the network names were incorrectly referencing the fabric network, not the quorum. Signed-off-by: Peter Somogyvari * refactor(validator): change getter to method The getter that was changed: isCurrentNodeLeader Signed-off-by: Peter Somogyvari * refactor(validator): Object.assign -> line by line TODO(peter.somogyvari): Once leader election has enough test coverage, get rid of these property assignments and just use the this.leaderNodeInfo.networkInfo object directly everywhere. Signed-off-by: Peter Somogyvari * fix(test/validator): isCurrentNodeLeader syntax Signed-off-by: Peter Somogyvari * fix(examples,tools): use local npm package The examples were hardcoding GitHub branch references which is a moving target and makes it error prone in certain situations to have the intended code running for local tests/CI. Solved it with a pre-install npm script that runs npm pack in the root directory of the project creating an installable tarball of the latest source code that's checked out at the current moment. This strongly ties the examples of any given revision to the exact source code of BIF from that revision as well, guaranteeing that whoever/wherever does an npm install inside the examples will get the current source code of that revision packaged up as an npm dependency. that they are committed with Signed-off-by: Peter Somogyvari * fix(example/quorum): container resource usage Reverting an attempted fix that was breaking the CI. The attempted fix was to introduce resource constraints on the quorum containers (CPU, RAM usage). This worked in the sense that on a smaller dev laptop launching the quorum network didn't cause OOM, but on the other hand containers got stuck in 'unhealthy' status on CI so overall the fix didn't pan out. Also: Performance optimization is added by reducing logging verbosity within the quorum containers and the geth syncmode is being changed from 'full' to 'fast' (the default) which does not verify each block one by one upon initialization. Signed-off-by: Peter Somogyvari * fix(examples/corda): adds etcd to docker-compose This was forgotten from the original commit which only updated fabrid and quorum Signed-off-by: Peter Somogyvari * docs(tools): add docs for create local npm packge Signed-off-by: Peter Somogyvari --- .eslintignore | 1 + .gitignore | 1 + .npmignore | 8 + .../leader-election/deployment-diagram.puml | 46 + .../leader-election/etcd-leases.md | 22 + .../state-diagram-validator.puml | 25 + examples/simple-asset-transfer/app.js | 7 +- .../federations/docker-compose-corda.yml | 83 +- .../federations/docker-compose-fabric.yml | 79 +- .../federations/docker-compose-quorum.yml | 83 +- .../simple-asset-transfer/package-lock.json | 1220 +++++++++++++---- examples/simple-asset-transfer/package.json | 38 +- .../quorum/platform/docker-compose.yml | 2 +- package-lock.json | 662 ++++++++- package.json | 2 + src/Validator.js | 194 +-- tests/client.js | 5 + tests/validator.js | 78 +- tools/create-local-npm-package.js | 73 + 19 files changed, 2154 insertions(+), 475 deletions(-) create mode 100644 .npmignore create mode 100644 docs/architecture/leader-election/deployment-diagram.puml create mode 100644 docs/architecture/leader-election/etcd-leases.md create mode 100644 docs/architecture/leader-election/state-diagram-validator.puml create mode 100755 tools/create-local-npm-package.js diff --git a/.eslintignore b/.eslintignore index f05b1f265d..e998250561 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ node_modules test +.tmp/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6203d7b5ac..8ac14f252e 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ typings/ examples/simple-asset-transfer/fabric/**/hfc-key-store/ bin/ +.tmp/ \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000000..cecf93dc7f --- /dev/null +++ b/.npmignore @@ -0,0 +1,8 @@ +.github/ +.tmp/ +.vscode/ +bin/ +docs/ +examples/ +testes/ +tools/ \ No newline at end of file diff --git a/docs/architecture/leader-election/deployment-diagram.puml b/docs/architecture/leader-election/deployment-diagram.puml new file mode 100644 index 0000000000..3a51113460 --- /dev/null +++ b/docs/architecture/leader-election/deployment-diagram.puml @@ -0,0 +1,46 @@ +@startuml leader-election-etcd-leases-deployment-caption +!include +!include +!include + +center header +Hyperledger Blockchain Integration Framework + +endheader + +title + Leader Election Deployment Diagram + +end title + +center footer Hyperledger Blockchain Integration Framework, 2019 + +frame BIF { + + frame Etcd_Cluster as ec { + OFF_DATABASE_SERVER(etcd1,"Etcd 1") + OFF_DATABASE_SERVER(etcd2,"Etcd 2") + OFF_DATABASE_SERVER(etcdn,"Etcd N") + } + + frame Validator_Cluster as vc { + OFF_APPLICATION_SERVER(bvn1,"Validator 1") + OFF_APPLICATION_SERVER(bvn2,"Validator 2") + OFF_APPLICATION_SERVER(bvnn,"Validator N") + } + +} + +bvn2 <~~> bvnn +bvn1 <~> bvn2 +bvn1 <~> bvnn + +etcd1 <~~> etcd2 +etcd1 <~> etcdn +etcd2 <~> etcdn + +bvn1 <=[#blue]=> ec +bvn2 <=[#blue]=> ec +bvnn <=[#blue]=> ec + +@enduml diff --git a/docs/architecture/leader-election/etcd-leases.md b/docs/architecture/leader-election/etcd-leases.md new file mode 100644 index 0000000000..d400baaebe --- /dev/null +++ b/docs/architecture/leader-election/etcd-leases.md @@ -0,0 +1,22 @@ +# Leader Election via Etcd's Distributed Synchronization Primitives + +## Summary + +Validators nodes self-elect a leader by leveraging the Etcd API's `watch` and `lease` features. BIF depends on Etcd API version 3, but other than that it's able to work with any Etcd cluster or single node configuration as long as connectivity is achievable. + +At startup, each node attempts to make themselves leader, which will only succeed if there is no current leader. + +If a validator node fails to become leader, it starts acting as a follower. +The identity of the leader node is stored under a specific key in Etcd on which the leader holds the lease. + +Followers are watching the key storing the leaders identity and react to changes as soon as the change is detected, there is no polling that would waste network/compute resources. + +Stability of the leader election is guaranteed by the Raft algorithm that Etcd uses under the hood. + +## Deployment Diagram + +![leader-election-etcd-leases-deployment-caption](https://www.plantuml.com/plantuml/png/0/bPDHIyCm58NVyokkyqN1CbUVX6siSnqEn8cJlOYCBBtJOfgKD9qCqT_kJLPhf-Am5Cev-UxDIT8C2ikDBJC94dc29a29mgPQ1MX54f1PO14ac4kzoL3PGF3S3RE3L0bP9WXTM-OyCMTjeRDCgtvZHAzMgS3s3CqQJT5EkELBwhSelF47oVDSfeAxYMgO2PeU3JpvdEnoawEHc3oIDPHQF8iddYgO4FDeV2MC3S_mHPjdnb0bLHspgPN80Bfb_yfR45TBXb6zJ1YbdDfatNRPzzMmBViCiTBQVVuJuWJ2qyuvOojdm70oXbT6CROofirUNCYoS5rv0IXe5EYPZiUBKNGN3QDPl9Z5j_FuziYTJEUavMgWqph-amihBjp3gOgxzjpRLx8vboaTd3RDUEjclEZcvcfo4TrDfjUV7PThHG7hqfsKl-DX4m_tugg9rvdfTQsW-_xU1qSvsI7fLRYZ51shsySjxBUgDhPQUHqsTDMWTt-ub2K-zCWNrOm_FFNTOmFwZUYYVG00 "leader-election-etcd-leases-deployment-caption") + +## Validator Node State Diagram + +![state-diagram-validator](https://www.plantuml.com/plantuml/png/0/XL9DRy8m3BtdL_WsQLgrZziGGkm3j4re5v1sM7R86WCHgLsbPen_FxUbG4yxrNrvp-_PoRWIbsHRHD12CFF1hP8hiXyNWtV2oHW94X4i3RUZ6JgF2IOHSmbCCAyryDngXjVRaIMpP1RbM7hPbvWY-fN-FKRED_dQ1O9N4bHwev-g37USDbTmTtDxRypdvHTasQXkd0IzENmRxCcHhpDXXmxWdJs-pQ5Cd6DL6NEam00UHB0efG9Xu6zHQqlgIm9g7D5LQ8cNC97SmmRtffrj07DKJOUgs184kQY0Trfu95t7tamvHjxLz0yd-HfRXQLM0Xvr1KKWjOXDMzKVjMSfTQfJfoQJIYdeu1qCvuDtdCLY1lXRXeI7rF-nUexTe2shMOaQddEKj6ZoE-b5wUETTHyrfxevqXirPepazOtz0G00 "state-diagram-validator") \ No newline at end of file diff --git a/docs/architecture/leader-election/state-diagram-validator.puml b/docs/architecture/leader-election/state-diagram-validator.puml new file mode 100644 index 0000000000..598cf0ac09 --- /dev/null +++ b/docs/architecture/leader-election/state-diagram-validator.puml @@ -0,0 +1,25 @@ +@startuml state-diagram-validator + +title \nLeader Election State Diagram\n +footer \nHyperledger Blockchain Integration Framework, 2019 + +[*] --> Started +Started --> Candidate +Started: NodeJS process + +Candidate : Attempts to obtain\ngrant on lease\nof Etcd key +Leader: Sets Etcd key to\n it's own identity +Follower: Watches Etcd\nkey to determine\nleader's identity + +Candidate -> Follower: lease denied +Follower -> Candidate: lease TTL expire +Leader -> Candidate: lease TTL expire +Candidate -> Leader: lease granted + +Candidate --> Terminated +Follower --> Terminated +Leader --> Terminated + +Terminated --> [*] + +@enduml \ No newline at end of file diff --git a/examples/simple-asset-transfer/app.js b/examples/simple-asset-transfer/app.js index 19915c55fd..d04e86b2cc 100755 --- a/examples/simple-asset-transfer/app.js +++ b/examples/simple-asset-transfer/app.js @@ -1,4 +1,4 @@ -const Validator = require(`@hyperledger-labs/blockchain-integration-framework`).Validator; +const { Validator } = require(`@hyperledger-labs/blockchain-integration-framework`); const { genKeyFile } = require(`@hyperledger-labs/blockchain-integration-framework`).cryptoUtils; const ConnectorFabric = require(`./fabric/connector`); const ConnectorQuorum = require(`./quorum/connector`); @@ -7,14 +7,11 @@ const ConnectorCorda = require(`./corda/connector`); (async () => { const keypair = await genKeyFile(`/federation/keypair`); const validatorOptions = { + etcdHosts: process.env.ETCD_HOSTS.split(','), clientRepAddr: process.env.CLIENT_REP_ADDR, pubAddr: process.env.PUB_ADDR, repAddr: process.env.REP_ADDR, - leaderPubAddr: process.env.LEAD_PUB_ADDR, - leaderRepAddr: process.env.LEAD_REP_ADDR, - leaderClientRepAddr: process.env.LEAD_CLIENT_REP_ADDR, dlType: process.env.DLT_TYPE, - type: process.env.TYPE, pubKey: keypair.pk, privKey: keypair.sk, }; diff --git a/examples/simple-asset-transfer/federations/docker-compose-corda.yml b/examples/simple-asset-transfer/federations/docker-compose-corda.yml index 4618f99464..a92ff37cbe 100644 --- a/examples/simple-asset-transfer/federations/docker-compose-corda.yml +++ b/examples/simple-asset-transfer/federations/docker-compose-corda.yml @@ -12,6 +12,7 @@ services: corda_validator1: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.21.0.2:7009" PUB_ADDR: "tcp://192.21.0.2:3009" REP_ADDR: "tcp://192.21.0.2:5009" @@ -19,7 +20,6 @@ services: USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" DLT_TYPE: "CORDA" - TYPE: "LEADER" mem_limit: 6g networks: corda-network: @@ -30,21 +30,22 @@ services: - "7009:7009" - "3009:3009" - "5009:5009" - + depends_on: + - etcd1 + - etcd2 + - etcd3 + corda_validator2: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.21.0.3:7010" PUB_ADDR: "tcp://192.21.0.3:3010" REP_ADDR: "tcp://192.21.0.3:5010" - LEAD_PUB_ADDR: "tcp://192.21.0.2:3009" - LEAD_REP_ADDR: "tcp://192.21.0.2:5009" USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" - LEAD_CLIENT_REP_ADDR: "tcp://192.21.0.2:7009" URL: "http://192.21.0.1:10052" DLT_TYPE: "CORDA" - TYPE: "FOLLOWER" mem_limit: 6g expose: - "10052" @@ -56,21 +57,20 @@ services: corda-network: ipv4_address: 192.21.0.3 depends_on: - - "corda_validator1" + - etcd1 + - etcd2 + - etcd3 corda_validator3: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.21.0.4:7011" PUB_ADDR: "tcp://192.21.0.4:3011" REP_ADDR: "tcp://192.21.0.4:5011" - LEAD_PUB_ADDR: "tcp://192.21.0.2:3009" - LEAD_REP_ADDR: "tcp://192.21.0.2:5009" USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" - LEAD_CLIENT_REP_ADDR: "tcp://192.21.0.2:7009" URL: "http://192.21.0.1:10053" - TYPE: "FOLLOWER" DLT_TYPE: "CORDA" mem_limit: 6g expose: @@ -83,22 +83,21 @@ services: corda-network: ipv4_address: 192.21.0.4 depends_on: - - "corda_validator1" + - etcd1 + - etcd2 + - etcd3 corda_validator4: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.21.0.5:7012" PUB_ADDR: "tcp://192.21.0.5:3012" REP_ADDR: "tcp://192.21.0.5:5012" - LEAD_PUB_ADDR: "tcp://192.21.0.2:3009" - LEAD_REP_ADDR: "tcp://192.21.0.2:5009" USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" - LEAD_CLIENT_REP_ADDR: "tcp://192.21.0.2:7009" URL: "http://192.21.0.1:10054" DLT_TYPE: "CORDA" - TYPE: "FOLLOWER" mem_limit: 6g expose: - "10054" @@ -110,4 +109,54 @@ services: corda-network: ipv4_address: 192.21.0.5 depends_on: - - "corda_validator1" + - etcd1 + - etcd2 + - etcd3 + + etcd1: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd1 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd1:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd1:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + corda-network: + ipv4_address: 192.21.0.50 + + etcd2: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd2 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd2:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd2:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + corda-network: + ipv4_address: 192.21.0.51 + + etcd3: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd3 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd3:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd3:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + corda-network: + ipv4_address: 192.21.0.52 diff --git a/examples/simple-asset-transfer/federations/docker-compose-fabric.yml b/examples/simple-asset-transfer/federations/docker-compose-fabric.yml index 87c2ca4a8b..e95bd4f821 100644 --- a/examples/simple-asset-transfer/federations/docker-compose-fabric.yml +++ b/examples/simple-asset-transfer/federations/docker-compose-fabric.yml @@ -12,6 +12,7 @@ services: fabric_validator1: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://172.20.0.5:7001" PUB_ADDR: "tcp://172.20.0.5:3001" REP_ADDR: "tcp://172.20.0.5:5001" @@ -33,18 +34,20 @@ services: - "3001:3001" - "5001:5001" - "9001:9001" - + depends_on: + - etcd1 + - etcd2 + - etcd3 + fabric_validator2: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://172.20.0.6:7002" PUB_ADDR: "tcp://172.20.0.6:3002" REP_ADDR: "tcp://172.20.0.6:5002" USER_NAME: "Mike" ORG_NAME: "Org1" - LEAD_PUB_ADDR: "tcp://172.20.0.5:3001" - LEAD_REP_ADDR: "tcp://172.20.0.5:5001" - LEAD_CLIENT_REP_ADDR: "tcp://172.20.0.5:7001" URL: "http://172.20.0.1:4000" PEER_NAME: "peer1.org1.example.com" DLT_TYPE: "FABRIC" @@ -62,19 +65,19 @@ services: fabric-network: ipv4_address: 172.20.0.6 depends_on: - - "fabric_validator1" + - etcd1 + - etcd2 + - etcd3 fabric_validator3: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://172.20.0.7:7003" PUB_ADDR: "tcp://172.20.0.7:3003" REP_ADDR: "tcp://172.20.0.7:5003" USER_NAME: "Hugo" ORG_NAME: "Org2" - LEAD_PUB_ADDR: "tcp://172.20.0.5:3001" - LEAD_REP_ADDR: "tcp://172.20.0.5:5001" - LEAD_CLIENT_REP_ADDR: "tcp://172.20.0.5:7001" URL: "http://172.20.0.1:4000" PEER_NAME: "peer0.org2.example.com" TYPE: "FOLLOWER" @@ -92,19 +95,19 @@ services: fabric-network: ipv4_address: 172.20.0.7 depends_on: - - "fabric_validator1" + - etcd1 + - etcd2 + - etcd3 fabric_validator4: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://172.20.0.8:7004" PUB_ADDR: "tcp://172.20.0.8:3004" REP_ADDR: "tcp://172.20.0.8:5004" USER_NAME: "Luca" ORG_NAME: "Org2" - LEAD_PUB_ADDR: "tcp://172.20.0.5:3001" - LEAD_REP_ADDR: "tcp://172.20.0.5:5001" - LEAD_CLIENT_REP_ADDR: "tcp://172.20.0.5:7001" URL: "http://172.20.0.1:4000" PEER_NAME: "peer1.org2.example.com" DLT_TYPE: "FABRIC" @@ -122,4 +125,54 @@ services: fabric-network: ipv4_address: 172.20.0.8 depends_on: - - "fabric_validator1" + - etcd1 + - etcd2 + - etcd3 + + etcd1: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd1 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd1:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd1:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + fabric-network: + ipv4_address: 172.20.0.50 + + etcd2: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd2 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd2:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd2:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + fabric-network: + ipv4_address: 172.20.0.51 + + etcd3: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd3 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd3:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd3:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + fabric-network: + ipv4_address: 172.20.0.52 diff --git a/examples/simple-asset-transfer/federations/docker-compose-quorum.yml b/examples/simple-asset-transfer/federations/docker-compose-quorum.yml index ea1a5d0fd3..2f2e2a1df8 100644 --- a/examples/simple-asset-transfer/federations/docker-compose-quorum.yml +++ b/examples/simple-asset-transfer/federations/docker-compose-quorum.yml @@ -12,6 +12,7 @@ services: quorum_validator1: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.20.0.2:7005" PUB_ADDR: "tcp://192.20.0.2:3005" REP_ADDR: "tcp://192.20.0.2:5005" @@ -19,7 +20,6 @@ services: USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" DLT_TYPE: "QUORUM" - TYPE: "LEADER" API_PORT: 9005 mem_limit: 6g networks: @@ -32,21 +32,22 @@ services: - "3005:3005" - "5005:5005" - "9005:9005" - + depends_on: + - etcd1 + - etcd2 + - etcd3 + quorum_validator2: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.20.0.3:7006" PUB_ADDR: "tcp://192.20.0.3:3006" REP_ADDR: "tcp://192.20.0.3:5006" - LEAD_PUB_ADDR: "tcp://192.20.0.2:3005" - LEAD_REP_ADDR: "tcp://192.20.0.2:5005" USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" - LEAD_CLIENT_REP_ADDR: "tcp://192.20.0.2:7005" URL: "http://192.20.0.1:5051" DLT_TYPE: "QUORUM" - TYPE: "FOLLOWER" API_PORT: 9006 mem_limit: 6g expose: @@ -60,21 +61,20 @@ services: quorum-network: ipv4_address: 192.20.0.3 depends_on: - - "quorum_validator1" + - etcd1 + - etcd2 + - etcd3 quorum_validator3: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.20.0.4:7007" PUB_ADDR: "tcp://192.20.0.4:3007" REP_ADDR: "tcp://192.20.0.4:5007" - LEAD_PUB_ADDR: "tcp://192.20.0.2:3005" - LEAD_REP_ADDR: "tcp://192.20.0.2:5005" USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" - LEAD_CLIENT_REP_ADDR: "tcp://192.20.0.2:7005" URL: "http://192.20.0.1:5052" - TYPE: "FOLLOWER" DLT_TYPE: "QUORUM" API_PORT: 9007 mem_limit: 6g @@ -89,22 +89,21 @@ services: quorum-network: ipv4_address: 192.20.0.4 depends_on: - - "quorum_validator1" + - etcd1 + - etcd2 + - etcd3 quorum_validator4: image: "federation/validator" environment: + ETCD_HOSTS: "http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" CLIENT_REP_ADDR: "tcp://192.20.0.5:7008" PUB_ADDR: "tcp://192.20.0.5:3008" REP_ADDR: "tcp://192.20.0.5:5008" - LEAD_PUB_ADDR: "tcp://192.20.0.2:3005" - LEAD_REP_ADDR: "tcp://192.20.0.2:5005" USER_NAME: "test" PASSWORD: "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3" - LEAD_CLIENT_REP_ADDR: "tcp://192.20.0.2:7005" URL: "http://192.20.0.1:5053" DLT_TYPE: "QUORUM" - TYPE: "FOLLOWER" API_PORT: 9008 mem_limit: 6g expose: @@ -118,4 +117,54 @@ services: quorum-network: ipv4_address: 192.20.0.5 depends_on: - - "quorum_validator1" + - etcd1 + - etcd2 + - etcd3 + + etcd1: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd1 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd1:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd1:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + quorum-network: + ipv4_address: 192.20.0.50 + + etcd2: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd2 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd2:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd2:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + quorum-network: + ipv4_address: 192.20.0.51 + + etcd3: + image: bitnami/etcd:3 + environment: + - ALLOW_NONE_AUTHENTICATION=yes + - ETCD_NAME=etcd3 + - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd3:2380 + - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 + - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 + - ETCD_ADVERTISE_CLIENT_URLS=http://etcd3:2379 + - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster + - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380 + - ETCD_INITIAL_CLUSTER_STATE=new + networks: + quorum-network: + ipv4_address: 192.20.0.52 diff --git a/examples/simple-asset-transfer/package-lock.json b/examples/simple-asset-transfer/package-lock.json index 950a259dd4..6376ee9fc0 100644 --- a/examples/simple-asset-transfer/package-lock.json +++ b/examples/simple-asset-transfer/package-lock.json @@ -4,10 +4,20 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@grpc/proto-loader": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.3.tgz", + "integrity": "sha512-8qvUtGg77G2ZT2HqdqYoM/OY97gQd/0crSG34xNmZ4ZOsv3aQT/FQV9QfZPazTGna6MIoyUd+u6AxsoZjJ/VMQ==", + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, "@hyperledger-labs/blockchain-integration-framework": { - "version": "git+https://github.com/hyperledger-labs/blockchain-integration-framework.git#d8b959023e6235089dbc333b24ada88c87b881a5", - "from": "git+https://github.com/hyperledger-labs/blockchain-integration-framework.git#fix/peter.somogyvari/make-ci-pass", + "version": "file:../../.tmp/hyperledger-labs-blockchain-integration-framework-dev.tgz", + "integrity": "sha512-CCqK+QlcReTgTd323KHhKnMlmVcG0leKa511IHr3BhFskUPjVcpmq8eSpZpBWi6ruZkyhuEcJGb3F8vxQbD8yw==", "requires": { + "etcd3": "0.2.13", "log4js": "^4.1.0", "prettier": "^1.16.4", "request": "^2.88.0", @@ -15,11 +25,66 @@ "secp256k1": "^3.6.2", "sha3": "^2.0.1", "truffle": "^5.0.14", - "web3": "1.2.2", - "web3-utils": "1.2.2", + "uuid": "3.3.3", + "web3": "1.2.4", + "web3-utils": "1.2.4", "zeromq": "^5.1.0" } }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -33,6 +98,14 @@ "defer-to-connect": "^1.0.1" } }, + "@types/bignumber.js": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz", + "integrity": "sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==", + "requires": { + "bignumber.js": "*" + } + }, "@types/bn.js": { "version": "4.11.5", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.5.tgz", @@ -41,10 +114,60 @@ "@types/node": "*" } }, + "@types/bytebuffer": { + "version": "5.0.40", + "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.40.tgz", + "integrity": "sha512-h48dyzZrPMz25K6Q4+NCwWaxwXany2FhQg/ErOcdZS1ZpsaDnDMZg8JYLMTGz7uvXKrcKGJUZJlZObyfgdaN9g==", + "requires": { + "@types/long": "*", + "@types/node": "*" + } + }, + "@types/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" + }, "@types/node": { - "version": "12.12.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.8.tgz", - "integrity": "sha512-XLla8N+iyfjvsa0KKV+BP/iGSoTmwxsu5Ci5sM33z9TjohF72DEz95iNvD6pPmemvbQgxAv/909G73gUn8QR7w==" + "version": "10.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", + "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==" + }, + "@web3-js/scrypt-shim": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", + "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", + "requires": { + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + } + }, + "@web3-js/websocket": { + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", + "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", + "requires": { + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "nan": "^2.14.0", + "typedarray-to-buffer": "^3.1.5", + "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=" + } + } }, "accepts": { "version": "1.3.7", @@ -195,6 +318,15 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -346,6 +478,11 @@ "tweetnacl": "^0.14.3" } }, + "bignumber.js": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-5.0.0.tgz", + "integrity": "sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg==" + }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -448,6 +585,12 @@ "color-convert": "^1.9.0" } }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -625,6 +768,21 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "~3" + }, + "dependencies": { + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + } + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -680,10 +838,9 @@ } }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, "camelcase-keys": { "version": "2.1.0", @@ -693,14 +850,6 @@ "requires": { "camelcase": "^2.0.0", "map-obj": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } } }, "capture-stack-trace": { @@ -786,7 +935,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", @@ -827,6 +975,11 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1065,8 +1218,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", @@ -1199,6 +1351,98 @@ "require-package-name": "^2.0.1", "walkdir": "0.0.11", "yargs": "^8.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + } } }, "depd": { @@ -1404,6 +1648,16 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "etcd3": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/etcd3/-/etcd3-0.2.13.tgz", + "integrity": "sha512-9zVnoebQRwOGivGT9/bFHQsjkcZttgzyDU50G1J27tdU76vmgp78YGOAEe9zzEjU6IEFa2KYYUg5AyMKDOp37A==", + "requires": { + "@grpc/proto-loader": "^0.5.1", + "bignumber.js": "^5.0.0", + "grpc": "^1.21.1" + } + }, "eth-ens-namehash": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", @@ -1494,11 +1748,6 @@ "xmlhttprequest": "1.8.0" }, "dependencies": { - "@types/node": { - "version": "10.17.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", - "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==" - }, "elliptic": { "version": "6.3.3", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", @@ -2097,6 +2346,435 @@ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, + "grpc": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.24.2.tgz", + "integrity": "sha512-EG3WH6AWMVvAiV15d+lr+K77HJ/KV/3FvMpjKjulXHbTwgDZkhkcWbwhxFAoTdxTkQvy0WFcO3Nog50QBbHZWw==", + "requires": { + "@types/bytebuffer": "^5.0.40", + "lodash.camelcase": "^4.3.0", + "lodash.clone": "^4.5.0", + "nan": "^2.13.2", + "node-pre-gyp": "^0.14.0", + "protobufjs": "^5.0.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.4", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.1.2", + "bundled": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true + }, + "npm-packlist": { + "version": "1.4.6", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true + }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "requires": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + } + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.7.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -2364,8 +3042,7 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { "version": "1.9.0", @@ -2688,7 +3365,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "^1.0.0" } @@ -2740,6 +3416,16 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -2798,6 +3484,11 @@ "streamroller": "^1.0.6" } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3343,6 +4034,11 @@ "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, "ora": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", @@ -3361,37 +4057,11 @@ "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=" }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } + "lcid": "^1.0.0" } }, "p-cancelable": { @@ -3731,6 +4401,26 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "protobufjs": { + "version": "6.8.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + } + }, "proxy-addr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", @@ -4109,14 +4799,6 @@ "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" }, - "scrypt-shim": { - "version": "github:web3-js/scrypt-shim#be5e616323a8b5e568788bf94d03c1b8410eac54", - "from": "github:web3-js/scrypt-shim", - "requires": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - } - }, "scryptsy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", @@ -4947,151 +5629,159 @@ "dev": true }, "web3": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.2.tgz", - "integrity": "sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.4.tgz", + "integrity": "sha512-xPXGe+w0x0t88Wj+s/dmAdASr3O9wmA9mpZRtixGZxmBexAF0MjfqYM+MS4tVl5s11hMTN3AZb8cDD4VLfC57A==", "requires": { "@types/node": "^12.6.1", - "web3-bzz": "1.2.2", - "web3-core": "1.2.2", - "web3-eth": "1.2.2", - "web3-eth-personal": "1.2.2", - "web3-net": "1.2.2", - "web3-shh": "1.2.2", - "web3-utils": "1.2.2" + "web3-bzz": "1.2.4", + "web3-core": "1.2.4", + "web3-eth": "1.2.4", + "web3-eth-personal": "1.2.4", + "web3-net": "1.2.4", + "web3-shh": "1.2.4", + "web3-utils": "1.2.4" + }, + "dependencies": { + "@types/node": { + "version": "12.12.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.10.tgz", + "integrity": "sha512-rhG2F0v4nNMqcPM4dMSne7R9iBzehUnARYbJq7G36CoczcqjNWuriAy6kd6quT30ISmfBhIRFVYDMSLrBASHNw==" + } } }, "web3-bzz": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.2.tgz", - "integrity": "sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.4.tgz", + "integrity": "sha512-MqhAo/+0iQSMBtt3/QI1rU83uvF08sYq8r25+OUZ+4VtihnYsmkkca+rdU0QbRyrXY2/yGIpI46PFdh0khD53A==", "requires": { "@types/node": "^10.12.18", "got": "9.6.0", "swarm-js": "0.1.39", "underscore": "1.9.1" - }, - "dependencies": { - "@types/node": { - "version": "10.17.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", - "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==" - } } }, "web3-core": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.2.tgz", - "integrity": "sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.4.tgz", + "integrity": "sha512-CHc27sMuET2cs1IKrkz7xzmTdMfZpYswe7f0HcuyneTwS1yTlTnHyqjAaTy0ZygAb/x4iaVox+Gvr4oSAqSI+A==", "requires": { + "@types/bignumber.js": "^5.0.0", "@types/bn.js": "^4.11.4", "@types/node": "^12.6.1", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-requestmanager": "1.2.2", - "web3-utils": "1.2.2" + "web3-core-helpers": "1.2.4", + "web3-core-method": "1.2.4", + "web3-core-requestmanager": "1.2.4", + "web3-utils": "1.2.4" + }, + "dependencies": { + "@types/node": { + "version": "12.12.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.10.tgz", + "integrity": "sha512-rhG2F0v4nNMqcPM4dMSne7R9iBzehUnARYbJq7G36CoczcqjNWuriAy6kd6quT30ISmfBhIRFVYDMSLrBASHNw==" + } } }, "web3-core-helpers": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz", - "integrity": "sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.4.tgz", + "integrity": "sha512-U7wbsK8IbZvF3B7S+QMSNP0tni/6VipnJkB0tZVEpHEIV2WWeBHYmZDnULWcsS/x/jn9yKhJlXIxWGsEAMkjiw==", "requires": { "underscore": "1.9.1", - "web3-eth-iban": "1.2.2", - "web3-utils": "1.2.2" + "web3-eth-iban": "1.2.4", + "web3-utils": "1.2.4" } }, "web3-core-method": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.2.tgz", - "integrity": "sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.4.tgz", + "integrity": "sha512-8p9kpL7di2qOVPWgcM08kb+yKom0rxRCMv6m/K+H+yLSxev9TgMbCgMSbPWAHlyiF3SJHw7APFKahK5Z+8XT5A==", "requires": { "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-utils": "1.2.2" + "web3-core-helpers": "1.2.4", + "web3-core-promievent": "1.2.4", + "web3-core-subscriptions": "1.2.4", + "web3-utils": "1.2.4" } }, "web3-core-promievent": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz", - "integrity": "sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.4.tgz", + "integrity": "sha512-gEUlm27DewUsfUgC3T8AxkKi8Ecx+e+ZCaunB7X4Qk3i9F4C+5PSMGguolrShZ7Zb6717k79Y86f3A00O0VAZw==", "requires": { "any-promise": "1.3.0", "eventemitter3": "3.1.2" } }, "web3-core-requestmanager": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz", - "integrity": "sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.4.tgz", + "integrity": "sha512-eZJDjyNTDtmSmzd3S488nR/SMJtNnn/GuwxnMh3AzYCqG3ZMfOylqTad2eYJPvc2PM5/Gj1wAMQcRpwOjjLuPg==", "requires": { "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "web3-providers-http": "1.2.2", - "web3-providers-ipc": "1.2.2", - "web3-providers-ws": "1.2.2" + "web3-core-helpers": "1.2.4", + "web3-providers-http": "1.2.4", + "web3-providers-ipc": "1.2.4", + "web3-providers-ws": "1.2.4" } }, "web3-core-subscriptions": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz", - "integrity": "sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.4.tgz", + "integrity": "sha512-3D607J2M8ymY9V+/WZq4MLlBulwCkwEjjC2U+cXqgVO1rCyVqbxZNCmHyNYHjDDCxSEbks9Ju5xqJxDSxnyXEw==", "requires": { "eventemitter3": "3.1.2", "underscore": "1.9.1", - "web3-core-helpers": "1.2.2" + "web3-core-helpers": "1.2.4" } }, "web3-eth": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.2.tgz", - "integrity": "sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.4.tgz", + "integrity": "sha512-+j+kbfmZsbc3+KJpvHM16j1xRFHe2jBAniMo1BHKc3lho6A8Sn9Buyut6odubguX2AxoRArCdIDCkT9hjUERpA==", "requires": { "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-eth-accounts": "1.2.2", - "web3-eth-contract": "1.2.2", - "web3-eth-ens": "1.2.2", - "web3-eth-iban": "1.2.2", - "web3-eth-personal": "1.2.2", - "web3-net": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.2.4", + "web3-core-helpers": "1.2.4", + "web3-core-method": "1.2.4", + "web3-core-subscriptions": "1.2.4", + "web3-eth-abi": "1.2.4", + "web3-eth-accounts": "1.2.4", + "web3-eth-contract": "1.2.4", + "web3-eth-ens": "1.2.4", + "web3-eth-iban": "1.2.4", + "web3-eth-personal": "1.2.4", + "web3-net": "1.2.4", + "web3-utils": "1.2.4" } }, "web3-eth-abi": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz", - "integrity": "sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.4.tgz", + "integrity": "sha512-8eLIY4xZKoU3DSVu1pORluAw9Ru0/v4CGdw5so31nn+7fR8zgHMgwbFe0aOqWQ5VU42PzMMXeIJwt4AEi2buFg==", "requires": { "ethers": "4.0.0-beta.3", "underscore": "1.9.1", - "web3-utils": "1.2.2" + "web3-utils": "1.2.4" } }, "web3-eth-accounts": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz", - "integrity": "sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.4.tgz", + "integrity": "sha512-04LzT/UtWmRFmi4hHRewP5Zz43fWhuHiK5XimP86sUQodk/ByOkXQ3RoXyGXFMNoRxdcAeRNxSfA2DpIBc9xUw==", "requires": { + "@web3-js/scrypt-shim": "^0.1.0", "any-promise": "1.3.0", "crypto-browserify": "3.12.0", "eth-lib": "0.2.7", "ethereumjs-common": "^1.3.2", "ethereumjs-tx": "^2.1.1", - "scrypt-shim": "github:web3-js/scrypt-shim#be5e616323a8b5e568788bf94d03c1b8410eac54", "underscore": "1.9.1", "uuid": "3.3.2", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.2.4", + "web3-core-helpers": "1.2.4", + "web3-core-method": "1.2.4", + "web3-utils": "1.2.4" }, "dependencies": { "eth-lib": { @@ -5112,112 +5802,119 @@ } }, "web3-eth-contract": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz", - "integrity": "sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.4.tgz", + "integrity": "sha512-b/9zC0qjVetEYnzRA1oZ8gF1OSSUkwSYi5LGr4GeckLkzXP7osEnp9lkO/AQcE4GpG+l+STnKPnASXJGZPgBRQ==", "requires": { "@types/bn.js": "^4.11.4", "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.2.4", + "web3-core-helpers": "1.2.4", + "web3-core-method": "1.2.4", + "web3-core-promievent": "1.2.4", + "web3-core-subscriptions": "1.2.4", + "web3-eth-abi": "1.2.4", + "web3-utils": "1.2.4" } }, "web3-eth-ens": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz", - "integrity": "sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.4.tgz", + "integrity": "sha512-g8+JxnZlhdsCzCS38Zm6R/ngXhXzvc3h7bXlxgKU4coTzLLoMpgOAEz71GxyIJinWTFbLXk/WjNY0dazi9NwVw==", "requires": { "eth-ens-namehash": "2.0.8", "underscore": "1.9.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-promievent": "1.2.2", - "web3-eth-abi": "1.2.2", - "web3-eth-contract": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.2.4", + "web3-core-helpers": "1.2.4", + "web3-core-promievent": "1.2.4", + "web3-eth-abi": "1.2.4", + "web3-eth-contract": "1.2.4", + "web3-utils": "1.2.4" } }, "web3-eth-iban": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz", - "integrity": "sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.4.tgz", + "integrity": "sha512-D9HIyctru/FLRpXakRwmwdjb5bWU2O6UE/3AXvRm6DCOf2e+7Ve11qQrPtaubHfpdW3KWjDKvlxV9iaFv/oTMQ==", "requires": { "bn.js": "4.11.8", - "web3-utils": "1.2.2" + "web3-utils": "1.2.4" } }, "web3-eth-personal": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz", - "integrity": "sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.4.tgz", + "integrity": "sha512-5Russ7ZECwHaZXcN3DLuLS7390Vzgrzepl4D87SD6Sn1DHsCZtvfdPIYwoTmKNp69LG3mORl7U23Ga5YxqkICw==", "requires": { "@types/node": "^12.6.1", - "web3-core": "1.2.2", - "web3-core-helpers": "1.2.2", - "web3-core-method": "1.2.2", - "web3-net": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.2.4", + "web3-core-helpers": "1.2.4", + "web3-core-method": "1.2.4", + "web3-net": "1.2.4", + "web3-utils": "1.2.4" + }, + "dependencies": { + "@types/node": { + "version": "12.12.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.10.tgz", + "integrity": "sha512-rhG2F0v4nNMqcPM4dMSne7R9iBzehUnARYbJq7G36CoczcqjNWuriAy6kd6quT30ISmfBhIRFVYDMSLrBASHNw==" + } } }, "web3-net": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.2.tgz", - "integrity": "sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.4.tgz", + "integrity": "sha512-wKOsqhyXWPSYTGbp7ofVvni17yfRptpqoUdp3SC8RAhDmGkX6irsiT9pON79m6b3HUHfLoBilFQyt/fTUZOf7A==", "requires": { - "web3-core": "1.2.2", - "web3-core-method": "1.2.2", - "web3-utils": "1.2.2" + "web3-core": "1.2.4", + "web3-core-method": "1.2.4", + "web3-utils": "1.2.4" } }, "web3-providers-http": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.2.tgz", - "integrity": "sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.4.tgz", + "integrity": "sha512-dzVCkRrR/cqlIrcrWNiPt9gyt0AZTE0J+MfAu9rR6CyIgtnm1wFUVVGaxYRxuTGQRO4Dlo49gtoGwaGcyxqiTw==", "requires": { - "web3-core-helpers": "1.2.2", + "web3-core-helpers": "1.2.4", "xhr2-cookies": "1.1.0" } }, "web3-providers-ipc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz", - "integrity": "sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.4.tgz", + "integrity": "sha512-8J3Dguffin51gckTaNrO3oMBo7g+j0UNk6hXmdmQMMNEtrYqw4ctT6t06YOf9GgtOMjSAc1YEh3LPrvgIsR7og==", "requires": { "oboe": "2.1.4", "underscore": "1.9.1", - "web3-core-helpers": "1.2.2" + "web3-core-helpers": "1.2.4" } }, "web3-providers-ws": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz", - "integrity": "sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.4.tgz", + "integrity": "sha512-F/vQpDzeK+++oeeNROl1IVTufFCwCR2hpWe5yRXN0ApLwHqXrMI7UwQNdJ9iyibcWjJf/ECbauEEQ8CHgE+MYQ==", "requires": { + "@web3-js/websocket": "^1.0.29", "underscore": "1.9.1", - "web3-core-helpers": "1.2.2", - "websocket": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e" + "web3-core-helpers": "1.2.4" } }, "web3-shh": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.2.tgz", - "integrity": "sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.4.tgz", + "integrity": "sha512-z+9SCw0dE+69Z/Hv8809XDbLj7lTfEv9Sgu8eKEIdGntZf4v7ewj5rzN5bZZSz8aCvfK7Y6ovz1PBAu4QzS4IQ==", "requires": { - "web3-core": "1.2.2", - "web3-core-method": "1.2.2", - "web3-core-subscriptions": "1.2.2", - "web3-net": "1.2.2" + "web3-core": "1.2.4", + "web3-core-method": "1.2.4", + "web3-core-subscriptions": "1.2.4", + "web3-net": "1.2.4" } }, "web3-utils": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", - "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.4.tgz", + "integrity": "sha512-+S86Ip+jqfIPQWvw2N/xBQq5JNqCO0dyvukGdJm8fEWHZbckT4WxSpHbx+9KLEWY4H4x9pUwnoRkK87pYyHfgQ==", "requires": { "bn.js": "4.11.8", "eth-lib": "0.2.7", @@ -5241,32 +5938,6 @@ } } }, - "websocket": { - "version": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e", - "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", - "requires": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "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=" - } - } - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -5355,11 +6026,15 @@ } } }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -5458,8 +6133,7 @@ "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yaeti": { "version": "0.0.6", @@ -5472,57 +6146,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true, + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", + "camelcase": "^2.0.1", + "cliui": "^3.0.3", "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "read-pkg-up": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" } }, "yargs-parser": { @@ -5532,6 +6166,14 @@ "dev": true, "requires": { "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } } }, "yauzl": { @@ -5544,9 +6186,9 @@ } }, "zeromq": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/zeromq/-/zeromq-5.1.1.tgz", - "integrity": "sha512-ZInBjczu5qjKW9WFnFcaOoAqCqDqTn1QqVzB6nTt5SGu9OQb9K8qk9RjBoXJY+fxTpRDparqBnhFxYBZFEgJyw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/zeromq/-/zeromq-5.2.0.tgz", + "integrity": "sha512-qsckhCmrg6et6zrAJytC971SSN/4iLxKgkXK1Wqn2Gij5KXMY+TA+3cy/iFwehaWdU5usg5HNOOgaBdjSqtCVw==", "requires": { "nan": "^2.14.0", "prebuild-install": "^5.3.2" diff --git a/examples/simple-asset-transfer/package.json b/examples/simple-asset-transfer/package.json index 9c40418b48..7b9a0c3a34 100644 --- a/examples/simple-asset-transfer/package.json +++ b/examples/simple-asset-transfer/package.json @@ -2,13 +2,12 @@ "version": "0.1.0", "name": "@hyperledger-labs/blockchain-integration-framework.examples.simple-asset-transfer", "dependencies": { - "@hyperledger-labs/blockchain-integration-framework": "git+https://github.com/hyperledger-labs/blockchain-integration-framework.git#fix/peter.somogyvari/make-ci-pass", + "@hyperledger-labs/blockchain-integration-framework": "../../.tmp/hyperledger-labs-blockchain-integration-framework-dev.tgz", "cookie-parser": "^1.4.4", "express-bearer-token": "^2.4.0", "express-jwt": "^5.3.1", "express-session": "^1.16.2", - "request-promise": "^4.2.4", - "typedarray-to-buffer": "^3.1.5" + "request-promise": "^4.2.4" }, "devDependencies": { "npm-check": "^5.9.0" @@ -22,23 +21,23 @@ "fabric:down": "fuser -k -n tcp 4000 ; docker-compose -f fabric/artifacts/docker-compose.yaml rm -sf", "fabric:log": "docker-compose -f fabric/artifacts/docker-compose.yaml logs -f", "fed:build": "docker build --no-cache --force-rm -t federation/validator .", - "fed:fabric": "docker-compose -p federation-fabric -f ./federations/docker-compose-fabric.yml up --renew-anon-volumes -d", - "fed:fabric:down": "docker-compose -p federation-fabric -f ./federations/docker-compose-fabric.yml rm -sf", - "fed:fabric:log": "docker-compose -p federation-fabric -f ./federations/docker-compose-fabric.yml logs -f", - "fed:quorum": "docker-compose -p federation-quorum -f ./federations/docker-compose-quorum.yml up --renew-anon-volumes -d", - "fed:quorum:down": "docker-compose -p federation-quorum -f ./federations/docker-compose-quorum.yml rm -sf", - "fed:quorum:log": "docker-compose -p federation-quorum -f ./federations/docker-compose-quorum.yml logs -f", - "fed:corda": "docker-compose -p federation-corda -f ./federations/docker-compose-corda.yml up --renew-anon-volumes -d", - "fed:corda:down": "docker-compose -p federation-corda -f ./federations/docker-compose-corda.yml rm -sf", - "fed:corda:log": "docker-compose -p federation-corda -f ./federations/docker-compose-corda.yml logs -f", + "fed:fabric": "docker-compose -p federation-fabric -f ./federations/docker-compose-fabric.yml --compatibility up --renew-anon-volumes -d", + "fed:fabric:down": "docker-compose -p federation-fabric -f ./federations/docker-compose-fabric.yml --compatibility rm -sf", + "fed:fabric:log": "docker-compose -p federation-fabric -f ./federations/docker-compose-fabric.yml --compatibility logs -f", + "fed:quorum": "docker-compose -p federation-quorum -f ./federations/docker-compose-quorum.yml --compatibility up --renew-anon-volumes -d", + "fed:quorum:down": "docker-compose -p federation-quorum -f ./federations/docker-compose-quorum.yml --compatibility rm -sf", + "fed:quorum:log": "docker-compose -p federation-quorum -f ./federations/docker-compose-quorum.yml --compatibility logs -f", + "fed:corda": "docker-compose -p federation-corda -f ./federations/docker-compose-corda.yml --compatibility up --renew-anon-volumes -d", + "fed:corda:down": "docker-compose -p federation-corda -f ./federations/docker-compose-corda.yml --compatibility rm -sf", + "fed:corda:log": "docker-compose -p federation-corda -f ./federations/docker-compose-corda.yml --compatibility logs -f", "install-all": "npm i && cd fabric/api && npm i && cd - && cd quorum/api && npm i", - "quorum": "QUORUM_CONSENSUS=raft docker-compose -p quorum -f ./quorum/platform/docker-compose.yml up --renew-anon-volumes -d", - "quorum:down": "docker-compose -p quorum -f ./quorum/platform/docker-compose.yml rm -sf", - "quorum:log": "docker-compose -p quorum -f ./quorum/platform/docker-compose.yml logs -f", - "quorum:api": "docker-compose -p quorum-api -f ./quorum/api/docker-compose.yml up --renew-anon-volumes -d", + "quorum": "QUORUM_CONSENSUS=raft docker-compose -p quorum -f ./quorum/platform/docker-compose.yml --compatibility up --renew-anon-volumes -d", + "quorum:down": "docker-compose -p quorum -f ./quorum/platform/docker-compose.yml --compatibility rm -sf", + "quorum:log": "docker-compose -p quorum -f ./quorum/platform/docker-compose.yml --compatibility logs -f", + "quorum:api": "docker-compose -p quorum-api -f ./quorum/api/docker-compose.yml --compatibility up --renew-anon-volumes -d", "quorum:api:build": "docker build --no-cache -t federation/qserver -f quorum/api/Dockerfile quorum", - "quorum:api:down": "docker-compose -p quorum-api -f ./quorum/api/docker-compose.yml rm -sf", - "quorum:api:log": "docker-compose -p quorum-api -f ./quorum/api/docker-compose.yml logs -f", + "quorum:api:down": "docker-compose -p quorum-api -f ./quorum/api/docker-compose.yml --compatibility rm -sf", + "quorum:api:log": "docker-compose -p quorum-api -f ./quorum/api/docker-compose.yml --compatibility logs -f", "scenario:share": "cd scenarios && node share-pub-keys.js", "scenario:FtQ": "cd scenarios && node fabric-to-quorum.js", "scenario:QtF": "cd scenarios && node quorum-to-fabric.js", @@ -48,7 +47,8 @@ "scenario:QtC": "cd scenarios && node quorum-to-corda.js", "test": "../../node_modules/.bin/cross-env NODE_ENV=test ../../node_modules/.bin/mocha --ui bdd --reporter spec --colors tests/*.js --recursive --exit", "test:bc": "BLOCKCHAIN=true npm run test", - "upgrade-interactive": "npm-check --update" + "upgrade-interactive": "npm-check --update", + "preinstall": "node ../../tools/create-local-npm-package.js" }, "private": true, "engines": { diff --git a/examples/simple-asset-transfer/quorum/platform/docker-compose.yml b/examples/simple-asset-transfer/quorum/platform/docker-compose.yml index f29c64be9c..6b349b302c 100644 --- a/examples/simple-asset-transfer/quorum/platform/docker-compose.yml +++ b/examples/simple-asset-transfer/quorum/platform/docker-compose.yml @@ -187,7 +187,7 @@ x-tx-manager-def: --publickeys=/examples/keys/tm$${NODE_ID}.pub \ --privatekeys=/examples/keys/tm$${NODE_ID}.key \ --storage=$${DDIR} \ - --verbosity=4 + --verbosity=1 ;; *) echo "Invalid Transaction Manager" diff --git a/package-lock.json b/package-lock.json index 454f395184..643c430559 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,69 @@ "regenerator-runtime": "^0.13.2" } }, + "@grpc/proto-loader": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.3.tgz", + "integrity": "sha512-8qvUtGg77G2ZT2HqdqYoM/OY97gQd/0crSG34xNmZ4ZOsv3aQT/FQV9QfZPazTGna6MIoyUd+u6AxsoZjJ/VMQ==", + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -69,6 +132,20 @@ "@types/node": "*" } }, + "@types/bytebuffer": { + "version": "5.0.40", + "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.40.tgz", + "integrity": "sha512-h48dyzZrPMz25K6Q4+NCwWaxwXany2FhQg/ErOcdZS1ZpsaDnDMZg8JYLMTGz7uvXKrcKGJUZJlZObyfgdaN9g==", + "requires": { + "@types/long": "*", + "@types/node": "*" + } + }, + "@types/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" + }, "@types/node": { "version": "12.12.8", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.8.tgz", @@ -341,6 +418,15 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -924,6 +1010,21 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "~3" + }, + "dependencies": { + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + } + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -1312,6 +1413,11 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1577,8 +1683,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", @@ -2447,6 +2552,23 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "etcd3": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/etcd3/-/etcd3-0.2.13.tgz", + "integrity": "sha512-9zVnoebQRwOGivGT9/bFHQsjkcZttgzyDU50G1J27tdU76vmgp78YGOAEe9zzEjU6IEFa2KYYUg5AyMKDOp37A==", + "requires": { + "@grpc/proto-loader": "^0.5.1", + "bignumber.js": "^5.0.0", + "grpc": "^1.21.1" + }, + "dependencies": { + "bignumber.js": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-5.0.0.tgz", + "integrity": "sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg==" + } + } + }, "eth-ens-namehash": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", @@ -3860,6 +3982,486 @@ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, + "grpc": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.24.2.tgz", + "integrity": "sha512-EG3WH6AWMVvAiV15d+lr+K77HJ/KV/3FvMpjKjulXHbTwgDZkhkcWbwhxFAoTdxTkQvy0WFcO3Nog50QBbHZWw==", + "requires": { + "@types/bytebuffer": "^5.0.40", + "lodash.camelcase": "^4.3.0", + "lodash.clone": "^4.5.0", + "nan": "^2.13.2", + "node-pre-gyp": "^0.14.0", + "protobufjs": "^5.0.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "chownr": { + "version": "1.1.3", + "bundled": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.4", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.1.2", + "bundled": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true + }, + "npm-packlist": { + "version": "1.4.6", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true + }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "requires": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + } + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.7.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "3.1.1", + "bundled": true + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -4218,8 +4820,7 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { "version": "1.9.0", @@ -4743,7 +5344,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "^1.0.0" } @@ -4806,6 +5406,16 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -4863,6 +5473,11 @@ "streamroller": "^1.0.6" } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -5924,6 +6539,11 @@ "word-wrap": "~1.2.3" } }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, "ora": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", @@ -6409,6 +7029,33 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "protobufjs": { + "version": "6.8.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "10.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", + "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==" + } + } + }, "proxy-addr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", @@ -8587,6 +9234,11 @@ } } }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index 835b839e08..b17a71c2c8 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "upgrade-interactive": "npm-check --update" }, "dependencies": { + "etcd3": "0.2.13", "log4js": "^4.1.0", "prettier": "^1.16.4", "request": "^2.88.0", @@ -26,6 +27,7 @@ "secp256k1": "^3.6.2", "sha3": "^2.0.1", "truffle": "^5.0.14", + "uuid": "3.3.3", "web3": "1.2.4", "web3-utils": "1.2.4", "zeromq": "^5.1.0" diff --git a/src/Validator.js b/src/Validator.js index bdb4876f2f..4d18587dd8 100644 --- a/src/Validator.js +++ b/src/Validator.js @@ -1,6 +1,8 @@ /* eslint no-use-before-define: ["error", { "variables": false }] */ const zmq = require(`zeromq`); const log4js = require(`log4js`); +const { Etcd3 } = require('etcd3'); +const uuidV4 = require('uuid/v4'); const fedcom = require(`./federation-communication`); const conf = require(`../config.json`); @@ -11,6 +13,8 @@ const Multisig = require(`./Multisig`); const logger = log4js.getLogger(`Validator`); logger.level = `DEBUG`; +const BIF_LEADER = 'bif/leader'; + /** * Validator * @@ -43,27 +47,13 @@ class Validator { * @param {String} options.clientRepAddr Client Rep address * @param {String} options.pubAddr Public address * @param {String} options.repAddr Rep address - * @param {String} options.leaderPubAddr Leader Public address - * @param {String} options.leaderRepAddr Leader Rep address - * @param {String} options.leaderClientRepAddr Leader Client Rep address - * @param {String} options.type Validator type */ constructor(blockchainClient, options) { if (!(blockchainClient instanceof Connector)) { throw new Error(`Validator needs a valid connector to get started`); } this.blockchainClient = blockchainClient; - Object.assign(this, options); - if (this.type === fedcom.VALIDATOR_TYPE.LEADER) { - this.leaderPubAddr = options.pubAddr; - this.leaderRepAddr = options.repAddr; - this.leaderClientRepAddr = options.clientRepAddr; - } else { - this.leaderPubAddr = options.leaderPubAddr; - this.leaderRepAddr = options.leaderRepAddr; - this.leaderClientRepAddr = options.leaderClientRepAddr; - } this.publishSocket = null; this.requestSocket = null; @@ -72,6 +62,89 @@ class Validator { this.clientRepSocket = null; this.currentMultisig = new Multisig(); this.electionTimeout = conf.electionTimeout; + this.randomizedLeadershipPoolInterval = this.electionTimeout / 3 + (Math.random() * this.electionTimeout) / 3; + + this.selfNodeInfo = { + id: uuidV4(), + pid: process.pid, + startedAt: new Date(), + networkInfo: { + leaderPubAddr: this.pubAddr, + leaderRepAddr: this.repAddr, + leaderClientRepAddr: this.clientRepAddr, + }, + }; + + logger.debug(`Creating new validator instance. Node info: `, JSON.stringify(this.selfNodeInfo)); + + // etcd setup + this.EtcdConstructor = typeof this.EtcdConstructor === 'function' ? this.EtcdConstructor : Etcd3; + this.etcdClient = this.createEtcdClient(); + + this.setupLeaderElections(); + } + + isCurrentNodeLeader() { + return typeof this.leaderNodeInfo === 'object' && this.leaderNodeInfo.id === this.selfNodeInfo.id; + } + + createEtcdClient() { + if (typeof this.EtcdConstructor !== 'function') { + throw new TypeError(`Validator#createEtcdClient() expected this.EtcdConstructor to be function.`); + } + if (!Array.isArray(this.etcdHosts)) { + throw new TypeError(`Validator#createEtcdClient() expected this.etcdHosts to be an Array.`); + } + logger.debug(`Creating etcd client with hosts`, this.etcdHosts); + return new this.EtcdConstructor({ + hosts: this.etcdHosts, + }); + } + + async setupLeaderElections() { + // Setup the watcher + const watcher = await this.etcdClient + .watch() + .key(BIF_LEADER) + .create(); + logger.debug(`Etcd watcher set up OK.`); + + watcher + .on('disconnected', () => logger.debug('[WATCH] disconnected...', this.selfNodeInfo)) + .on('connected', () => logger.debug('[WATCH] successfully reconnected!', this.selfNodeInfo)) + .on('put', res => { + const newLeaderNodeInfoJson = res.value.toString('utf8'); + logger.debug(`[WATCH] key ${BIF_LEADER} got set to new value: `, newLeaderNodeInfoJson); + const newLeaderNodeInfo = JSON.parse(newLeaderNodeInfoJson); + this.switchToNewLeader(newLeaderNodeInfo); + }); + // Finished settig up watcher + + const leaseTtlSeconds = Math.round(this.electionTimeout / 1000); + logger.debug(`Creating lease with TTL=${leaseTtlSeconds} seconds...`); + const theLease = this.etcdClient.lease(leaseTtlSeconds); + + theLease.on('lost', () => logger.debug(['LEASE:keepaliveLost'])); + theLease.on('keepaliveFailed', () => logger.warn(['LEASE:keepaliveFailed'])); + theLease.on('keepaliveEstablished', () => logger.debug(['LEASE:keepaliveEstablished'])); + + this.attemptToBecomeLeader(theLease); + setInterval(this.attemptToBecomeLeader.bind(this, theLease), this.randomizedLeadershipPoolInterval); + } + + attemptToBecomeLeader(theLease) { + if (this.isCurrentNodeLeader()) { + return; + } + this.etcdClient + .if(BIF_LEADER, 'Lease', '==', 0) + .then(theLease.put(BIF_LEADER).value(JSON.stringify(this.selfNodeInfo))) + .else(this.etcdClient.get(BIF_LEADER)) + .commit() + // .then(transactionResponse => { + // logger.debug(`TransactionResponse=${JSON.stringify(transactionResponse)}`); + // }) + .catch(ex => logger.error('Leadership attempt failed with exception:', ex)); } /** @@ -80,12 +153,6 @@ class Validator { */ start() { this.startClientServer(); - - if (this.type === fedcom.VALIDATOR_TYPE.LEADER) { - this.startAsLeader(); - } else { - this.startAsFollower(); - } } /** @@ -93,7 +160,7 @@ class Validator { * @return {void} */ stop() { - if (this.type === fedcom.VALIDATOR_TYPE.LEADER) { + if (this.isCurrentNodeLeader()) { clearInterval(this.intervalExec); this.requestSocket.close(); } @@ -108,17 +175,11 @@ class Validator { */ startAsLeader() { logger.debug(`Starting as Leader ...`); - logger.debug( - `I am : - (${this.pubAddr}, - ${this.repAddr}, - ${this.clientRepAddr})` - ); + logger.debug(`I am : (${this.pubAddr}, ${this.repAddr}, ${this.clientRepAddr})`); this.type = fedcom.VALIDATOR_TYPE.LEADER; this.publishSocket = zmq.socket(`pub`); this.publishSocket.bindSync(this.leaderPubAddr); - this.intervalExec = this.newLeaderElection(); this.requestSocket = zmq.socket(`rep`); this.requestSocket.bindSync(this.leaderRepAddr); this.requestSocket.on(`message`, fedcom.ValidatorAsLeaderMessage.bind(this)); @@ -131,12 +192,7 @@ class Validator { */ startAsFollower() { logger.debug(`Starting as Follower... `); - logger.debug( - `My Leader is : - (${this.leaderPubAddr}, - ${this.leaderRepAddr}, - ${this.leaderClientRepAddr})` - ); + logger.debug(`My Leader is : (${this.leaderPubAddr}, ${this.leaderRepAddr}, ${this.leaderClientRepAddr})`); this.type = fedcom.VALIDATOR_TYPE.FOLLOWER; this.publishSocket = zmq.socket(`sub`); @@ -211,17 +267,6 @@ class Validator { } } - /** - * Select on validator in the specified pool to be the leader of the next round - * @static - * @param {string[]} aliveValidators - Alive Validators - * @return {string} Next Leader Address - */ - static selectNextLeader(aliveValidators) { - const index = Math.floor(Math.random() * Math.floor(aliveValidators.length)); - return aliveValidators[index]; - } - /** * Sign locally and broadcast remaining job to alive validators * @param {string} type Validator type @@ -249,63 +294,34 @@ class Validator { return new Promise(resolve => setTimeout(resolve.bind(this, true), conf.timeout)); } - /** - * Prepare validator pool and select new leader - * @return {string} Interval Id. - */ - newLeaderElection() { - return setInterval(() => { - this.availableFollowers = []; - - logger.debug(`Sending heartbeat request`); - this.publishSocket.send([fedcom.MSG_TYPE.HEARTBEAT, `{}`]); - - setTimeout(() => { - // Select the next leader - if (this.availableFollowers.length !== 0) { - const nextLeader = Validator.selectNextLeader(this.availableFollowers); - this.publishSocket.send([fedcom.MSG_TYPE.NEWLEADER, JSON.stringify(nextLeader)]); - // Switch from leader to follower - this.switchToNewLeader(nextLeader); - } - }, conf.timeout); - }, this.electionTimeout); - } - /** * Change local parameters to adjust to new leader - * @param {Object} newLeader - * @param {string} newLeader.pub New Leader Public Address - * @param {string} newLeader.rep New Leader Rep Address - * @param {string} newLeader.clientRep New Leader Client Rep Address * @return {void} */ - switchToNewLeader(newLeader) { - // Update leader address - this.leaderPubAddr = newLeader.pub; - this.leaderRepAddr = newLeader.rep; - this.leaderClientRepAddr = newLeader.clientRep; + switchToNewLeader(newLeaderNodeInfo) { + this.leaderNodeInfo = newLeaderNodeInfo; + + // TODO(peter.somogyvari): Once leader election has enough test coverage, get rid of these property assignments + // and just use the this.leaderNodeInfo.networkInfo object directly everywhere. + this.leaderPubAddr = this.leaderNodeInfo.networkInfo.leaderPubAddr; + this.leaderRepAddr = this.leaderNodeInfo.networkInfo.leaderRepAddr; + this.leaderClientRepAddr = this.leaderNodeInfo.networkInfo.leaderClientRepAddr; // Stop the pub and rep sockets - this.publishSocket.close(); + if (this.publishSocket) { + this.publishSocket.close(); + } - if (this.type === fedcom.VALIDATOR_TYPE.LEADER) { - // REFAC: this if content could go to line ~206 - // (right before newLeaderElection/switchToNewLeader) - // but that would need to refac the test + if (this.requestSocket) { this.requestSocket.close(); this.requestSocket = null; - clearInterval(this.intervalExec); - this.intervalExec = null; } - if (this.pubAddr === newLeader.pub) { + if (this.isCurrentNodeLeader()) { this.startAsLeader(); - return; + } else { + this.startAsFollower(); } - - // Follower updates its references to the new leader - this.startAsFollower(); } } diff --git a/tests/client.js b/tests/client.js index a0b0a72a04..6fc544c67b 100644 --- a/tests/client.js +++ b/tests/client.js @@ -124,6 +124,7 @@ describe(`Client module`, function() { pubKey: `031b3e4b65070268bd2ce3652966f75ebdf7184f637fd24a4fe0417c2dcb92fd9b`, }; const validatorOptions1 = { + etcdHosts: ['http://localhost:2379'], ...validatorKeys, type: fedcom.VALIDATOR_TYPE.LEADER, clientRepAddr: `tcp://127.0.0.1:7103`, @@ -137,7 +138,11 @@ describe(`Client module`, function() { validator1 = new Validator(connector1, validatorOptions1); validator1.start(); + // self promote to leader manually for test since there's no etd cluster, we need to fake/rig the election + validator1.switchToNewLeader(validator1.selfNodeInfo); + const validatorOptions2 = { + etcdHosts: ['http://localhost:2379'], ...validatorKeys, type: fedcom.VALIDATOR_TYPE.FOLLOWER, leaderClientRepAddr: `tcp://127.0.0.1:7103`, diff --git a/tests/validator.js b/tests/validator.js index 7b88ebd10f..aec41bf69e 100644 --- a/tests/validator.js +++ b/tests/validator.js @@ -3,7 +3,7 @@ /* eslint func-names: ["error", "never"] */ const chai = require(`chai`); const zmq = require(`zeromq`); - +const uuidV4 = require('uuid/v4'); const fedcom = require(`../src/federation-communication`); const Validator = require(`../src/Validator`); const Multisig = require(`../src/Multisig`); @@ -34,6 +34,7 @@ describe(`Validator module`, function() { it(`Create a leader`, function() { // Lets set the leader to be validator 1 const leaderOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, ...addrOptions, type: fedcom.VALIDATOR_TYPE.LEADER, @@ -50,6 +51,7 @@ describe(`Validator module`, function() { it(`Create a follower`, function() { // leader is considered to be validator 2 const followerOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, ...addrOptions, type: fedcom.VALIDATOR_TYPE.FOLLOWER, @@ -101,15 +103,20 @@ describe(`Validator module`, function() { }); describe(`Switch to new leader`, function() { - const newLeader = { - type: fedcom.MSG_TYPE.HEARTBEAT, - pub: `tcp://127.0.0.1:13003`, - rep: `tcp://127.0.0.1:15003`, - clientRep: `tcp://127.0.0.1:17003`, + const newLeaderNodeInfo = { + id: uuidV4(), + pid: process.pid, + startedAt: new Date(), + networkInfo: { + leaderRepAddr: `tcp://127.0.0.1:15003`, + leaderPubAddr: `tcp://127.0.0.1:13003`, + leaderClientRepAddr: `tcp://127.0.0.1:17003`, + }, }; it(`Switch from leader to follower`, function() { const leaderOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, ...addrOptions, type: fedcom.VALIDATOR_TYPE.LEADER, @@ -118,12 +125,11 @@ describe(`Validator module`, function() { // Validator starting as leader validator.start(); - validator.switchToNewLeader(newLeader); + validator.switchToNewLeader(newLeaderNodeInfo); chai.expect(validator.leaderPubAddr).to.equal(`tcp://127.0.0.1:13003`); chai.expect(validator.leaderRepAddr).to.equal(`tcp://127.0.0.1:15003`); chai.expect(validator.leaderClientRepAddr).to.equal(`tcp://127.0.0.1:17003`); - chai.expect(validator.type).to.equal(fedcom.VALIDATOR_TYPE.FOLLOWER); // Stop the validator validator.stop(); @@ -134,6 +140,7 @@ describe(`Validator module`, function() { // Its leader is follower 2 // It has been elected leader const followerOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, clientRepAddr: `tcp://127.0.0.1:17003`, pubAddr: `tcp://127.0.0.1:13003`, @@ -141,19 +148,17 @@ describe(`Validator module`, function() { leaderPubAddr: `tcp://127.0.0.1:13002`, leaderRepAddr: `tcp://127.0.0.1:15002`, leaderClientRepAddr: `tcp://127.0.0.1:17002`, - type: fedcom.VALIDATOR_TYPE.FOLLOWER, }; const validator = new Validator(new Connector.FABRIC(config.blockchains.fabric), followerOptions); // Validator starting as follower 3 validator.start(); // New leader is follower 3 - validator.switchToNewLeader(newLeader); + validator.switchToNewLeader(newLeaderNodeInfo); chai.expect(validator.leaderPubAddr).to.equal(`tcp://127.0.0.1:13003`); chai.expect(validator.leaderRepAddr).to.equal(`tcp://127.0.0.1:15003`); chai.expect(validator.leaderClientRepAddr).to.equal(`tcp://127.0.0.1:17003`); - chai.expect(validator.type).to.equal(fedcom.VALIDATOR_TYPE.LEADER); // Stop the validator validator.stop(); @@ -164,6 +169,7 @@ describe(`Validator module`, function() { // His leader is follower 2 // Elected validator is follower 3 const followerOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, ...addrOptions, type: fedcom.VALIDATOR_TYPE.FOLLOWER, @@ -176,7 +182,7 @@ describe(`Validator module`, function() { validator.start(); // New leader is follower 3 - validator.switchToNewLeader(newLeader); + validator.switchToNewLeader(newLeaderNodeInfo); chai.expect(validator.leaderPubAddr).to.equal(`tcp://127.0.0.1:13003`); chai.expect(validator.leaderRepAddr).to.equal(`tcp://127.0.0.1:15003`); @@ -195,12 +201,19 @@ describe(`Validator module`, function() { it(`The messages are well published via the right addr`, async function() { const leaderOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, ...addrOptions, - type: fedcom.VALIDATOR_TYPE.LEADER, }; leader = new Validator(new Connector.FABRIC(config.blockchains.fabric), leaderOptions); + // self promote to leader manually for test since there's no etd cluster, we need to fake/rig the election + leader.leaderNodeInfo = leader.selfNodeInfo; + // sets this.leaderPubAddr, this.leaderRepAddr, this.leaderClientRepAddr according to new leader + Object.assign(leader, leader.leaderNodeInfo.networkInfo); + + chai.expect(leader.isCurrentNodeLeader()).to.equal(true); + // Validator starting as leader leader.startAsLeader(); @@ -209,14 +222,14 @@ describe(`Validator module`, function() { new Promise((resolve, reject) => { const socket = zmq.socket(`sub`); try { - socket.connect(`tcp://127.0.0.1:13001`); + socket.connect(leader.leaderPubAddr); socket.subscribe(``); } catch (error) { reject(error); } - socket.on(`message`, type => { - resolve(type.toString()); + socket.on(`message`, typeBuffer => { + resolve(typeBuffer.toString()); clearInterval(leader.intervalExec); leader.publishSocket.close(); leader.requestSocket.close(); @@ -224,13 +237,21 @@ describe(`Validator module`, function() { }); }); - const type = await receiveBroadcast(); - const ok = [fedcom.MSG_TYPE.HEARTBEAT, fedcom.MSG_TYPE.NEWLEADER, fedcom.MSG_TYPE.SIGN].includes(type); - chai.expect(ok).to.equal(true); + setTimeout(() => { + const targetDLTType = `FABRIC`; + const data = {}; + const type = fedcom.MSG_TYPE.SIGN; + const signatureReq = { type, data, targetDLTType, requester: leader.leaderRepAddr }; + leader.publishSocket.send([fedcom.MSG_TYPE.SIGN, JSON.stringify(signatureReq)]); + }, 100); + + const broadcastedType = await receiveBroadcast(); // if message didn't arrive this will cause the test to time out + chai.expect(broadcastedType).to.equal(fedcom.MSG_TYPE.SIGN); }); it(`The leader listens to heartbeat messages at repAddr`, async function() { const leaderOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, clientRepAddr: `tcp://127.0.0.1:17002`, pubAddr: `tcp://127.0.0.1:13002`, @@ -239,6 +260,13 @@ describe(`Validator module`, function() { }; const validator = new Validator(new Connector.FABRIC(config.blockchains.fabric), leaderOptions); + // self promote to leader manually for test since there's no etd cluster, we need to fake/rig the election + validator.leaderNodeInfo = validator.selfNodeInfo; + // sets this.leaderPubAddr, this.leaderRepAddr, this.leaderClientRepAddr according to new leader + Object.assign(validator, validator.leaderNodeInfo.networkInfo); + + chai.expect(validator.isCurrentNodeLeader()).to.equal(true); + // Validator starting as leader validator.startAsLeader(); const heartbeat = { @@ -274,6 +302,7 @@ describe(`Validator module`, function() { it(`The leader listens to signature messages at repAddr`, async function() { const leaderOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, clientRepAddr: `tcp://127.0.0.1:17003`, pubAddr: `tcp://127.0.0.1:13003`, @@ -282,6 +311,12 @@ describe(`Validator module`, function() { }; const validator = new Validator(new Connector.FABRIC(config.blockchains.fabric), leaderOptions); + // self promote to leader manually for test since there's no etd cluster, we need to fake/rig the election + validator.leaderNodeInfo = validator.selfNodeInfo; + // sets this.leaderPubAddr, this.leaderRepAddr, this.leaderClientRepAddr according to new leader + Object.assign(validator, validator.leaderNodeInfo.networkInfo); + + chai.expect(validator.isCurrentNodeLeader()).to.equal(true); // Validator starting as leader validator.startAsLeader(); const signature = { @@ -388,7 +423,8 @@ describe(`Validator module`, function() { // chai.expect(signature).to.have.own.property(`signature`); // chai.expect(signature).to.deep.equal({ // type: fedcom.MSG_TYPE.SIGN, - // signature: `31a5012bcdaf27b75d34c78d643d262c8b01db477dc65f308189866cfac0f82461362e3b00039007c2f1da164de7aeeba2f491711cde191957d51cc408eb1787`, // eslint-disable-line + // eslint-disable-next-line + // signature: `31a5012bcdaf27b75d34c78d643d262c8b01db477dc65f308189866cfac0f82461362e3b00039007c2f1da164de7aeeba2f491711cde191957d51cc408eb1787`, // pubKey: `031b3e4b65070268bd2ce3652966f75ebdf7184f637fd24a4fe0417c2dcb92fd9b`, // }); // }); @@ -401,6 +437,7 @@ describe(`Validator module`, function() { before(function() { const leaderOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, ...addrOptions, type: fedcom.VALIDATOR_TYPE.LEADER, @@ -483,6 +520,7 @@ describe(`Validator module`, function() { before(function() { const followerOptions = { + etcdHosts: ['http://localhost:2379'], ...keyOptions, clientRepAddr: `tcp://127.0.0.1:17005`, pubAddr: `tcp://127.0.0.1:13005`, diff --git a/tools/create-local-npm-package.js b/tools/create-local-npm-package.js new file mode 100755 index 0000000000..4f94acef09 --- /dev/null +++ b/tools/create-local-npm-package.js @@ -0,0 +1,73 @@ +/* eslint-disable no-console */ +const { execSync } = require('child_process'); +const fs = require('fs'); +const { join } = require('path'); + +const TAG = '[create-local-npm-package]'; +const PROJECT_ROOT = join(__dirname, '../'); // step out of the tools dir to project root +const TMP_DIR = join(PROJECT_ROOT, './.tmp'); + +/** + * A short, self-contained script with zero non-builtin dependencies (so that it doesn't require package.sjon/npm install) + * to be executed. It just needs NodeJS installed on the host operating system to be ready to go. + * + * The script is responsible for generating an npm package archivel file with a fixed name that can be used to install + * BIF locally for the examples without having to depend on remote Github URLs/registries for installation (which + * hugely complicates things and makes the whole process less deterministic) + * + * CWD (current working directory) agnostic: script anchors paths based on assumption that it is one level down from + * the root directory in the tools sub-folder so it will work regardless of where it was invoked from. This was + * necessary to make it easy to call the script from the examples/ sub-folders without having to bother about relative + * paths/project root resolution/normalization. + * + * Step by step this is what the script does: + * 1. Prints diagnostic info for debugging purposes about node and npm versions. + * 2. Reads the package.json file's contents form the project root directory + * 3. Gets version, package name from package.json contents (after parsing the JSON string) + * 4. Assembles the package file name that npm pack will produce based on the metadata (version, name) of the package + * obtained in step 3). + * 5. Invokes shell `npm pack` so that npm generates the package file that we already know the name of from step 4) + * 6. Renames and moves the generated package file so that a) it does not have a version in it's name and b) it resides + * in a directory that is not under version control (.tmp directory). + * 7. Prints success or failure depending on what happened. + * + */ +const main = async () => { + if (!fs.existsSync(TMP_DIR)) { + fs.mkdirSync(TMP_DIR); + } + + const nodeVersion = execSync('node --version') + .toString() + .trim(); + + const npmVersion = execSync('npm --version') + .toString() + .trim(); + + console.log(`${new Date().toJSON()} ${TAG} - NodeVersion=${nodeVersion}, npmVersion=${npmVersion}`); + + const packageFileName = execSync('npm pack', { cwd: PROJECT_ROOT }) + .toString() + .trim(); + + console.log(`${new Date().toJSON()} ${TAG} - packageFileName: "${packageFileName}"`); + + const packageJsonRaw = fs.readFileSync(join(PROJECT_ROOT, 'package.json')); + const packageJson = JSON.parse(packageJsonRaw); + console.log(`${new Date().toJSON()} ${TAG} - packageJson.version=${packageJson.version}`); + + const newPackageFileName = packageFileName.replace(packageJson.version, 'dev'); + fs.renameSync(join(PROJECT_ROOT, packageFileName), join(TMP_DIR, newPackageFileName)); + return newPackageFileName; +}; + +main() + .then(newPackageFileName => { + console.log(`${new Date().toJSON()} ${TAG} - SUCCESS_4d21b660-7676-4394-b853-642ce3617bed ${newPackageFileName}`); + process.exit(0); + }) + .catch(ex => { + console.error(`${new Date().toJSON()} ${TAG} - FAILURE_4d21b660-7676-4394-b853-642ce3617bed Process crashed:`, ex); + process.exit(1); + });