Go to file
Yurii Rashkovskii 9a192c1e07
Problem: bridge should not deploy its contracts anymore
Bridge's contracts are now developed in a separate repository
and have their own deployment procedure:

https://github.com/poanetwork/poa-parity-bridge-contracts

However, our integration tests are not yet updated to
use this deployment procedure.

Solution: disable deployment compile-time by default
and only use it in integration tests as a stopgap measure
until the new deployment procedure (or any other viable
alternative) has been used.
2018-05-01 09:43:34 -07:00
bridge Problem: bridge should not deploy its contracts anymore 2018-05-01 09:43:34 -07:00
cli Problem: bridge should not deploy its contracts anymore 2018-05-01 09:43:34 -07:00
contracts Merge pull request #26 from yrashk/integration-tests-work 2018-03-09 10:04:30 +01:00
examples Problem: RPC transport change conflated with keystore 2018-04-19 10:13:45 -07:00
integration-tests Problem: bridge should not deploy its contracts anymore 2018-05-01 09:43:34 -07:00
jsTests update Ropsten Sokol db file 2017-11-14 13:31:47 +03:00
res res 2017-08-13 19:43:43 +02:00
tests Merge branch 'raw-transactions' into rpc+raw-transactions 2018-04-26 18:21:07 -07:00
tools tools/estimate_gas_costs.sh: improve wording 2018-01-04 16:27:49 +01:00
truffle verifySignatures -> hasEnoughValidSignatures and make it return bool 2018-02-13 17:18:24 +01:00
.editorconfig fixed signature validation in solidity, added truffle tests for it 2017-09-04 12:49:05 +02:00
.gitignore Problem: yarn.lock entry in gitignore 2018-04-19 09:51:37 -07:00
.travis.yml .travis.yml: run integration tests as part of stable, beta and nightly 2018-01-22 14:35:54 +01:00
Cargo.lock Problem: nonce reuse 2018-04-29 13:20:42 -07:00
Cargo.toml Problem: Cargo manifest still includes test_bridge_stuff 2018-04-19 09:51:37 -07:00
LICENSE LICENSE 2017-09-28 10:51:23 +02:00
Makefile Problem: bridge should not deploy its contracts anymore 2018-05-01 09:43:34 -07:00
README.md Problem: bridge should not deploy its contracts anymore 2018-05-01 09:43:34 -07:00

README.md

POA-Ethereum Bridge

Join the chat at https://gitter.im/paritytech/parity-bridge

Build Status Solidity Coverage Status (contracts only)

the bridge is an ERC20 token contract on one ethereum-based blockchain that is backed by ether on another ethereum-based blockchain.

users can convert ether on one chain into the same amount of ERC20 tokens on the other and back. the bridge securely relays these conversions.

the bridge can mitigate scaling issues: by deploying a proof-of-authority network and bridging it to the Ethereum Foundation network ('mainnet') users can convert their mainnet ether into ERC20 tokens on the PoA chain and there transfer them with much lower transaction fees, faster block times and unaffected by mainnet congestion.

the users can withdraw their tokens worth of ether on the mainnet at any point.

parity is using the bridge project to prototype the system that will eventually connect ethereum and other non-parachains to polkadot.

next steps

  1. deploy to bridge ethereum and kovan (bridge authorities TBD)
  2. make the bridge work with contract-based dynamic validator sets
  3. after kovan hardfork 2: deploy to kovan again with dynamic validator set

current functionality

the bridge connects two chains home and foreign.

when users deposit ether into the HomeBridge contract on home they get the same amount of ERC20 tokens on foreign.

they can use ForeignBridge as they would use any ERC20 token.

to convert their foreign ERC20 into ether on home users can always call ForeignBridge.transferHomeViaRelay(homeRecipientAddress, value, homeGasPrice).

foreign is assumed to use PoA (proof of authority) consensus. relays between the chains happen in a byzantine fault tolerant way using the authorities of foreign.

high level explanation of home ether -> foreign ERC20 relay

sender deposits value into HomeBridge. the HomeBridge fallback function emits Deposit(sender, value).

