Updated README.md. Moved tools to docker containers

This commit is contained in:
Kirill Fedoseev 2019-07-17 18:30:52 +07:00
parent 38dee19559
commit e990f4dec3
26 changed files with 4026 additions and 144 deletions

View File

@ -8,20 +8,22 @@ two are enough to sign any transaction in the Binance Chain,
confirm token transfer on the Ethereum Side, or vote for state changes.
ERC20 Token is used on the Ethereum side of the bridge.
All ERC20 tokens are located on address associated with DEPLOY_PRIVATE_KEY.
All ERC20 tokens are initially located on the address associated
with ```DEPLOY_PRIVATE_KEY```.
BEP2 Token is used on the Binance Chain side.
#### Running demo:
1) Build tss from local source.
```docker build -t tss -f ./src/tss/Dockerfile-local ./src/tss```
2) Run test environment (home and side blockchains, contracts deployment)
```./demo/start-environment.sh```
3) Run three validators in separate terminal sessions
```N=1 ./demo/validator-demo.sh```
```N=2 ./demo/validator-demo.sh```
```N=3 ./demo/validator-demo.sh```
All parts of this demo are docker containers.
#### Running demo:
1) Build tss from local source. (TSS cryptographic executables are taken from this image) \
```docker build -t tss -f ./src/tss/Dockerfile-local ./src/tss```
2) Run test environment. (home and side ganache-cli blockchains, contracts deployment)
```./demo/start-environment.sh```
3) Run three validators in separate terminal sessions.\
```N=1 ./demo/validator-demo.sh```\
```N=2 ./demo/validator-demo.sh```\
```N=3 ./demo/validator-demo.sh```
#### Interacting with validators, sending votes, retrieving bridge information
* For each validator, a specific port is mapped outside of the docker
@ -30,33 +32,38 @@ container for listening GET requests
- 5002 - second validator
- 5003 - third validator
* Retrieving bridge state
- http://localhost:5000/info
- http://localhost:5001/info
* Voting for bridge state changes
- http://localhost:5000/vote/startEpoch/NEW_EPOCH
- ```NEW_EPOCH``` should be equal nextEpoch + 1
- http://localhost:5001/vote/startKeygen
- After enough votes are collected, keygen process starts, and
ends with transfer of all remained funds in the Binance Chain
to the new generated account
- http://localhost:5000/vote/addValidator/ADDRESS
- ```ADDRESS``` is the Ethereum address of a validator
ends with the transfer of all remained funds in the Binance Chain
to the new generated bridge account.
- http://localhost:5001/vote/addValidator/ADDRESS
- ```ADDRESS``` - Ethereum address of a validator.
- After enough votes are collected, validator is added into
the pending validators list for the next epoch
- http://localhost:5000/vote/addValidator/ADDRESS
- ```ADDRESS``` is the Ethereum address of a validator
the next validators list for the next epoch.
- http://localhost:5001/vote/addValidator/ADDRESS
- ```ADDRESS``` - Ethereum address of a validator.
- After enough votes are collected, validator is removed from
the pending validators list for the next epoch
the next validators list for the next epoch.
#### Tools for sending transactions on both sides of the bridge
#### Testing tools for both sides of the bridge
Run this scripts from ```src/oracle``` dir
In this tools, ```run.sh``` file simply builds and runs a docker container
for interacting with test blockchains.
* ```node testBinanceSend.js TO VALUE_TOKEN [VALUE_BNB]```
- ```TO``` - receiver address, current bridge address in the Binance Chain
- ```VALUE_TOKEN``` - amount of tokens to send
- ```VALUE_BNB``` - amount of BNB tokens to send, if present, the
transaction is considered as a funding one
* ```node testEthereumSend.js TO VALUE```
- Approves specified amount of tokens to the bridge account and calls
needed method for starting exchange process
- ```TO``` - receiver address in the Binance Chain
- ```VALUE``` - amount of tokens to transfer and exchange
* ```./src/test-services/binanceSend/run.sh TO TOKENS NATIVE```
- Sends specified amount of tokens and BNBs to the bridge account.
- ```TO``` - receiver address in the Binance Chain.
- ```TOKENS``` - amount of tokens to send.
- ```NATIVE``` - amount of BNB tokens to send, if present, the
transaction is considered as a funding one.
* ```./src/test-services/ethereumSend/run.sh TOKENS```
- Transfers specified amount of tokens to the bridge account.
- ```VALUE``` - amount of tokens to transfer and exchange.
* ```./src/test-services/binanceBalance/run.sh ADDRESS```
- Gets current BEP2 token and BNB balances of the specified account.
- ```ADDRESS``` - account address in the Binance Chain.
* ```./src/test-services/ethereumBalance/run.sh ADDRESS```
- Gets current ERC20 token balance of the specified account.
- ```ADDRESS``` - Ethereum address of the account.

