From 56ee91818fa2b66d9d18bae887ad92df7dfad471 Mon Sep 17 00:00:00 2001 From: cf19drofxots Date: Wed, 14 Aug 2019 14:58:57 -0700 Subject: [PATCH 1/5] Update create channel API --- packages/apps/package.json | 2 +- packages/cf-adjudicator-contracts/package.json | 2 +- packages/cf-funding-protocol-contracts/package.json | 2 +- packages/cf-wallet.js/package.json | 2 +- packages/cf.js/package.json | 2 +- packages/firebase-client/package.json | 2 +- packages/local-ganache-server/package.json | 2 +- packages/node-provider/package.json | 2 +- packages/node/docs/source/api.md | 8 ++++---- packages/node/package.json | 2 +- .../src/methods/state-channel/create/controller.ts | 13 +++++++++---- packages/postgresql-node-connector/package.json | 2 +- packages/simple-hub-server/package.json | 2 +- packages/types/package.json | 2 +- packages/types/src/node.ts | 1 + 15 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/apps/package.json b/packages/apps/package.json index eed2be8ca..9c81950bc 100644 --- a/packages/apps/package.json +++ b/packages/apps/package.json @@ -25,7 +25,7 @@ }, "devDependencies": { "@counterfactual/cf-adjudicator-contracts": "0.0.1", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "@types/chai": "4.2.0", "@types/mocha": "5.2.7", "chai": "4.2.0", diff --git a/packages/cf-adjudicator-contracts/package.json b/packages/cf-adjudicator-contracts/package.json index d1ee35ae2..0d09f5b41 100644 --- a/packages/cf-adjudicator-contracts/package.json +++ b/packages/cf-adjudicator-contracts/package.json @@ -30,7 +30,7 @@ "solidity" ], "devDependencies": { - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "@counterfactual/typescript-typings": "0.1.0", "@types/chai": "4.2.0", "@types/node": "12.7.1", diff --git a/packages/cf-funding-protocol-contracts/package.json b/packages/cf-funding-protocol-contracts/package.json index 72724e72f..f5b46050e 100644 --- a/packages/cf-funding-protocol-contracts/package.json +++ b/packages/cf-funding-protocol-contracts/package.json @@ -31,7 +31,7 @@ ], "devDependencies": { "@counterfactual/cf-adjudicator-contracts": "0.0.1", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "@counterfactual/typescript-typings": "0.1.0", "@types/chai": "4.2.0", "@types/node": "12.7.1", diff --git a/packages/cf-wallet.js/package.json b/packages/cf-wallet.js/package.json index 237a1078b..c0f0b53b9 100644 --- a/packages/cf-wallet.js/package.json +++ b/packages/cf-wallet.js/package.json @@ -34,7 +34,7 @@ }, "dependencies": { "@counterfactual/node-provider": "0.1.2", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "ethers": "4.0.33", "eventemitter3": "^4.0.0", "global": "^4.3.2", diff --git a/packages/cf.js/package.json b/packages/cf.js/package.json index 0fdd4f55d..4e544f7f2 100644 --- a/packages/cf.js/package.json +++ b/packages/cf.js/package.json @@ -34,7 +34,7 @@ }, "dependencies": { "@counterfactual/node-provider": "0.2.0", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "ethers": "4.0.33", "eventemitter3": "^4.0.0", "rpc-server": "0.0.1" diff --git a/packages/firebase-client/package.json b/packages/firebase-client/package.json index f802e2968..2ef911df2 100644 --- a/packages/firebase-client/package.json +++ b/packages/firebase-client/package.json @@ -16,7 +16,7 @@ "lint": "tslint -c tslint.json -p ." }, "devDependencies": { - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "@firebase/app-types": "0.4.0", "@firebase/util": "0.2.25", "@types/firebase": "3.2.1", diff --git a/packages/local-ganache-server/package.json b/packages/local-ganache-server/package.json index 6a2c1b841..764c947d5 100644 --- a/packages/local-ganache-server/package.json +++ b/packages/local-ganache-server/package.json @@ -21,7 +21,7 @@ "dependencies": { "@counterfactual/cf-funding-protocol-contracts": "0.0.1", "@counterfactual/cf-adjudicator-contracts": "0.0.1", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "@counterfactual/apps": "0.1.4", "ganache-core": "2.6.1", "ethers": "4.0.33" diff --git a/packages/node-provider/package.json b/packages/node-provider/package.json index 061bb2104..87b0c25a1 100644 --- a/packages/node-provider/package.json +++ b/packages/node-provider/package.json @@ -21,7 +21,7 @@ "postinstall": "patch-package" }, "devDependencies": { - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "@types/jest": "24.0.15", "@types/node": "12.7.1", "@types/web3": "1.0.19", diff --git a/packages/node/docs/source/api.md b/packages/node/docs/source/api.md index 8e829e4b6..f319f6f21 100644 --- a/packages/node/docs/source/api.md +++ b/packages/node/docs/source/api.md @@ -252,6 +252,8 @@ Params: - `owners: string[]` - the addresses who should be the owners of the multisig +- `retryCount?: number` + - the number of times to retry _deploying the multisig_ using an expontential backoff period between each successive retry, starting with 1 second. This defaults to 3 if no retry count is provided. Result: @@ -346,8 +348,7 @@ Error(s): ### Method: `getFreeBalance` -Gets the free balance AppInstance of the specified channel for the specified -token. Defaults to ETH if no token is specified. +Gets the free balance AppInstance of the specified channel for the specified token. Defaults to ETH if no token is specified. Params: @@ -364,8 +365,7 @@ Result: Returns a mapping from address to balance in wei. The address of a node with public identifier `publicIdentifier` is defined as `fromExtendedKey(publicIdentifier).derivePath("0").address`. -Note: calling this a specific token address will return Zero even if the channel -has never had any deposits/withdrawals of that token. +Note: calling this a specific token address will return Zero even if the channel has never had any deposits/withdrawals of that token. ### Method: `getTokenIndexedFreeBalanceStates` diff --git a/packages/node/package.json b/packages/node/package.json index 92a182f7b..7757c74cb 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -58,7 +58,7 @@ "@counterfactual/cf-funding-protocol-contracts": "0.0.1", "@counterfactual/cf.js": "0.2.3", "@counterfactual/firebase-client": "0.0.3", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "ethers": "4.0.33", "eventemitter3": "^4.0.0", "loglevel": "^1.6.1", diff --git a/packages/node/src/methods/state-channel/create/controller.ts b/packages/node/src/methods/state-channel/create/controller.ts index a3955e1d8..b485de798 100644 --- a/packages/node/src/methods/state-channel/create/controller.ts +++ b/packages/node/src/methods/state-channel/create/controller.ts @@ -47,7 +47,7 @@ export default class CreateChannelController extends NodeController { requestHandler: RequestHandler, params: Node.CreateChannelParams ): Promise { - const { owners } = params; + const { owners, retryCount } = params; const { wallet, networkContext } = requestHandler; const multisigAddress = getCreate2MultisigAddress( @@ -56,7 +56,12 @@ export default class CreateChannelController extends NodeController { networkContext.MinimumViableMultisig ); - const tx = await this.sendMultisigDeployTx(wallet, owners, networkContext); + const tx = await this.sendMultisigDeployTx( + wallet, + owners, + networkContext, + retryCount + ); this.handleDeployedMultisigOnChain(multisigAddress, requestHandler, params); @@ -103,7 +108,8 @@ export default class CreateChannelController extends NodeController { private async sendMultisigDeployTx( signer: Signer, owners: string[], - networkContext: NetworkContext + networkContext: NetworkContext, + retryCount: number = 3 ): Promise { const proxyFactory = new Contract( networkContext.ProxyFactory, @@ -112,7 +118,6 @@ export default class CreateChannelController extends NodeController { ); let error; - const retryCount = 3; for (let tryCount = 0; tryCount < retryCount; tryCount += 1) { try { const extraGasLimit = tryCount * 1e6; diff --git a/packages/postgresql-node-connector/package.json b/packages/postgresql-node-connector/package.json index 06c4e06a6..609568e06 100644 --- a/packages/postgresql-node-connector/package.json +++ b/packages/postgresql-node-connector/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "pg": "7.12.1", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "reflect-metadata": "0.1.13", "typeorm": "0.2.18" }, diff --git a/packages/simple-hub-server/package.json b/packages/simple-hub-server/package.json index b971061ae..219b4eeda 100644 --- a/packages/simple-hub-server/package.json +++ b/packages/simple-hub-server/package.json @@ -40,7 +40,7 @@ "dependencies": { "@counterfactual/firebase-client": "0.0.3", "@counterfactual/node": "0.2.44", - "@counterfactual/types": "0.0.34", + "@counterfactual/types": "0.0.35", "@counterfactual/typescript-typings": "0.1.0", "@ebryn/jsonapi-ts": "0.1.17", "@koa/cors": "^3.0.0", diff --git a/packages/types/package.json b/packages/types/package.json index 0d3eb1f90..f693b9aee 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@counterfactual/types", - "version": "0.0.34", + "version": "0.0.35", "description": "TypeScript typings for common Counterfactual types", "main": "dist/index.js", "module": "dist/index.esm.js", diff --git a/packages/types/src/node.ts b/packages/types/src/node.ts index e3cabaa14..6d467d816 100644 --- a/packages/types/src/node.ts +++ b/packages/types/src/node.ts @@ -155,6 +155,7 @@ export namespace Node { export type CreateChannelParams = { owners: string[]; + retryCount?: number; }; export type CreateChannelResult = { From 361fdfc25e71ddf43d10f622aea05e8ba426fa02 Mon Sep 17 00:00:00 2001 From: cf19drofxots Date: Wed, 14 Aug 2019 15:53:27 -0700 Subject: [PATCH 2/5] Add exponential backoff retry --- packages/node/src/methods/state-channel/create/controller.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/node/src/methods/state-channel/create/controller.ts b/packages/node/src/methods/state-channel/create/controller.ts index b485de798..451a8691b 100644 --- a/packages/node/src/methods/state-channel/create/controller.ts +++ b/packages/node/src/methods/state-channel/create/controller.ts @@ -16,6 +16,7 @@ import { CHANNEL_CREATION_FAILED, NO_TRANSACTION_HASH_FOR_MULTISIG_DEPLOYMENT } from "../../errors"; +import { sleep } from "../../../../test/integration/utils"; // TODO: Add good estimate for ProxyFactory.createProxy const CREATE_PROXY_AND_SETUP_GAS = 6e6; @@ -121,6 +122,7 @@ export default class CreateChannelController extends NodeController { for (let tryCount = 0; tryCount < retryCount; tryCount += 1) { try { const extraGasLimit = tryCount * 1e6; + const tx: TransactionResponse = await proxyFactory.functions.createProxyWithNonce( networkContext.MinimumViableMultisig, new Interface(MinimumViableMultisig.abi).functions.setup.encode([ @@ -145,6 +147,8 @@ export default class CreateChannelController extends NodeController { console.error(`Channel creation attempt ${tryCount} failed: ${e}.\n Retrying ${retryCount - tryCount} more times`); } + + await sleep(1000 * tryCount ** 2); } throw new Error(`${CHANNEL_CREATION_FAILED}: ${error}`); From 3e7fae7af145db936cbf0ec2e07ff2733efa4291 Mon Sep 17 00:00:00 2001 From: cf19drofxots Date: Wed, 14 Aug 2019 19:04:52 -0700 Subject: [PATCH 3/5] Add deployed bytecode validity check for multisig deployments --- packages/node/package.json | 2 +- packages/node/src/constants.ts | 6 +++ .../state-channel/create/controller.ts | 38 +++++++++++++++++-- packages/simple-hub-server/package.json | 2 +- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/node/package.json b/packages/node/package.json index d8c57aab1..bfced7d28 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@counterfactual/node", - "version": "0.2.47", + "version": "0.2.48", "main": "dist/index.js", "iife": "dist/index.iife.js", "types": "dist/src/index.d.ts", diff --git a/packages/node/src/constants.ts b/packages/node/src/constants.ts index 684bf540f..e5f93eea6 100644 --- a/packages/node/src/constants.ts +++ b/packages/node/src/constants.ts @@ -15,3 +15,9 @@ export const CONVENTION_FOR_ETH_TOKEN_ADDRESS = AddressZero; // 25446 is 0x6366... or "cf" in ascii, for "Counterfactual". export const CF_PATH = "m/44'/60'/0'/25446"; + +// When the source code of the contract changes, the deployed bytecode will +// also change and the tests will fail as the deplyed bytecode checking +// in the create channel call will fail. +export const MULTISIG_DEPLOYED_BYTECODE = + "0x608060405273ffffffffffffffffffffffffffffffffffffffff600054163660008037600080366000845af43d6000803e6000811415603d573d6000fd5b3d6000f3fea265627a7a723058202b014062fac5bbf2f3a320134dac5811a29f916a0f071e16e4493bf4a28fe8a064736f6c634300050a0032"; diff --git a/packages/node/src/methods/state-channel/create/controller.ts b/packages/node/src/methods/state-channel/create/controller.ts index adf512ce2..828061c3d 100644 --- a/packages/node/src/methods/state-channel/create/controller.ts +++ b/packages/node/src/methods/state-channel/create/controller.ts @@ -2,11 +2,12 @@ import MinimumViableMultisig from "@counterfactual/cf-funding-protocol-contracts import ProxyFactory from "@counterfactual/cf-funding-protocol-contracts/build/ProxyFactory.json"; import { NetworkContext, Node } from "@counterfactual/types"; import { Contract, Signer } from "ethers"; -import { TransactionResponse } from "ethers/providers"; +import { Provider, TransactionResponse } from "ethers/providers"; import { Interface } from "ethers/utils"; import Queue from "p-queue"; import { jsonRpcMethod } from "rpc-server"; +import { MULTISIG_DEPLOYED_BYTECODE } from "../../../constants"; import { xkeysToSortedKthAddresses } from "../../../machine"; import { RequestHandler } from "../../../request-handler"; import { CreateChannelMessage, NODE_EVENTS } from "../../../types"; @@ -146,16 +147,47 @@ export default class CreateChannelController extends NodeController { ); } + if ( + !(await checkForCorrectDeployedByteCode( + tx!, + signer.provider!, + owners, + networkContext + )) + ) { + error = `Could not confirm the deployed multisig contract has the expected bytecode`; + await sleep(1000 * tryCount ** 2); + continue; + } + return tx; } catch (e) { error = e; console.error(`Channel creation attempt ${tryCount} failed: ${e}.\n Retrying ${retryCount - tryCount} more times`); } - - await sleep(1000 * tryCount ** 2); } throw Error(`${CHANNEL_CREATION_FAILED}: ${prettyPrintObject(error)}`); } } + +async function checkForCorrectDeployedByteCode( + // @ts-ignore + tx: TransactionResponse, + provider: Provider, + owners: string[], + networkContext: NetworkContext +): Promise { + const multisigAddress = getCreate2MultisigAddress( + owners, + networkContext.ProxyFactory, + networkContext.MinimumViableMultisig + ); + + const multisigDeployedBytecode = await provider.getCode( + multisigAddress, + tx.blockHash + ); + return MULTISIG_DEPLOYED_BYTECODE === multisigDeployedBytecode; +} diff --git a/packages/simple-hub-server/package.json b/packages/simple-hub-server/package.json index 99050d7d1..a1721ef1e 100644 --- a/packages/simple-hub-server/package.json +++ b/packages/simple-hub-server/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "@counterfactual/firebase-client": "0.0.3", - "@counterfactual/node": "0.2.47", + "@counterfactual/node": "0.2.48", "@counterfactual/types": "0.0.35", "@counterfactual/typescript-typings": "0.1.0", "@ebryn/jsonapi-ts": "0.1.17", From fce5103b150f6958d7d48b2a1562b42f11ca8b0a Mon Sep 17 00:00:00 2001 From: cf19drofxots Date: Wed, 14 Aug 2019 19:07:23 -0700 Subject: [PATCH 4/5] Fix doc and versioning --- packages/node/docs/source/api.md | 2 +- packages/node/package.json | 2 +- packages/simple-hub-server/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/node/docs/source/api.md b/packages/node/docs/source/api.md index f319f6f21..be53bea90 100644 --- a/packages/node/docs/source/api.md +++ b/packages/node/docs/source/api.md @@ -365,7 +365,7 @@ Result: Returns a mapping from address to balance in wei. The address of a node with public identifier `publicIdentifier` is defined as `fromExtendedKey(publicIdentifier).derivePath("0").address`. -Note: calling this a specific token address will return Zero even if the channel has never had any deposits/withdrawals of that token. +Note: calling this with a specific token address will return Zero even if the channel has never had any deposits/withdrawals of that token. ### Method: `getTokenIndexedFreeBalanceStates` diff --git a/packages/node/package.json b/packages/node/package.json index bfced7d28..d8c57aab1 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@counterfactual/node", - "version": "0.2.48", + "version": "0.2.47", "main": "dist/index.js", "iife": "dist/index.iife.js", "types": "dist/src/index.d.ts", diff --git a/packages/simple-hub-server/package.json b/packages/simple-hub-server/package.json index a1721ef1e..99050d7d1 100644 --- a/packages/simple-hub-server/package.json +++ b/packages/simple-hub-server/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "@counterfactual/firebase-client": "0.0.3", - "@counterfactual/node": "0.2.48", + "@counterfactual/node": "0.2.47", "@counterfactual/types": "0.0.35", "@counterfactual/typescript-typings": "0.1.0", "@ebryn/jsonapi-ts": "0.1.17", From d47c8069d54b0ce8676e3d33b3bc94eaa0bf9a76 Mon Sep 17 00:00:00 2001 From: cf19drofxots Date: Wed, 14 Aug 2019 19:08:17 -0700 Subject: [PATCH 5/5] Remove ignore --- packages/node/src/methods/state-channel/create/controller.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/node/src/methods/state-channel/create/controller.ts b/packages/node/src/methods/state-channel/create/controller.ts index 828061c3d..68eb97598 100644 --- a/packages/node/src/methods/state-channel/create/controller.ts +++ b/packages/node/src/methods/state-channel/create/controller.ts @@ -173,7 +173,6 @@ export default class CreateChannelController extends NodeController { } async function checkForCorrectDeployedByteCode( - // @ts-ignore tx: TransactionResponse, provider: Provider, owners: string[],