for each Deposit event on HomeBridge every authority executes ForeignBridge.deposit(sender, value, transactionHash).

once there are ForeignBridge.requiredSignatures such transactions with identical arguments and from distinct authorities then ForeignBridge.balanceOf(sender) is increased by value.

high level explanation of foreign ERC20 -> home ether relay

sender executes ForeignBridge.transferHomeViaRelay(recipient, value, homeGasPrice) which checks and reduces ForeignBridge.balances(sender) by value and emits ForeignBridge.Withdraw(recipient, value, homeGasPrice).

for every ForeignBridge.Withdraw, every bridge authority creates a message containing value, recipient and the transactionHash of the transaction referenced by the ForeignBridge.Withdraw event; signs that message and executes ForeignBridge.submitSignature(signature, message). this collection of signatures is on foreign because transactions are free for the authorities on foreign, but not free on home.

once ForeignBridge.requiredSignatures signatures by distinct authorities are collected a ForeignBridge.CollectedSignatures(authorityThatSubmittedLastSignature, messageHash) event is emitted.

everyone (usually authorityThatSubmittedLastSignature) can then call ForeignBridge.message(messageHash) and ForeignBridge.signature(messageHash, 0..requiredSignatures) to look up the message and signatures and execute HomeBridge.withdraw(vs, rs, ss, message) and complete the withdraw.

HomeBridge.withdraw(vs, rs, ss, message) recovers the addresses from the signatures, checks that enough authorities in its authority list have signed and finally transfers value ether (minus the relay gas costs) to recipient.

run truffle smart contract tests

requires yarn to be $PATH. installation instructions

cd truffle
yarn test

build

requires rust and cargo: installation instructions.

requires solc to be in $PATH: installation instructions.

assuming you've cloned the bridge (git clone git@github.com:poanetwork/parity-bridge.git) and are in the project directory (cd parity-bridge) run:

make

and install ../target/release/bridge in your $PATH.

run

bridge --config config.toml --database db.toml
  • --config - location of the configuration file. configuration file must exist
  • --database - location of the database file.

configuration file example

estimated_gas_cost_of_withdraw = 100000

[home]
account = "0x006e27b6a72e1f34c626762f3c4761547aff1421"
ipc = "/Users/marek/Library/Application Support/io.parity.ethereum/jsonrpc.ipc"
required_confirmations = 0

[home.contract]
bin = "contracts/EthereumBridge.bin"

[foreign]
account = "0x006e27b6a72e1f34c626762f3c4761547aff1421"
ipc = "/Users/marek/Library/Application Support/io.parity.ethereum/jsonrpc.ipc"
required_confirmations = 0

[foreign.contract]
bin = "contracts/KovanBridge.bin"

[authorities]
accounts = [
    "0x006e27b6a72e1f34c626762f3c4761547aff1421",
    "0x006e27b6a72e1f34c626762f3c4761547aff1421",
    "0x006e27b6a72e1f34c626762f3c4761547aff1421"
]
required_signatures = 2

options

home options

  • home.account - authority address on the home (required)
  • home.ipc - path to home parity ipc handle (required)
  • home.contract.bin - path to the compiled bridge contract (required)
  • home.required_confirmations - number of confirmation required to consider transaction final on home (default: 12)
  • home.poll_interval - specify how often home node should be polled for changes (in seconds, default: 1)
  • home.request_timeout - specify request timeout (in seconds, default: 5)

foreign options

  • foreign.account - authority address on the foreign (required)
  • foreign.ipc - path to foreign parity ipc handle (required)
  • foreign.contract.bin - path to the compiled bridge contract (required)
  • foreign.required_confirmations - number of confirmation required to consider transaction final on foreign (default: 12)
  • foreign.poll_interval - specify how often home node should be polled for changes (in seconds, default: 1)
  • foreign.request_timeout - specify request timeout (in seconds, default: 5)

authorities options

  • authorities.account - all authorities (required)
  • authorities.required_signatures - number of authorities signatures required to consider action final (required)

