diff --git a/.circleci/config.yml b/.circleci/config.yml index b3ef664..18daaeb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -147,8 +147,8 @@ jobs: docker build -t tests ./tests docker create --env-file ./tests/.env --name tests tests docker network connect binance_net tests - docker network connect blockchain_side tests - docker network connect blockchain_home tests + docker network connect ethereum_side_rpc_net tests + docker network connect ethereum_home_rpc_net tests docker network connect validator1_test_network tests docker network connect validator2_test_network tests docker network connect validator3_test_network tests diff --git a/DEMO.md b/DEMO.md index 9dde9b6..2d5a5f4 100644 --- a/DEMO.md +++ b/DEMO.md @@ -331,21 +331,13 @@ Make sure, to first run demo in development mode, before trying to run it in the docker kill binance-testnet_http-api_1 docker kill binance-testnet_node_1 docker kill binance-testnet_api-server_1 - docker kill ganache_home - docker kill ganache_side + docker kill ethereum-testnet_ganache_home_1 + docker kill ethereum-testnet_ganache_side_1 + docker kill ethereum-testnet_side_oracle_1 ``` -3. Remove virtual networks: +3. Remove testnets and validators data: ``` - docker network rm binance_net - docker network rm blockchain_home - docker network rm blockchain_side - docker network rm validator1_test_network - docker network rm validator2_test_network - docker network rm validator3_test_network - ``` -4. Remove testnets and validators data: - ``` - TARGET_NETWORK= ./demo/clean.sh + TARGET_NETWORK=development ./demo/clean.sh ``` #### Testing tools for both sides of the bridge diff --git a/demo/clean.sh b/demo/clean.sh index 0b5586d..bf59570 100755 --- a/demo/clean.sh +++ b/demo/clean.sh @@ -15,14 +15,25 @@ docker kill ganache_home ganache_side > /dev/null 2>&1 || true docker rm ganache_home ganache_side > /dev/null 2>&1 || true docker kill $(docker ps | grep binance-testnet_ | awk '{print $1}') > /dev/null 2>&1 || true docker rm $(docker ps -a | grep binance-testnet_ | awk '{print $1}') > /dev/null 2>&1 || true +docker kill $(docker ps | grep ethereum-testnet_ | awk '{print $1}') > /dev/null 2>&1 || true +docker rm $(docker ps -a | grep ethereum-testnet_ | awk '{print $1}') > /dev/null 2>&1 || true if [[ "$TARGET_NETWORK" == "development" ]]; then docker volume rm ganache_side_data > /dev/null 2>&1 || true docker volume rm ganache_home_data > /dev/null 2>&1 || true docker volume rm binance_data > /dev/null 2>&1 || true docker volume rm binance_marketdata > /dev/null 2>&1 || true + + docker network rm ethereum_side_rpc_net > /dev/null 2>&1 || true + docker network rm ethereum_home_rpc_net > /dev/null 2>&1 || true + docker network rm binance_net > /dev/null 2>&1 || true + docker network rm binance-testnet_binance_rpc_net > /dev/null 2>&1 || true fi +docker network rm validator1_test_network > /dev/null 2>&1 || true +docker network rm validator2_test_network > /dev/null 2>&1 || true +docker network rm validator3_test_network > /dev/null 2>&1 || true + for (( I = 1; I < 4; ++I )); do DIRNAME="validator$I" rm -rf "$DIRNAME/$TARGET_NETWORK" diff --git a/demo/start-ethereum-environment.sh b/demo/start-ethereum-environment.sh index 3396f86..19a3800 100755 --- a/demo/start-ethereum-environment.sh +++ b/demo/start-ethereum-environment.sh @@ -13,29 +13,8 @@ DEPLOY_DIR="`pwd`/src/deploy" TEST_SERVICES_DIR="`pwd`/src/test-services" DEMO_DIR="`pwd`/demo" -start_dev_blockchain_networks() { - echo "Starting side test blockchain" - - docker kill ganache_side > /dev/null 2>&1 || true - docker network create blockchain_side > /dev/null 2>&1 || true - docker volume create ganache_side_data > /dev/null 2>&1 || true - docker run -d --network blockchain_side --rm --name ganache_side -v "ganache_side_data:/app/db" \ - -p "7545:8545" \ - trufflesuite/ganache-cli:latest \ - -m "shrug dwarf easily blade trigger lucky reopen cage lake scatter desk boat" -i 33 --db /app/db -b "$BLOCK_TIME" --noVMErrorsOnRPCResponse - - echo "Starting home test blockchain" - - docker kill ganache_home > /dev/null 2>&1 || true - docker network create blockchain_home > /dev/null 2>&1 || true - docker volume create ganache_home_data > /dev/null 2>&1 || true - docker run -d --network blockchain_home --rm --name ganache_home -v "ganache_home_data:/app/db" \ - -p "8545:8545" \ - trufflesuite/ganache-cli:latest \ - -m "shrug dwarf easily blade trigger lucky reopen cage lake scatter desk boat" -i 44 --db /app/db -b "$BLOCK_TIME" --noVMErrorsOnRPCResponse - - sleep 4 -} +HOME_NETWORK="ethereum_home_rpc_net" +SIDE_NETWORK="ethereum_side_rpc_net" deploy_token() { echo "Compiling and deploying erc20" @@ -45,7 +24,7 @@ deploy_token() { echo "Deploying" if [[ "$TARGET_NETWORK" == "development" ]]; then - TOKEN_ADDRESS=$(docker run --network blockchain_home --rm -v "$DEPLOY_DIR/deploy-test/build:/build/build" --env-file "$DEPLOY_DIR/deploy-test/.env.development" \ + TOKEN_ADDRESS=$(docker run --network "$HOME_NETWORK" --rm -v "$DEPLOY_DIR/deploy-test/build:/build/build" --env-file "$DEPLOY_DIR/deploy-test/.env.development" \ deploy_test \ --network home 2>&1 \ | grep "contract address" \ @@ -67,7 +46,7 @@ deploy_bridge() { echo "Deploying" if [[ "$TARGET_NETWORK" == "development" ]]; then - BRIDGE_ADDRESS=$(docker run --network blockchain_home --rm -v "$DEPLOY_DIR/deploy-home/build:/build/build" --env-file "$DEPLOY_DIR/deploy-home/.env.development" \ + BRIDGE_ADDRESS=$(docker run --network "$HOME_NETWORK" --rm -v "$DEPLOY_DIR/deploy-home/build:/build/build" --env-file "$DEPLOY_DIR/deploy-home/.env.development" \ deploy_home \ --network home 2>&1 \ | grep "contract address" \ @@ -89,7 +68,7 @@ deploy_db() { echo "Deploying" if [[ "$TARGET_NETWORK" == "development" ]]; then - SHARED_DB_ADDRESS=$(docker run --network blockchain_side --rm -v "$DEPLOY_DIR/deploy-side/build:/build/build" --env-file "$DEPLOY_DIR/deploy-side/.env.development" \ + SHARED_DB_ADDRESS=$(docker run --network "$SIDE_NETWORK" --rm -v "$DEPLOY_DIR/deploy-side/build:/build/build" --env-file "$DEPLOY_DIR/deploy-side/.env.development" \ deploy_side \ --network side 2>&1 \ | grep "contract address" \ @@ -131,25 +110,39 @@ deploy_all() { sed -i 's/HOME_TOKEN_ADDRESS=.*$/HOME_TOKEN_ADDRESS='"$TOKEN_ADDRESS"'/' "$TEST_SERVICES_DIR/ethereumSend/.env.$TARGET_NETWORK" } - - - if [[ "$TARGET_NETWORK" == "development" ]]; then if [[ "$(docker volume ls | grep ganache_side_data)" ]] || [[ "$(docker volume ls | grep ganache_home_data)" ]]; then - echo "Restarting dev blockchain networks" + echo "Restarting ethereum test network" else - echo "Starting dev blockchain networks and deploying contracts" + echo "Creating new ethereum test network" + + echo "Removing old environment" + docker kill $(docker ps -a | grep ethereum-testnet_ | awk '{print $1}') > /dev/null 2>&1 || true + docker rm $(docker ps -a | grep ethereum-testnet_ | awk '{print $1}') > /dev/null 2>&1 || true + docker volume rm ganache_side_data > /dev/null 2>&1 || true + docker volume rm ganache_home_data > /dev/null 2>&1 || true + + docker network create ethereum_side_rpc_net > /dev/null 2>&1 || true + docker network create ethereum_home_rpc_net > /dev/null 2>&1 || true + docker volume create ganache_side_data > /dev/null 2>&1 || true + docker volume create ganache_home_data > /dev/null 2>&1 || true + need_to_deploy=true fi - start_dev_blockchain_networks + echo "Starting ethereum test environment" + + BLOCK_TIME="$BLOCK_TIME" docker-compose -f ./src/ethereum-testnet/docker-compose.yml up --build -d + + sleep 4 if [[ -n "$need_to_deploy" ]]; then deploy_all else echo "Contracts are already deployed, run clean.sh first if you want to redeploy everything" fi + else echo "Deploying to the staging blockchain environment" diff --git a/src/ethereum-testnet/docker-compose.yml b/src/ethereum-testnet/docker-compose.yml new file mode 100644 index 0000000..4003362 --- /dev/null +++ b/src/ethereum-testnet/docker-compose.yml @@ -0,0 +1,37 @@ +version: '3.0' +services: + ganache_side: + image: trufflesuite/ganache-cli:latest + command: ["-m", "shrug dwarf easily blade trigger lucky reopen cage lake scatter desk boat", "-i", "33", "--db", "/app/db", "-b", "${BLOCK_TIME}", "--noVMErrorsOnRPCResponse"] + networks: + - ethereum_side_rpc_net + ports: + - '7545:8545' + volumes: + - 'ganache_side_data:/app/db' + ganache_home: + image: trufflesuite/ganache-cli:latest + command: ["-m", "shrug dwarf easily blade trigger lucky reopen cage lake scatter desk boat", "-i", "44", "--db", "/app/db", "-b", "${BLOCK_TIME}", "--noVMErrorsOnRPCResponse"] + networks: + - ethereum_home_rpc_net + ports: + - '8545:8545' + volumes: + - 'ganache_home_data:/app/db' + side_oracle: + build: side-oracle + image: side-oracle + env_file: side-oracle/.env.development + networks: + - ethereum_side_rpc_net + - ethereum_home_rpc_net +networks: + ethereum_side_rpc_net: + external: true + ethereum_home_rpc_net: + external: true +volumes: + ganache_side_data: + external: true + ganache_home_data: + external: true diff --git a/src/ethereum-testnet/side-oracle/.env.development b/src/ethereum-testnet/side-oracle/.env.development new file mode 100644 index 0000000..08ced61 --- /dev/null +++ b/src/ethereum-testnet/side-oracle/.env.development @@ -0,0 +1,9 @@ +HOME_RPC_URL=http://ganache_home:8545 +HOME_BRIDGE_ADDRESS=0x44c158FE850821ae69DaF37AADF5c539e9d0025B + +HOME_PRIVATE_KEY=e2aeb24eaa63102d0c0821717c3b6384abdabd7af2ad4ec8e650dce300798b27 + +SIDE_RPC_URL=http://ganache_side:8545 +SIDE_SHARED_DB_ADDRESS=0xd5fE0D28e058D375b0b038fFbB446Da37E85fFdc +SIDE_MAX_FETCH_RANGE_SIZE=100 + diff --git a/src/ethereum-testnet/side-oracle/Dockerfile b/src/ethereum-testnet/side-oracle/Dockerfile new file mode 100644 index 0000000..ad6c12d --- /dev/null +++ b/src/ethereum-testnet/side-oracle/Dockerfile @@ -0,0 +1,14 @@ +FROM node:10.16.0-alpine + +WORKDIR /side-oracle + +RUN apk update && \ + apk add libssl1.1 libressl-dev curl + +COPY ./package.json /side-oracle/ + +RUN npm install + +COPY ./index.js ./ + +ENTRYPOINT ["node", "index.js"] diff --git a/src/ethereum-testnet/side-oracle/index.js b/src/ethereum-testnet/side-oracle/index.js new file mode 100644 index 0000000..f567bb7 --- /dev/null +++ b/src/ethereum-testnet/side-oracle/index.js @@ -0,0 +1,107 @@ +const ethers = require('ethers') + +const { + HOME_PRIVATE_KEY, HOME_RPC_URL, HOME_BRIDGE_ADDRESS, SIDE_RPC_URL, SIDE_SHARED_DB_ADDRESS +} = process.env +const SIDE_MAX_FETCH_RANGE_SIZE = parseInt(process.env.SIDE_MAX_FETCH_RANGE_SIZE, 10) + +const bridgeAbi = [ + 'function applyMessage(bytes message, bytes signatures)', + 'function getThreshold(uint epoch) view returns (uint)', + 'function getValidatorsInEpoch(uint epoch) view returns (address[])' +] +const sharedDbAbi = [ + 'event NewMessage(bytes32 msgHash)', + 'function getSignatures(bytes32 msgHash, address[] validators) view returns (bytes)' +] + +let homeProvider +let sideProvider +let bridge +let sharedDb +let homeWallet +let nonce +let blockNumber = 0 + +async function delay(ms) { + await new Promise((res) => setTimeout(res, ms)) +} + +async function handleNewMessage(event) { + const { msgHash } = event.values + const message = (await sharedDb.signedMessages(msgHash))[0] + const epoch = parseInt(message.slice(30, 3).toString('hex'), 16) + const [threshold, validators] = await Promise.all([ + bridge.getThreshold(epoch), + bridge.getValidatorsInEpoch(epoch) + ]) + + while (true) { + const signatures = await sharedDb.getSignatures(msgHash, validators) + if (signatures.length / 65 >= threshold) { + const tx = await bridge.applyMessage(message, signatures, { + gasLimit: 1000000, + nonce + }) + await tx.wait() + nonce += 1 + break + } + } +} + +async function initialize() { + await delay(5000) + sideProvider = new ethers.providers.JsonRpcProvider(SIDE_RPC_URL) + homeProvider = new ethers.providers.JsonRpcProvider(HOME_RPC_URL) + bridge = new ethers.Contract(HOME_BRIDGE_ADDRESS, bridgeAbi, homeProvider) + sharedDb = new ethers.Contract(SIDE_SHARED_DB_ADDRESS, sharedDbAbi, sideProvider) + + homeWallet = new ethers.Wallet(HOME_PRIVATE_KEY, homeProvider) + + nonce = await homeWallet.getTransactionCount() +} + +async function loop() { + const latestBlockNumber = await sideProvider.getBlockNumber() + if (latestBlockNumber < blockNumber) { + console.log(`No block after ${latestBlockNumber}`) + return + } + + const endBlock = Math.min(latestBlockNumber, blockNumber + SIDE_MAX_FETCH_RANGE_SIZE - 1) + + console.log(`Watching events in blocks #${blockNumber}-${endBlock}`) + + const bridgeEvents = (await sideProvider.getLogs({ + address: SIDE_SHARED_DB_ADDRESS, + fromBlock: blockNumber, + toBlock: endBlock, + topics: [] + })) + + for (let i = 0; i < bridgeEvents.length; i += 1) { + const event = bridge.interface.parseLog(bridgeEvents[i]) + console.log('Consumed event', event, bridgeEvents[i]) + switch (event.name) { + case 'NewMessage': + await handleNewMessage(event) + break + default: + console.log('Unknown event %o', event) + } + } + + blockNumber = endBlock + 1 +} + +async function main() { + await initialize() + + while (true) { + await delay(2000) + await loop() + } +} + +main() diff --git a/src/ethereum-testnet/side-oracle/package.json b/src/ethereum-testnet/side-oracle/package.json new file mode 100644 index 0000000..f09b986 --- /dev/null +++ b/src/ethereum-testnet/side-oracle/package.json @@ -0,0 +1,10 @@ +{ + "name": "side-oracle", + "version": "0.0.1", + "dependencies": { + "ethers": "4.0.33" + }, + "engines": { + "node": ">=10.6.0" + } +} diff --git a/src/oracle/docker-compose-test.yml b/src/oracle/docker-compose-test.yml index 939f22f..4dbadd6 100644 --- a/src/oracle/docker-compose-test.yml +++ b/src/oracle/docker-compose-test.yml @@ -23,8 +23,8 @@ services: test_network: aliases: - local_proxy - blockchain_home: - blockchain_side: + ethereum_home_rpc_net: + ethereum_side_rpc_net: binance_net: keygen: image: keygen-client @@ -96,7 +96,7 @@ services: - LOG_LEVEL networks: - test_network - - blockchain_home + - ethereum_home_rpc_net bnc-watcher: build: dockerfile: bncWatcher/Dockerfile @@ -118,9 +118,9 @@ services: - binance_net networks: test_network: - blockchain_side: + ethereum_side_rpc_net: external: true - blockchain_home: + ethereum_home_rpc_net: external: true binance_net: external: true diff --git a/src/test-services/ethereumBalance/run.sh b/src/test-services/ethereumBalance/run.sh index 9dbef3f..58dc621 100755 --- a/src/test-services/ethereumBalance/run.sh +++ b/src/test-services/ethereumBalance/run.sh @@ -10,7 +10,7 @@ TARGET_NETWORK=${TARGET_NETWORK:=development} docker build -t ethereum-balance . > /dev/null if [[ "$TARGET_NETWORK" == "development" ]]; then - docker run --network blockchain_home --rm --env-file ".env.$TARGET_NETWORK" ethereum-balance $@ + docker run --network ethereum_home_rpc_net --rm --env-file ".env.$TARGET_NETWORK" ethereum-balance $@ else docker run --rm --env-file ".env.$TARGET_NETWORK" ethereum-balance $@ fi diff --git a/src/test-services/ethereumSend/run.sh b/src/test-services/ethereumSend/run.sh index 3808257..8980f27 100755 --- a/src/test-services/ethereumSend/run.sh +++ b/src/test-services/ethereumSend/run.sh @@ -10,7 +10,7 @@ TARGET_NETWORK=${TARGET_NETWORK:=development} docker build -t ethereum-send . > /dev/null if [[ "$TARGET_NETWORK" == "development" ]]; then - docker run --network blockchain_home --rm --env-file ".env.$TARGET_NETWORK" -e "PRIVATE_KEY=$PRIVATE_KEY" ethereum-send $@ + docker run --network ethereum_home_rpc_net --rm --env-file ".env.$TARGET_NETWORK" -e "PRIVATE_KEY=$PRIVATE_KEY" ethereum-send $@ else docker run --rm --env-file ".env.$TARGET_NETWORK" --env-file "../.keys.$TARGET_NETWORK" -e "PRIVATE_KEY=$PRIVATE_KEY" ethereum-send $@ fi diff --git a/src/test-services/sidePrefund/run.sh b/src/test-services/sidePrefund/run.sh index 3955564..c63a220 100755 --- a/src/test-services/sidePrefund/run.sh +++ b/src/test-services/sidePrefund/run.sh @@ -12,7 +12,7 @@ echo "Using $TARGET_NETWORK network" docker build -t side-prefund . > /dev/null if [[ "$TARGET_NETWORK" == "development" ]]; then - docker run --network blockchain_side --rm --env-file ".env.$TARGET_NETWORK" side-prefund $@ + docker run --network ethereum_side_rpc_net --rm --env-file ".env.$TARGET_NETWORK" side-prefund $@ else docker run --rm --env-file ".env.$TARGET_NETWORK" --env-file "../.keys.$TARGET_NETWORK" side-prefund $@ fi diff --git a/tests/run.sh b/tests/run.sh index c0ca1b2..35799b7 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -11,8 +11,8 @@ docker create --name tests --env-file ./tests/.env tests $@ echo "Connecting tests container to test networks" docker network connect binance_net tests -docker network connect blockchain_home tests -docker network connect blockchain_side tests +docker network connect ethereum_home_rpc_net tests +docker network connect ethereum_side_rpc_net tests docker network connect validator1_test_network tests docker network connect validator2_test_network tests docker network connect validator3_test_network tests