diff --git a/7nodes-test/deployContractViaHttp-pe.js b/7nodes-test/deployContractViaHttp-pe.js index 6084410..5418189 100644 --- a/7nodes-test/deployContractViaHttp-pe.js +++ b/7nodes-test/deployContractViaHttp-pe.js @@ -89,9 +89,13 @@ const bytecodeWithInitParam = simpleContract from: signAcct, isPrivate: true, privateFrom: "BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=", - privateFor: ["QfeDAys9MPDs2XHExtc84jKGHxZg/aj52DTh0vtA3Xc="], + privateFor: [ + "QfeDAys9MPDs2XHExtc84jKGHxZg/aj52DTh0vtA3Xc=", + "BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=", + ], nonce: txCount, - privacyFlag: 1, + privacyFlag: 2, + mandatoryFor: ["QfeDAys9MPDs2XHExtc84jKGHxZg/aj52DTh0vtA3Xc="], }); console.log("Contract address: ", tx.contractAddress); diff --git a/7nodes-test/multi-tenant.js b/7nodes-test/multi-tenant.js new file mode 100644 index 0000000..d71c8bd --- /dev/null +++ b/7nodes-test/multi-tenant.js @@ -0,0 +1,83 @@ +const Web3 = require("web3"); +const https = require("https"); +const axios = require("axios"); +const FormData = require("form-data"); +const Web3HttpProvider = require("web3-providers-http"); + +const Web3Quorum = require("../src"); + +const PSI = "PS1"; // To change based on the private state identifier +const url = `https://localhost:22000?PSI=${PSI}`; +const oauthURL = "https://localhost:4445/clients"; + +const getAccessToken = async () => { + try { + const instance = axios.create({ + httpsAgent: new https.Agent({ + rejectUnauthorized: false, + }), + }); + await instance.delete(`${oauthURL}/${PSI}`); + const args = { + client_id: PSI, + client_secret: "foofoo", + scope: `rpc://eth_* rpc://quorumExtension_* rpc://rpc_modules psi://${PSI}?self.eoa=0x0&node.eoa=0x0`, + }; + await instance.post(oauthURL, { + grant_types: ["client_credentials"], + token_endpoint_auth_method: "client_secret_post", + audience: ["Node1"], + ...args, + }); + + const body = new FormData(); + body.append("grant_type", "client_credentials"); + body.append("audience", "Node1"); + Object.keys(args).forEach((key) => { + body.append(key, args[key]); + }); + + const { data } = await instance.post( + `https://localhost:4444/oauth2/token`, + body, + { + headers: { + ...body.getHeaders(), + }, + } + ); + return data.access_token; + } catch (e) { + console.error(e.response.data); + } + return null; +}; +(async () => { + try { + const accessToken = await getAccessToken(); + const options = { + keepAlive: true, + headers: [{ name: "Authorization", value: `bearer ${accessToken}` }], + agent: { + https: https.Agent({ + rejectUnauthorized: false, + }), + baseUrl: url, + }, + }; + + const provider = new Web3HttpProvider(url, options); + const web3 = new Web3Quorum( + new Web3(provider), + { + privateUrl: "http://localhost:9081", + }, + true + ); + // Example of calling PSI specific API + const psi = await web3.eth.getPSI(); + console.log(`You are connected to ${psi}`); + } catch (e) { + console.error(e); + } +})(); diff --git a/docker/.env b/docker/.env index e74d1d6..512c890 100644 --- a/docker/.env +++ b/docker/.env @@ -1,5 +1,5 @@ -BESU_VERSION=latest +BESU_VERSION=21.10.6 QUORUM_TESSERA_VERSION=latest QUORUM_ETHSIGNER_VERSION=latest QUICKSTART_VERSION=$BESU_VERSION diff --git a/package-lock.json b/package-lock.json index ccf846c..8a2a333 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2754,9 +2754,9 @@ "dev": true }, "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", "dev": true }, "copy-descriptor": { @@ -4452,13 +4452,13 @@ "dev": true }, "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, @@ -8747,6 +8747,17 @@ "uuid": "^3.3.2" }, "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", @@ -10563,6 +10574,18 @@ "web3-providers-http": "1.5.2", "web3-providers-ipc": "1.5.2", "web3-providers-ws": "1.5.2" + }, + "dependencies": { + "web3-providers-http": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.5.2.tgz", + "integrity": "sha512-dUNFJc9IMYDLZnkoQX3H4ZjvHjGO6VRVCqrBrdh84wPX/0da9dOA7DwIWnG0Gv3n9ybWwu5JHQxK4MNQ444lyA==", + "dev": true, + "requires": { + "web3-core-helpers": "1.5.2", + "xhr2-cookies": "1.1.0" + } + } } }, "web3-core-subscriptions": { @@ -10750,13 +10773,80 @@ } }, "web3-providers-http": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.5.2.tgz", - "integrity": "sha512-dUNFJc9IMYDLZnkoQX3H4ZjvHjGO6VRVCqrBrdh84wPX/0da9dOA7DwIWnG0Gv3n9ybWwu5JHQxK4MNQ444lyA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.6.1.tgz", + "integrity": "sha512-xBoKOJxu10+kO3ikamXmBfrWZ/xpQOGy0ocdp7Y81B17En5TXELwlmMXt1UlIgWiyYDhjq4OwlH/VODYqHXy3A==", "dev": true, "requires": { - "web3-core-helpers": "1.5.2", + "web3-core-helpers": "1.6.1", "xhr2-cookies": "1.1.0" + }, + "dependencies": { + "@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "ethereumjs-util": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz", + "integrity": "sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==", + "dev": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "dependencies": { + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + } + } + }, + "web3-core-helpers": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.6.1.tgz", + "integrity": "sha512-om2PZvK1uoWcgMq6JfcSx3241LEIVF6qi2JuHz2SLKiKEW5UsBUaVx0mNCmcZaiuYQCyOsLS3r33q5AdM+v8ng==", + "dev": true, + "requires": { + "web3-eth-iban": "1.6.1", + "web3-utils": "1.6.1" + } + }, + "web3-eth-iban": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.6.1.tgz", + "integrity": "sha512-91H0jXZnWlOoXmc13O9NuQzcjThnWyAHyDn5Yf7u6mmKOhpJSGF/OHlkbpXt1Y4v2eJdEPaVFa+6i8aRyagE7Q==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "web3-utils": "1.6.1" + } + }, + "web3-utils": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.6.1.tgz", + "integrity": "sha512-RidGKv5kOkcerI6jQqDFDoTllQQqV+rPhTzZHhmbqtFObbYpU93uc+yG1LHivRTQhA6llIx67iudc/vzisgO+w==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "ethereum-bloom-filters": "^1.0.6", + "ethereumjs-util": "^7.1.0", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "utf8": "3.0.0" + } + } } }, "web3-providers-ipc": { diff --git a/package.json b/package.json index 06d32c4..ac7e7b4 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "eslint-plugin-jest": "^24.3.5", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-promise": "^4.3.1", + "form-data": "^4.0.0", "husky": "^6.0.0", "jest": "^26.6.3", "jsdoc": "^3.6.7", @@ -113,7 +114,8 @@ "nyc": "^15.1.0", "prettier": "^2.2.1", "wait-for-expect": "^3.0.2", - "web3": "^1.5.2" + "web3": "^1.5.2", + "web3-providers-http": "^1.6.1" }, "peerDependencies": { "web3": "^1.x" diff --git a/src/eth.js b/src/eth.js index 0096018..72814e3 100644 --- a/src/eth.js +++ b/src/eth.js @@ -127,6 +127,15 @@ function Eth(web3) { call: "eth_getPrivateTransactionReceipt", params: 1, }, + /** + * @function getPSI + * @return {String} the private state identifier (PSI) + */ + { + name: "getPSI", + call: "eth_getPSI", + params: 0, + }, ], }); diff --git a/src/priv.js b/src/priv.js index 271cd44..2290f12 100644 --- a/src/priv.js +++ b/src/priv.js @@ -299,17 +299,7 @@ function Priv(web3) { return `0x${serializedTx.toString("hex")}`; }; - const sendRawRequest = async ( - payload, - privateFor, - privacyFlag = undefined - ) => { - const privacyParams = { - privateFor, - }; - if (typeof privacyFlag !== "undefined") { - privacyParams.privacyFlag = privacyFlag; - } + const sendRawRequest = async (payload, privacyParams) => { const txHash = await web3.eth.sendRawPrivateTransaction( payload, privacyParams @@ -326,11 +316,11 @@ function Priv(web3) { ); const privateTx = web3.utils.setPrivate(serializedTx); - return sendRawRequest( - `0x${privateTx.toString("hex")}`, - options.privateFor, - options.privacyFlag - ); + return sendRawRequest(`0x${privateTx.toString("hex")}`, { + privateFor: options.privateFor, + privacyFlag: options.privacyFlag, + mandatoryFor: options.mandatoryFor, + }); } if (options.privacyGroupId && options.privateFor) { throw Error("privacyGroupId and privateFor are mutually exclusive");