transaction options

  • transaction.deposit_relay.gas - specify how much gas should be consumed by deposit relay
  • transaction.deposit_relay.gas_price - specify gas price for deposit relay
  • transaction.withdraw_confirm.gas - specify how much gas should be consumed by withdraw confirm
  • transaction.withdraw_confirm.gas_price - specify gas price for withdraw confirm
  • transaction.withdraw_relay.gas - specify how much gas should be consumed by withdraw relay
  • transaction.withdraw_relay.gas_price - specify gas price for withdraw relay

database file format

home_contract_address = "0x49edf201c1e139282643d5e7c6fb0c7219ad1db7"
foreign_contract_address = "0x49edf201c1e139282643d5e7c6fb0c7219ad1db8"
checked_deposit_relay = 120
checked_withdraw_relay = 121
checked_withdraw_confirm = 121

all fields are required

  • home_contract_address - address of the bridge contract on home chain
  • foreign_contract_address - address of the bridge contract on foreign chain
  • checked_deposit_relay - number of the last block for which an authority has relayed deposits to the foreign
  • checked_withdraw_relay - number of the last block for which an authority has relayed withdraws to the home
  • checked_withdraw_confirm - number of the last block for which an authority has confirmed withdraw

example run

./target/release/bridge --config examples/config.toml --database db.toml
  • example run requires a parity instance running
  • this parity instance can be started by running examples/parity_start.sh
  • it connects to this parity instance twice. one connection treats the node as home, whereas the other as foreign
  • by default, parity tries to unlock account generates from seedphrase this is sparta - 0x006e27b6a72e1f34c626762f3c4761547aff1421
  • this is just an example. the 'real world' bridge needs to connect to the two different parity instances

deposit

deposit

withdraw

withdraw

recipient pays relay cost to relaying authority

a bridge authority has to pay for gas (cost) to execute HomeBridge.withdraw when withdrawing value from foreign chain to home chain. value - cost is transferred to the recipient. cost is transferred to the authority executing HomeBridge.withdraw. the recipient pays the relaying authority for the execution of the transaction. that shuts down an attack that enabled exhaustion of authorities funds on home.

read on for a more thorough explanation.

parity-bridge connects a value-bearing ethereum blockchain home (initially the ethereum foundation chain) to a non-value-bearing PoA ethereum blockchain foreign (initially the kovan testnet).

value-bearing means that the ether on that chain has usable value in the sense that in order to obtain it one has to either mine it (trade in electricity) or trade in another currency. non-value-bearing means that one can easily obtain a large amount of ether on that chain for free. through a faucet in the case of testnets for example.

the bridge authorities are also the validators of the foreign PoA chain. transactions by the authorities are therefore free (gas price = 0) on foreign.

to execute a transaction on home a bridge authority has to spend ether to pay for the gas.

this opened up an attack where a malicious user could deposit a very small amount of wei on HomeBridge, get it relayed to ForeignBridge, then spam ForeignBridge.transferHomeViaRelay with 1 wei withdraws. it would cost the attacker very little home chain wei and essentially free foreign testnet wei to cause the authorities to spend orders of magnitude more wei to relay the withdraw to home by executing HomeBridge.withdraw. an attacker was able to exhaust bridge authorities funds on home.

to shut down this attack HomeBridge.withdraw was modified so value - cost is transferred to the recipient and cost is transferred to the authority doing the relay. this way the recipient pays the relaying authority for the execution of the withdraw transaction.

relayers can set the gas price for HomeBridge.withdraw. they could set a very high gas price resulting in a very high cost through which they could burn large portions of value. to shut down this attack the homeGasPrice param was added to ForeignBridge.transferHomeViaRelay. end users have control over the cost/latency tradeoff of their relay transaction through the homeGasPrice. relayers have to set gas price to homeGasPrice when calling HomeBridge.withdraw. the recipient for value is the exception and can freely choose any gas price. see https://github.com/paritytech/parity-bridge/issues/112 for more details.

HomeBridge.withdraw is currently the only transaction bridge authorities execute on home. care must be taken to secure future functions that bridge authorities will execute on home in similar ways.