View File

@ -219,6 +219,7 @@ contract Bridge {
status = 1;
nextEpoch++;
states[nextEpoch].validators = getValidators();
emit NewEpoch(epoch, nextEpoch);
}
}

View File

@ -1,67 +0,0 @@
require('dotenv').config()
const Bnc = require('@binance-chain/javascript-sdk')
const axios = require('axios')
const Transaction = require('./tss-sign/tx')
const crypto = require('crypto')
const ecc = require('tiny-secp256k1')
const utils = require('ethers').utils
const { FOREIGN_URL, FOREIGN_ASSET, FOREIGN_PRIVATE_KEY } = process.env
const amount = process.argv[3]
const addressTo = process.argv[2]
const addressFrom = Bnc.crypto.getAddressFromPrivateKey(FOREIGN_PRIVATE_KEY)
const bnbs = process.argv[4]
const realBnbs = bnbs || '0'
const publicKeyStr = utils.computePublicKey(`0x${FOREIGN_PRIVATE_KEY}`)
const publicKey = {
x: publicKeyStr.substr(4, 64),
y: publicKeyStr.substr(68, 64)
}
if (bnbs)
console.log(`Funding from ${addressFrom} to ${addressTo}, ${amount} tokens, ${realBnbs} BNB'`)
else
console.log(`From ${addressFrom} to ${addressTo}, ${amount} tokens'`)
const httpClient = axios.create({ baseURL: FOREIGN_URL })
httpClient
.get(`/api/v1/account/${addressFrom}`)
.then((res) => {
const { sequence, account_number } = res.data
const tx = new Transaction({
from: addressFrom,
to: addressTo,
accountNumber: account_number,
sequence,
tokens: amount,
asset: FOREIGN_ASSET,
bnbs: realBnbs,
memo: bnbs ? 'funding' : 'exchange'
})
const hash = crypto.createHash('sha256').update(tx.getSignBytes()).digest('hex')
const signature = ecc.sign(Buffer.from(hash, 'hex'), Buffer.from(FOREIGN_PRIVATE_KEY, 'hex'))
const sig = {
r: signature.toString('hex').substr(0, 64),
s: signature.toString('hex').substr(64, 64)
}
return tx.addSignature(publicKey, sig)
})
.then(signed => {
console.log('sending')
return httpClient.post(`/api/v1/broadcast?sync=true`, signed, {
headers: {
'content-type': 'text/plain'
}
})
})
.then((result) => {
if (result.status === 200) {
console.log('success', result.data)
} else {
console.error('error', result)
}
})
.catch((error) => {
console.error('error', error)
})

View File

@ -1,37 +0,0 @@
require('dotenv').config()
const Web3 = require('web3')
const { HOME_RPC_URL, HOME_BRIDGE_ADDRESS, HOME_CHAIN_ID, DEPLOY_PRIVATE_KEY, HOME_TOKEN_ADDRESS } = process.env
const web3 = new Web3(HOME_RPC_URL, null, { transactionConfirmationBlocks: 1 })
const abiToken = require('../deploy/deploy-home/build/contracts/IERC20').abi
const token = new web3.eth.Contract(abiToken, HOME_TOKEN_ADDRESS)
const amount = parseInt(process.argv[2])
const query = token.methods.transfer(HOME_BRIDGE_ADDRESS, amount)
let nonce
const deployAddress = web3.eth.accounts.privateKeyToAccount(`0x${DEPLOY_PRIVATE_KEY}`).address
async function main () {
console.log(`Transfer from ${deployAddress} to ${HOME_BRIDGE_ADDRESS}, ${amount} tokens`)
nonce = await web3.eth.getTransactionCount(deployAddress)
console.log(await sendQuery(query, HOME_TOKEN_ADDRESS))
}
async function sendQuery (query, to) {
const encodedABI = query.encodeABI()
const tx = {
data: encodedABI,
from: deployAddress,
to,
nonce: nonce++,
chainId: parseInt(HOME_CHAIN_ID)
}
tx.gas = Math.min(Math.ceil(await query.estimateGas(tx) * 1.5), 6721975)
const signedTx = await web3.eth.accounts.signTransaction(tx, DEPLOY_PRIVATE_KEY)
return await web3.eth.sendSignedTransaction(signedTx.rawTransaction)
}
main()

