From 458e4e55764cfd0957c259b2c50c9e42b55ebb07 Mon Sep 17 00:00:00 2001 From: apostolof Date: Sun, 7 Feb 2021 17:51:05 +0200 Subject: [PATCH 1/3] refactor: add contracts provider integration to pinner --- .../src/redux/sagas/orbitSaga.js | 4 +- packages/concordia-pinner/package.json | 1 + packages/concordia-pinner/src/index.js | 27 +++++++--- .../src/utils/drizzleUtils.js | 50 +++++++++++++++++++ .../src/constants/configuration/defaults.js | 2 + .../src/environment/interpolated/pinner.js | 5 +- .../src/environment/pinnerEnv.js | 2 + 7 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 packages/concordia-pinner/src/utils/drizzleUtils.js diff --git a/packages/concordia-app/src/redux/sagas/orbitSaga.js b/packages/concordia-app/src/redux/sagas/orbitSaga.js index 1e3a8c4..8852a8e 100644 --- a/packages/concordia-app/src/redux/sagas/orbitSaga.js +++ b/packages/concordia-app/src/redux/sagas/orbitSaga.js @@ -5,9 +5,9 @@ import { import { breezeActions } from '@ezerous/breeze'; import { drizzleActions } from '@ezerous/drizzle'; -import { contracts } from 'concordia-contracts'; import { EthereumContractIdentityProvider } from '@ezerous/eth-identity-provider'; import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; +import drizzleOptions from '../../options/drizzleOptions'; function* initOrbitDatabases(action) { const { account, breeze } = action; @@ -24,7 +24,7 @@ function* orbitSaga() { const { drizzle: { web3 } } = res[0]; const networkId = yield call([web3.eth.net, web3.eth.net.getId]); - const contractAddress = contracts + const contractAddress = drizzleOptions.contracts .find((contract) => contract.contractName === FORUM_CONTRACT) .networks[networkId].address; diff --git a/packages/concordia-pinner/package.json b/packages/concordia-pinner/package.json index d5b0ccc..964198a 100644 --- a/packages/concordia-pinner/package.json +++ b/packages/concordia-pinner/package.json @@ -32,6 +32,7 @@ "orbit-db": "~0.26.0", "orbit-db-identity-provider": "~0.3.1", "rimraf": "~3.0.2", + "unirest": "^0.6.0", "web3": "~1.3.0", "web3-eth-contract": "^1.3.1", "wrtc": "~0.4.6" diff --git a/packages/concordia-pinner/src/index.js b/packages/concordia-pinner/src/index.js index 401bced..aa5dbb2 100644 --- a/packages/concordia-pinner/src/index.js +++ b/packages/concordia-pinner/src/index.js @@ -7,6 +7,7 @@ import getWeb3ProviderUrl from 'concordia-shared/src/utils/web3'; import { createOrbitInstance, getPeerDatabases, openKVDBs } from './utils/orbitUtils'; import ipfsOptions from './options/ipfsOptions'; import startAPI from './app'; +import downloadContractArtifacts from './utils/drizzleUtils'; process.on('unhandledRejection', (error) => { // This happens when attempting to initialize without any available Swarm addresses (e.g. Rendezvous) @@ -21,16 +22,26 @@ process.on('unhandledRejection', (error) => { }); const getDeployedContract = async (web3) => { - const forumContract = contracts.find((contract) => contract.contractName === FORUM_CONTRACT); + let forumContractPromise; - return web3.eth.net.getId() - .then((networkId) => forumContract.networks[networkId].address) - .then((contractAddress) => { - Contract.setProvider(getWeb3ProviderUrl()); - const contract = new Contract(forumContract.abi, contractAddress); + if (process.env.USE_EXTERNAL_CONTRACTS_PROVIDER) { + console.log('Downloading contracts.'); + forumContractPromise = downloadContractArtifacts() + .then((remoteContracts) => remoteContracts + .find((remoteContract) => remoteContract.contractName === FORUM_CONTRACT)); + } else { + forumContractPromise = Promise.resolve(contracts.find((contract) => contract.contractName === FORUM_CONTRACT)); + } + + return forumContractPromise + .then((forumContract) => web3.eth.net.getId() + .then((networkId) => forumContract.networks[networkId].address) + .then((contractAddress) => { + Contract.setProvider(getWeb3ProviderUrl()); + const contract = new Contract(forumContract.abi, contractAddress); - return { contract, contractAddress }; - }); + return { contract, contractAddress }; + })); }; // Open & replicate databases of existing users diff --git a/packages/concordia-pinner/src/utils/drizzleUtils.js b/packages/concordia-pinner/src/utils/drizzleUtils.js new file mode 100644 index 0000000..028c3e5 --- /dev/null +++ b/packages/concordia-pinner/src/utils/drizzleUtils.js @@ -0,0 +1,50 @@ +import unirest from 'unirest'; +import { + contractsProviderHost, + contractsProviderPort, + contractsVersionHash, +} from 'concordia-shared/src/environment/interpolated/contractsProvider'; +import { pinnerApiHost, pinnerApiPort } from 'concordia-shared/src/environment/interpolated/pinner'; +import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; + +function getContractsDownloadRequest() { + const HOST = pinnerApiHost; + const PORT = pinnerApiPort; + + return unirest( + 'GET', + `http://${contractsProviderHost}:${contractsProviderPort}/contracts/${contractsVersionHash}`, + ).headers({ + 'Access-Control-Allow-Origin': `${HOST}:${PORT}`, + 'Access-Control-Allow-Credentials': 'true', + }); +} + +const validateRemoteContracts = (remoteContracts) => { + if (!remoteContracts + .map((remoteContract) => remoteContract.contractName) + .includes(FORUM_CONTRACT)) { + throw new Error('Forum contract is missing from artifacts.'); + } +}; + +const downloadContractArtifacts = () => { + const request = getContractsDownloadRequest(); + + return new Promise((resolve, reject) => request + .end((response) => { + if (response.error) { + reject(new Error(`Remote contract artifacts download request failed!\n${response.error}`)); + } + + resolve(response.raw_body); + })).then((contractsRawData) => { + const remoteContracts = JSON.parse(contractsRawData); + + validateRemoteContracts(remoteContracts); + + return remoteContracts; + }); +}; + +export default downloadContractArtifacts; diff --git a/packages/concordia-shared/src/constants/configuration/defaults.js b/packages/concordia-shared/src/constants/configuration/defaults.js index 07ee374..6c68265 100644 --- a/packages/concordia-shared/src/constants/configuration/defaults.js +++ b/packages/concordia-shared/src/constants/configuration/defaults.js @@ -4,6 +4,7 @@ const CONTRACTS_PROVIDER_PORT_DEFAULT = '8400'; const CONTRACTS_VERSION_HASH_DEFAULT = 'latest'; // Pinner +const PINNER_API_HOST_DEFAULT = '127.0.0.1'; const PINNER_API_PORT_DEFAULT = 4444; // Rendezvous @@ -25,6 +26,7 @@ module.exports = Object.freeze({ hash: CONTRACTS_VERSION_HASH_DEFAULT, }, pinner: { + host: PINNER_API_HOST_DEFAULT, port: PINNER_API_PORT_DEFAULT, }, rendezvous: { diff --git a/packages/concordia-shared/src/environment/interpolated/pinner.js b/packages/concordia-shared/src/environment/interpolated/pinner.js index 5c81a88..e4007d5 100644 --- a/packages/concordia-shared/src/environment/interpolated/pinner.js +++ b/packages/concordia-shared/src/environment/interpolated/pinner.js @@ -1,12 +1,15 @@ const { pinner: { + host: PINNER_API_HOST_DEFAULT, port: PINNER_API_PORT_DEFAULT, }, } = require('../../constants/configuration/defaults'); -const { pinnerApiPortEnv } = require('../pinnerEnv'); +const { pinnerApiHostEnv, pinnerApiPortEnv } = require('../pinnerEnv'); +const pinnerApiHost = pinnerApiHostEnv || PINNER_API_HOST_DEFAULT; const pinnerApiPort = pinnerApiPortEnv || PINNER_API_PORT_DEFAULT; module.exports = { + pinnerApiHost, pinnerApiPort, }; diff --git a/packages/concordia-shared/src/environment/pinnerEnv.js b/packages/concordia-shared/src/environment/pinnerEnv.js index 2ab5cbf..d1df0bf 100644 --- a/packages/concordia-shared/src/environment/pinnerEnv.js +++ b/packages/concordia-shared/src/environment/pinnerEnv.js @@ -1,7 +1,9 @@ // Depending on the package user (app in contrast to any of the other packages) the env var names should either include // the REACT_APP_ prefix or not +const pinnerApiHostEnv = process.env.REACT_APP_PINNER_API_HOST || process.env.PINNER_API_HOST; const pinnerApiPortEnv = process.env.REACT_APP_PINNER_API_PORT || process.env.PINNER_API_PORT; module.exports = { + pinnerApiHostEnv, pinnerApiPortEnv, }; From 7b5380668c7fc099bfb1f45217b8a8b4d454bdca Mon Sep 17 00:00:00 2001 From: apostolof Date: Sun, 7 Feb 2021 19:04:49 +0200 Subject: [PATCH 2/3] feat: dockerize pinner application --- docker/Makefile | 13 ++++++++++++ docker/concordia-pinner/Dockerfile | 34 ++++++++++++++++++++++++++++++ docker/env/pinner.env | 16 ++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 docker/concordia-pinner/Dockerfile create mode 100644 docker/env/pinner.env diff --git a/docker/Makefile b/docker/Makefile index 0b47f47..4221351 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -1,6 +1,7 @@ PACKAGES := $(abspath ${CURDIR}/../packages) REPORTS := $(abspath ${CURDIR}/reports) GANACHE_VOLUMES := $(abspath ${CURDIR}/ganache/volumes) +PINNER_VOLUMES := $(abspath ${CURDIR}/pinner/volumes) run: compose-run build-contracts-migrate run-contracts-migrate build-app run-app @echo "Concordia is up and running, head over to http://localhost:7777." @@ -62,6 +63,18 @@ run-app: run-app-host-chain: @docker run -d --env-file=./env/concordia.env --name concordia-app --net=host concordia-app:latest +# Contracts provider targets +build-pinner: + @docker build ../ -f ./concordia-pinner/Dockerfile -t ecentrics/concordia-pinner --build-arg TZ=Europe/Athens +run-pinner-staging: + @docker run -d -v ${PINNER_VOLUMES}/orbitdb:/data/orbitdb --env-file=./env/pinner.env -e NODE_ENV=production -p 4444:4444 --name concordia-pinner ecentrics/concordia-pinner:latest +run-pinner: + @docker run -d -v ${PINNER_VOLUMES}/orbitdb:/data/orbitdb --env-file=./env/pinner.env -p 4444:4444 --name concordia-pinner ecentrics/concordia-pinner:latest +run-pinner-staging-host: + @docker run -d -v ${PINNER_VOLUMES}/orbitdb:/data/orbitdb --env-file=./env/pinner.env -e NODE_ENV=production --net=host --name concordia-pinner ecentrics/concordia-pinner:latest +run-pinner-host: + @docker run -d -v ${PINNER_VOLUMES}/orbitdb:/data/orbitdb --env-file=./env/pinner.env --net=host --name concordia-pinner ecentrics/concordia-pinner:latest + # Other clean-images: @docker rmi `docker images -q -f "dangling=true"` diff --git a/docker/concordia-pinner/Dockerfile b/docker/concordia-pinner/Dockerfile new file mode 100644 index 0000000..e44ad70 --- /dev/null +++ b/docker/concordia-pinner/Dockerfile @@ -0,0 +1,34 @@ +# -------------------------------------------------- +# Stage 1 (Runtime) +# -------------------------------------------------- +FROM node:14-buster as runtime +LABEL maintainers.1="Apostolos Fanakis " +LABEL maintainers.2="Panagiotis Nikolaidis " +LABEL gr.thmmy.ecentrics.concordia-image.name="pinner" + +# Fix timezome (needed for timestamps on report files) +ARG TZ +ENV TZ=${TZ} +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +WORKDIR /usr/src/concordia + +# Copy the root package.json and yarn.lock +COPY ./package.json . +COPY ./yarn.lock . + +# Copy the pinner, contracts and shared package.json files, then install modules +COPY ./packages/concordia-pinner/package.json ./packages/concordia-pinner/ +COPY ./packages/concordia-contracts/package.json ./packages/concordia-contracts/ +COPY ./packages/concordia-shared/package.json ./packages/concordia-shared/ + +RUN yarn install --frozen-lockfile --network-timeout 100000 + +# Gets the rest of the source code +COPY ./packages/concordia-shared ./packages/concordia-shared +COPY ./packages/concordia-contracts ./packages/concordia-contracts +COPY ./packages/concordia-pinner ./packages/concordia-pinner + +WORKDIR /usr/src/concordia/packages/concordia-pinner + +ENTRYPOINT ["yarn", "start"] \ No newline at end of file diff --git a/docker/env/pinner.env b/docker/env/pinner.env new file mode 100644 index 0000000..e723d45 --- /dev/null +++ b/docker/env/pinner.env @@ -0,0 +1,16 @@ +USE_EXTERNAL_CONTRACTS_PROVIDER=true +ORBIT_DIRECTORY=/data/orbitdb + +#CONTRACTS_PROVIDER_HOST=contracts-provider +CONTRACTS_PROVIDER_HOST=127.0.0.1 +CONTRACTS_PROVIDER_PORT=8400 +CONTRACTS_VERSION_HASH=latest + +PINNER_API_HOST=127.0.0.1 +PINNER_API_PORT=4444 + +RENDEZVOUS_HOST=127.0.0.1 +RENDEZVOUS_PORT=9090 + +WEB3_HOST=127.0.0.1 +WEB3_PORT=8545 From 78e209ddcede621a575fdd512ae09478642c308d Mon Sep 17 00:00:00 2001 From: apostolof Date: Sun, 7 Feb 2021 19:10:39 +0200 Subject: [PATCH 3/3] refactor: minor react scripts adjustment --- packages/concordia-contracts/package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/concordia-contracts/package.json b/packages/concordia-contracts/package.json index 6c46a16..41cbd3a 100644 --- a/packages/concordia-contracts/package.json +++ b/packages/concordia-contracts/package.json @@ -10,8 +10,10 @@ "_eslint": "yarn eslint . --format table", "_solhint": "yarn solhint --formatter table contracts/*.sol test/*.sol", "test": "yarn truffle test", - "migrate": "yarn _migrate --network develop && yarn upload", - "migrate-reset": "yarn _migrate --network develop --reset && yarn upload", + "migrate": "yarn _migrate --network develop", + "migrate-reset": "yarn _migrate --network develop --reset", + "migrate-upload": "yarn _migrate --network develop && yarn upload", + "migrate-reset-upload": "yarn _migrate --network develop --reset && yarn upload", "_migrate": "yarn truffle migrate", "upload": "node ./utils/contractsProviderUtils.js ${npm_package_version}-dev latest" },