View File

@ -0,0 +1,2 @@
FOREIGN_URL=https://testnet-dex.binance.org/
FOREIGN_ASSET=KFT-94F

View File

@ -0,0 +1,11 @@
FROM node:10.16.0-alpine
WORKDIR /test
COPY package.json /test/
RUN npm install
COPY testGetBinanceBalance.js /test/
ENTRYPOINT ["node", "testGetBinanceBalance.js"]

View File

@ -0,0 +1,7 @@
{
"name": "binance-balance",
"version": "0.0.1",
"dependencies": {
"axios": "0.19.0"
}
}

View File

@ -0,0 +1,9 @@
#!/bin/bash
set -e
cd $(dirname "$0")
docker build -t binance-balance . > /dev/null
docker run --rm --env-file .env binance-balance $@

View File

@ -1,5 +1,3 @@
require('dotenv').config()
const axios = require('axios')
const { FOREIGN_URL, FOREIGN_ASSET } = process.env
@ -9,5 +7,8 @@ const httpClient = axios.create({ baseURL: FOREIGN_URL })
httpClient
.get(`/api/v1/account/${address}`)
.then(res => console.log(parseFloat(res.data.balances.find(x => x.symbol === FOREIGN_ASSET).free)))
.then(res => {
console.log(`BNB: ${parseFloat(res.data.balances.find(x => x.symbol === 'BNB').free)}`)
console.log(`${FOREIGN_ASSET}: ${parseFloat(res.data.balances.find(x => x.symbol === FOREIGN_ASSET).free)}`)
})
.catch(console.log)

View File

@ -0,0 +1,4 @@
FOREIGN_URL=https://testnet-dex.binance.org/
FOREIGN_ASSET=KFT-94F
FOREIGN_PRIVATE_KEY=b92a59209e28149e5cee8e54dfceb80a08ea08e654261bdb9d264b15dee2525c

View File

@ -0,0 +1,13 @@
FROM node:10.16.0-alpine
WORKDIR /test
RUN apk add build-base python
COPY package.json /test/
RUN npm install
COPY testBinanceSend.js /test/
ENTRYPOINT ["node", "testBinanceSend.js"]

View File

@ -0,0 +1,7 @@
{
"name": "binance-send",
"version": "0.0.1",
"dependencies": {
"@binance-chain/javascript-sdk": "2.14.4"
}
}

View File

@ -0,0 +1,9 @@
#!/bin/bash
set -e
cd $(dirname "$0")
docker build -t binance-send . > /dev/null
docker run --rm --env-file .env binance-send $@

View File

@ -0,0 +1,50 @@
const Bnc = require('@binance-chain/javascript-sdk')
const { FOREIGN_URL, FOREIGN_ASSET, FOREIGN_PRIVATE_KEY } = process.env
const client = new Bnc(FOREIGN_URL)
async function main () {
client.chooseNetwork('testnet')
await client.setPrivateKey(FOREIGN_PRIVATE_KEY)
await client.initChain()
const from = client.getClientKeyAddress()
const to = process.argv[2]
const tokens = parseFloat(process.argv[3])
let bnbs = process.argv[4]
let receipt
if (bnbs) {
bnbs = parseFloat(bnbs)
console.log(`Funding from ${from} to ${to}, ${tokens} ${FOREIGN_ASSET}, ${bnbs} BNB'`)
const outputs = [{
to,
coins: []
}]
if (tokens) {
outputs[0].coins.push({
denom: FOREIGN_ASSET,
amount: tokens
})
}
if (bnbs) {
outputs[0].coins.push({
denom: 'BNB',
amount: bnbs
})
}
receipt = await client.multiSend(from, outputs, 'funding')
} else {
console.log(`From ${from} to ${to}, ${tokens} ${FOREIGN_ASSET}'`)
receipt = await client.transfer(from, to, tokens, FOREIGN_ASSET, 'exchange')
}
if (receipt.status === 200)
console.log(receipt.result[0].hash)
else
console.log(receipt)
}
main()

View File

@ -0,0 +1,2 @@
HOME_RPC_URL=http://ganache_home:8545
HOME_TOKEN_ADDRESS=0x44c158FE850821ae69DaF37AADF5c539e9d0025B

View File

@ -0,0 +1,11 @@
FROM node:10.16.0-alpine
WORKDIR /test
COPY package.json /test/
RUN npm install
COPY testGetEthereumBalance.js IERC20.json /test/
ENTRYPOINT ["node", "testGetEthereumBalance.js"]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
{
"name": "ethereum-balance",
"version": "0.0.1",
"dependencies": {
"web3": "1.0.0-beta.55"
}
}

View File

@ -0,0 +1,9 @@
#!/bin/bash
set -e
cd $(dirname "$0")
docker build -t ethreum-balance . > /dev/null
docker run --network blockchain_home --rm --env-file .env ethreum-balance $@

View File

@ -1,12 +1,14 @@
require('dotenv').config()
const Web3 = require('web3')
const { HOME_RPC_URL, HOME_TOKEN_ADDRESS } = process.env
const abiToken = require('./IERC20').abi
const web3 = new Web3(HOME_RPC_URL, null, { transactionConfirmationBlocks: 1 })
const abiToken = require('../deploy/deploy-home/build/contracts/IERC20').abi
const token = new web3.eth.Contract(abiToken, HOME_TOKEN_ADDRESS)
const address = process.argv[2]
token.methods.balanceOf(address).call().then(x => console.log(x.toNumber()))
token.methods.balanceOf(address).call()
.then(x => console.log(x.toNumber()))
.catch(() => console.log(0))

View File

@ -0,0 +1,6 @@
HOME_RPC_URL=http://ganache_home:8545
HOME_BRIDGE_ADDRESS=0x94b40CC641Ed7db241A1f04C8896ba6f6cC36b85
HOME_CHAIN_ID=44
HOME_TOKEN_ADDRESS=0x44c158FE850821ae69DaF37AADF5c539e9d0025B
HOME_PRIVATE_KEY=e2aeb24eaa63102d0c0821717c3b6384abdabd7af2ad4ec8e650dce300798b27

View File

@ -0,0 +1,11 @@
FROM node:10.16.0-alpine
WORKDIR /test
COPY package.json /test/
RUN npm install
COPY testEthereumSend.js IERC20.json /test/
ENTRYPOINT ["node", "testEthereumSend.js"]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
{
"name": "ethereum-send",
"version": "0.0.1",
"dependencies": {
"web3": "1.0.0-beta.55"
}
}

View File

@ -0,0 +1,9 @@
#!/bin/bash
set -e
cd $(dirname "$0")
docker build -t ethreum-send . > /dev/null
docker run --network blockchain_home --rm --env-file .env ethreum-send $@

View File

@ -0,0 +1,33 @@
const Web3 = require('web3')
const { HOME_RPC_URL, HOME_BRIDGE_ADDRESS, HOME_CHAIN_ID, HOME_PRIVATE_KEY, HOME_TOKEN_ADDRESS } = process.env
const abiToken = require('./IERC20').abi
const web3 = new Web3(HOME_RPC_URL, null, { transactionConfirmationBlocks: 1 })
const token = new web3.eth.Contract(abiToken, HOME_TOKEN_ADDRESS)
const amount = parseInt(process.argv[2])
const deployAddress = web3.eth.accounts.privateKeyToAccount(`0x${HOME_PRIVATE_KEY}`).address
async function main () {
console.log(`Transfer from ${deployAddress} to ${HOME_BRIDGE_ADDRESS}, ${amount} tokens`)
const query = token.methods.transfer(HOME_BRIDGE_ADDRESS, amount)
const encodedABI = query.encodeABI()
const tx = {
data: encodedABI,
from: deployAddress,
to: HOME_TOKEN_ADDRESS,
nonce: await web3.eth.getTransactionCount(deployAddress),
chainId: parseInt(HOME_CHAIN_ID)
}
tx.gas = Math.min(Math.ceil(await query.estimateGas(tx) * 1.5), 6721975)
const signedTx = await web3.eth.accounts.signTransaction(tx, HOME_PRIVATE_KEY)
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction)
console.log(receipt.transactionHash)
}
main()