Compare commits

..

142 Commits

Author SHA1 Message Date
Alexander Kolotov
f2a6a64637 Merge the develop branch to the master branch, preparation to v1.1.0 (#238) 2019-11-15 22:13:03 +01:00
Gerardo Nardelli
8d4eb86a19 Fix logs and start block parameters in oracle deployment (#235)
* Update start block env vars in oracle deployment
* Set logger to remote server for docker-compose-transfer.yml
* avoid calculating start block parameter if provided in oracle deployment config
* set home and foreign start block in erc20-native e2e
* set home and foreign start block in erc20-native ultimate test
2019-11-15 21:31:13 +01:00
phahulin
cc6afb3736 Fix monitor path in crontab example (#236)
This is a minor PR which fixes path in crontab example for monorepo
2019-11-15 06:16:21 +01:00
phahulin
84ecfc30d9 Optional ability to point ORACLE_LOG_LEVEL in the deployment configuration (#234) 2019-11-13 20:18:46 +01:00
Gerardo Nardelli
5d770e8607 Add AMB monitor e2e tests (#231)
* Add amb monitor e2e tests
* Fix eventsStats endpoint monitor
2019-11-13 07:51:10 +01:00
Alexander Kolotov
db89d1c12e Merge the develop branch to the master branch, preparation to v1.0.0 #230
* Support alternative receiver in Oracle (#221)
* Support alternative receiver feature in Monitor (#223)
* Support token migration (#224)
* Fix suggested gas price in transaction for ui production build (#222)
* Updated links to new repo with tokenbridge contracts (#226)
* Update the contract's submodule to the release 3.2.0 (#228)
2019-11-12 06:37:23 +01:00
Gerardo Nardelli
4fd4ac3d73 Merge branch 'master' into develop
# Conflicts:
#	commons/constants.js
#	e2e-commons/up.sh
#	monitor/alerts.js
#	monitor/eventsStats.js
#	monitor/utils/events.js
#	monitor/utils/message.js
2019-11-08 09:53:06 -03:00
Alexander Kolotov
cbd9d607ce Update the contract's submodule to the release 3.2.0 (#228) 2019-11-07 22:50:37 +01:00
Gerardo Nardelli
346fa1e732 Support token migration (#224)
* Filter transfer event in token swap in Oracle
* Support token swap in monitor
2019-11-06 22:49:01 +03:00
Alexander Kolotov
f6fa83d7ea Updated links to new repo with tokenbridge contracts (#226) 2019-11-05 15:53:47 +03:00
Gerardo Nardelli
1564ccc580 Support alternative receiver feature in Monitor (#223)
* Update monitor to support changes from alternative receiver
* Add monitor event processing unit tests
* update chrome version used en e2e tests
* update chromedriver version
2019-10-29 22:22:02 +03:00
Gerardo Nardelli
7a54e584d5 Support alternative receiver in Oracle (#221)
* Add transfer watcher
* Filter userRequestForAffirmation events in Transfer events
* Add extended oracle composer file
2019-10-29 17:55:47 +03:00
Gerardo Nardelli
1d79cf82f3 Fix suggested gas price in trasaction for ui production build (#222)
* use string version of bignumber when converting gasPrice to hex
* update chromedriver version
2019-10-25 15:38:30 +03:00
Alexander Kolotov
9884b4b424 Add support for AMB contracts (#199) 2019-10-21 15:57:28 +03:00
Gerardo Nardelli
d577a71096 Add support for AMB contracts (#199) 2019-09-18 22:45:13 +03:00
Alexander Kolotov
803f0074e6 Update the contract's submodule to a commit-predecessor of 3.1.0 (#214) 2019-09-17 10:56:29 +03:00
Przemyslaw Rzad
e288df39dc Remove rsync dependency (#213) 2019-09-16 18:34:42 +02:00
Przemyslaw Rzad
8d0e70359f Remove ERC20_TOKEN_ADDRESS from env variables (#211)
* Remove ERC20_TOKEN_ADDRESS from env variables

* Do not check erc20 token address for native-to-erc

* Rename ERC20_TOKEN_ADDRESS to bridgeableTokenAddress
2019-09-14 08:04:07 +02:00
Przemyslaw Rzad
ab8270ee7c Remove obsolete preapre.yml file (#212) 2019-09-13 16:19:34 +02:00
Przemyslaw Rzad
6b55c54497 Function naming (#208)
* Function naming

* More renames from oracle to gas supplier
2019-09-13 14:54:51 +02:00
Vedhavyas Singareddi
114f62da7b Update CONFIGURATION.md (#210)
remove `"` so that markdown can parse table properly
2019-09-13 14:25:44 +02:00
Przemyslaw Rzad
8b010f887d Consistent variable naming (#198)
* Add console.table

* First steps in validate script

* env rename

* Added parameter names

* Descriptions

* Print and configuration

* Added more parameters

* Rename gas oracle to gas supplier

* More changes

* Removed env examples for now

* RPC rename

* Bridge address rename

* More changes

* jobs

* Renames

* Typo

* jobs

* Changes

* jobs

* Changes

* Monitor changes

* jovs

* Typo

* Changes

* REACT_APP_ env prefix

* Typo

* Rollback changes

* Oracle deployment

* Defaults

* Monitor

* Naming

* Typo

* Typo

* Envs

* ui deployment

* ALl jobs

* Vars in ultimate

* Lint

* Lint

* Lint

* Another way to add REACT_APP prefixing

* Unnecessary mapping

* No output timeout

* No output timeout

* Got rid of ERC20_TOKEN_ADDRESS

* Configuration readme

* Configuration

* Prefixes

* timeout

* Docs

* Docs

* docs

* docs

* docs

* Roll back ERC20_TOKEN_ADDRESS for erc-to-erc

* Typo

* lint

* Rollback

* ROllback validator

* Rollback yarn.lock

* dai and wetc update

* Rollback ERC20_TOKEN_ADDRESS

* erc to native

* examples

* all jobs

* roll back

* roll back ERC20_TOKEN_ADDRESS: "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B"

* ui env example

* typo

* Allow rpc for ultimate

* Test

* ERC20_TOKEN_ADDRESS rollback

* Specify port

* React port

* All jobs

* cosmetics

* Values

* Restore erc20 token

* Rearrange example for easier comparision

* Rearrange ultimate for easier comparision

* Rearrange for easier comparision

* Refactor

* Conditional app styles

* Loading environment variables in react app

* Add missing vars for UI in wetc and dai

* Bring back test parameters readme

* Readme for monitor vars

* Reading environment variables in e2e-commons (#207)
2019-09-13 09:11:38 +02:00
Przemyslaw Rzad
d593577ace Update dpkg (#206) 2019-09-11 15:08:59 +02:00
Alexander Kolotov
4e2971f880 Update contract's submodule to 3.0.0 (#204) 2019-09-09 21:41:35 +03:00
Przemyslaw Rzad
54858ae597 Molecule tests for deploying repository (#194)
* Squashed commits

* All jobs

* Rollback changes

* Dependencies

* Remove .git checking

* Resolve path issues

* New way of copying repository.

* Test non existing .git

* New repo task

* Typo

* Do not fail mkdir if folder exists

* Test double task

* zipping the archives

* Increase no_output_timeout because of slowly installing apt-get
2019-09-06 15:24:30 +02:00
Przemyslaw Rzad
443474e802 Typos (#197)
* Typo

* Typo

* Typo
2019-09-06 13:27:17 +02:00
Przemyslaw Rzad
677bc50519 Move molecule to deployment-e2e (#196)
* Moved deployment/molecule to deployment-e2e

* Update paths and readmes

* Nested molecule

* Corrected paths

* paths

* path

* Moved docker up
2019-08-29 10:30:34 +02:00
MarkusTeufelberger
9af253b83e Remove deprecated config option (#166) 2019-08-29 09:56:39 +02:00
Przemyslaw Rzad
01186d6aa8 New way of deploying repository (#195)
* New repo task

* Removed bridge_repo and bridge_repo_branch configs

* Updated docs

* Update apt-get

* Fix path

* Exclude fix

* Removed CODEBASE_BRANCH

* Initializing submodules for deployment tests

* Synchronizing with ls-tree

* Synchronization without temp files
2019-08-29 09:20:55 +02:00
Przemyslaw Rzad
dd9add50a0 Monitor E2E rewrite (#187)
* Started monitor-e2e rewrite

* axios

* Implemented tests

* Monitor start

* First deploy

* Wait for monitor

* Removed redundant files

* Tests.

* TODO

* Links to minitor in constants

* Typo.

* [PR-into-PR] Monitor E2E rewrite - balance (#191)

* Test run for more monitor-e2e tests

* macos/docker

* timeout

* Little refactor

* Trying to test balances in other types of bridges.

* Utils.

* test

* check all

* erc to erc try

* Final tests

* typo

* All jobs

* Lint

* Roll back docker in docker

* WaitUntil

* Axios version

* New validator checks (#192)
2019-08-27 16:26:49 +02:00
Przemyslaw Rzad
c39e81f97d Simplify Molecule developemnt (#193) 2019-08-23 08:43:46 +02:00
phahulin
f72ca7d38f Fix docker command (#190) 2019-08-21 13:02:45 +03:00
phahulin
b4ec04173c Add a note about resetting nonces (#189) 2019-08-21 00:35:00 +03:00
Przemyslaw Rzad
6aafce052c Ultimate tests for ERC-TO-ERC (#186)
* Introduce ultimate erc-to-erc

* Added metamask setup

* Corrected configuration parameters
2019-08-20 10:19:42 +02:00
Przemyslaw Rzad
244306f0bf Update chrome version (#185) 2019-08-12 09:22:27 +02:00
Alexander Kolotov
2093ff2d7e Update contract's submodule to 2.4.0 (#183) 2019-08-09 10:58:53 +03:00
Przemyslaw Rzad
76daf5a436 Ultimate E2E for ERC TO NATIVE (#182)
* Introducing ultimate erc-to-native, with ultimate-commons

* Ports

* group

* up

* Addresses

* Typo.

* Redis key

* Redis key as a parameter

* ultimate

* parameters

* job name

* jobs

* Cosmetics

* cosmetics

* cosmetics

* jobs

* Descriptions
2019-08-08 16:09:24 +02:00
Przemyslaw Rzad
c865198290 Common Validator utils (#181)
* Extracted parseValidatorEvent to commons

* Extracted processValidatorsEvents to commons

* Extracted validatorList to commons.

* refactorings

* Fixed imports, lint

* UI using getValidatorList

* Monitor using getValidatorList from commons

* Lint

* UI using properly getPastEvents

* Default options

* Final changes

* Corrected invocation of getPastEvents

* Correct usage of options in getPastEvents

* Changed expected message from infura

* Change usage of fromBlock and toBlock

* Default parameters
2019-08-08 15:27:09 +02:00
Przemyslaw Rzad
055a444fae Common gasprice (#179)
* Common gas price normalization.

* only e2e jobs

* One func

* More extraction.

* Fixed the tests

* skip gasPriceWithinLimits

* test fix

* tos tring

* boundaries

* Extracted fetching gas price from contract

* Refactored oracle gas price

* lint

* lint

* Commentary

* Using common gas price from oracle in ui

* Fix lint

* lint

* Log

* Using common gas price in monitor

* cosmetics

* all jobs

* lint

* lint

* tests

* more tests

* incljdes

* Tests in oracle

* Tests in commons

* Lint

* moved tests from ui to commons

* chai

* Changed order of fetching gas price
2019-08-05 17:22:57 +02:00
Przemyslaw Rzad
2be0e9f363 Fix flaky UI-E2E (#178)
* Change user

* jobs

* Revert "Change user"

5fa7084f06

* Trying to use block generator address

* jobs

* Fixed

* 5 jobs

* 10 jobs

* all jobs

* finish

* Removed jobs

* Add funds for block generator in block genesis
2019-08-05 14:13:16 +02:00
Przemyslaw Rzad
52239a9506 Refactor CI config (#177)
* Update ci config version

* try to use orb

* command

* naming

* Common docker executor config

* Machine in orb

* Common tasks

* common caching

* nvm

* Final test
2019-08-05 09:48:21 +02:00
Przemyslaw Rzad
f3419cbec4 Molecule tests for Monitor deployment (#176)
* Monitor deployment testing - initial commit.

* deployment-monitor job

* one job

* Additional tests.

* server port.

* lint

* all jobs
2019-08-02 10:34:53 +02:00
Przemyslaw Rzad
40be5a5f8e Extend line width to 120 (#174)
* Extend line width to 120

* Lint fixes
2019-08-01 15:10:22 +02:00
Przemyslaw Rzad
a2e9dae43d Extending monitor-e2e with 3 types of bridge (#170)
* Started working on monitor-e2e

* Monitor e2e tests extended for 3 types of bridge

* Skipp error checking

* bash fix

* Fixed docker-compose

* check first

* grep errors

* all jobs

* Style

* Executing instead of sourcing
2019-08-01 10:26:20 +02:00
Przemyslaw Rzad
414fe9cb65 Ultimate e2e - Native to erc - UI (#168)
* Trying job

* dependency

* Run the tests

* Oracle docker composes

* Fixed networks

* endpoints

* Skip logging

* Try node

* Moved chromedriver from ui to ui-e2e

* Port

* Run

* Install chrome

* minte blocks

* Finishing

* Revert "Skip logging"

76747eb7ef

* inventory

* Inventory change.

* ui-e2e fix

* ui-e2e fix?

* native-to-erc group

* jobs

* Ports

* Blocks

* yarn

* fix

* fix

* killall

* Try ui-e2e

* no killall

* All jobs.

* Try two

* separate jobs

* all jobs

* One job.

* Removed the oracle-e2e step in ultimate tests.
2019-08-01 09:57:58 +02:00
Alexander Kolotov
272dc142de New security audit report for the contracts v2.3.2 (#169)
* new security audit report for the contracts v2.3.2
* contracts updated to points to latest commit
2019-08-01 09:03:49 +02:00
Przemyslaw Rzad
984b238279 Explicit and supported chrome version for ui-e2e (#172) 2019-07-31 17:36:28 +02:00
rzadp
93ebcc049e Revert "chrome.deb"
b532c8bad0
2019-07-31 15:31:17 +02:00
rzadp
b532c8bad0 chrome.deb 2019-07-31 15:28:16 +02:00
Przemyslaw Rzad
9c8259700b Add cron schedule to monitor deployment playbook (#161)
* Default cron schedule

* Added cron task

* Docs

* Overwriting log files

* Removed deprecated flag

* Default monitor_cron_schedule.
2019-07-26 15:59:30 +02:00
Przemyslaw Rzad
c66923827b Common getTokenType used on UI, monitor and Oracle (#165)
* Stopped silently swallowing errors

* getTokenType in commons

* Oracle using getTokenType from commons

* Moved the getTokenType tests from ui to commons

* Using getTokenType in ui and oracle

* Revert "Stopped silently swallowing errors"

fc92c0af9d

* using common getTokenType in monitor.

* Lint.
2019-07-26 14:26:14 +02:00
Przemyslaw Rzad
c94b68ab5b Monitor remote logging (#162)
* Added remote logging for monitor

* Legacy line

* Tempaltes
2019-07-26 10:51:39 +02:00
Przemyslaw Rzad
d3653bc31f UI using abis from commons (#164)
* Renamed v1 abi names

* Home store using v1 from commons

* Using ERC20_BYTES32_ABI from commons
2019-07-26 10:30:35 +02:00
Przemyslaw Rzad
c9d100491c Ultimate E2E tests (#158)
* Ultimate e2e for native to erc type of bridge

* One job

* Try to run the tests

* Run on CI

* Docs

* Cosmetics

* Final changes

* Revert the changes

* Networks

* Waiting for Oracle

* One job

* Initialize the contracts submodule

* Run on ci

* comment

* Sleep.

* ultimate network

* Docker localhost no longer needed

* Final changes

* Timeout

* Naming

* Sleep task.
2019-07-26 10:14:25 +02:00
Przemyslaw Rzad
5c92cf50d7 Oracle using ERC_TYPES from commons (#163) 2019-07-24 15:36:07 +02:00
Przemyslaw Rzad
5d22ad1ecb Remove default syslog server port. (#152) 2019-07-22 09:37:38 +02:00
Przemyslaw Rzad
110b9accc9 Cosistent TokenBridge naming (#159) 2019-07-19 09:18:51 +02:00
Przemyslaw Rzad
82a3bdd86b First step of ultimate e2e testing (#155)
* Ultimate e2e for native to erc type of bridge

* Initialize

* Node and yarn not needed anymore.
2019-07-17 10:14:58 +02:00
Przemyslaw Rzad
9b3c65f2c4 Creating redis and rabbit in oracle (#153) 2019-07-16 16:12:33 +02:00
Przemyslaw Rzad
8ea6c716ea Building containers in deployment (#149)
* Build instead of up

* Starting the service explicitly.
2019-07-16 14:58:26 +02:00
Przemyslaw Rzad
3e09fe890e UI using Commons (#145)
* ui using commons

* Update paths in abis

* Lint.
2019-07-15 18:07:11 +02:00
Przemyslaw Rzad
0b183fb861 Grouped ui-e2e tests (#148) 2019-07-15 09:22:16 +02:00
Gerardo Nardelli
811e8da6b5 Add support for oracle gas price values not expressed in gwei (#142)
* Support other oracle's gas price values in Oracle
* Add default gas price factor in Oracle
* Support other oracle's gas price values in UI
* Support other oracle's gas price values in Monitor
2019-07-12 19:10:17 +03:00
Przemyslaw Rzad
54f6fb5835 UI deployment - Molecule tests (#147)
* Renamed scenario default to oracle

* Introduced ui molecule tests

* Readme

* Common prepare

* Shared test_all

* Moved test_docker_config to common

* Added ui tests

* Lint.
2019-07-12 14:51:06 +02:00
Przemyslaw Rzad
208cfafa95 Monitor using commons (#143) 2019-07-12 14:49:46 +02:00
Przemyslaw Rzad
2e89d7724a Oracle using commons (#144) 2019-07-12 14:37:41 +02:00
Przemyslaw Rzad
b88dd66cac Oracle-e2e using Commons (#146) 2019-07-12 10:53:16 +02:00
Przemyslaw Rzad
054225d348 Added Commons sub-repository (#139)
* Added Commons

* Typo.

* Typo.

* Typo.
2019-07-11 15:46:52 +02:00
Przemyslaw Rzad
cf3aa56929 Simplified ui-e2e linting rules (#140)
* Simplified ui-e2e linting rules

* More simplification
2019-07-11 15:06:50 +02:00
Przemyslaw Rzad
1da1acbfbe Yaml and Ansible linting in Molecule (#141)
* Removed old ansible-lint outside of molecule

* Yamlint

* Enabled ansible-lint with minimal rules

* Removed ansible-lint job
2019-07-11 10:17:02 +02:00
Przemyslaw Rzad
3f27b98b8b Monitor deployment playbook (#133)
* Introduced monitor deployment playbook

* Timeouts

* dai deployment block

* wetc deployment blocks

* Corrected path

* Typo.

* Added monitor to execution readme.

* Monitor port.

* Check on start

* Timeouts

* check-and-start
2019-07-09 19:26:40 +02:00
Przemyslaw Rzad
4281adfd95 UI logging (#131)
* Introduced logging task for the ui

* Do not update repo to allow multiple apps

* Setup logging first

* Different template names

* Separate docker logging config

* Removed duplication

* Common logging task.

* Tests.

* Lint.

* Commented out syslog server port for ui

* Testing file permissions.
2019-07-09 17:00:12 +02:00
Gerardo Nardelli
319b493568 Use mintedTotallyByBridge for bridge-ui statistics (#135)
* Use mintedTotallyByBridge for bridge-ui statistics
2019-07-09 00:03:02 +03:00
Gerardo Nardelli
4e5e21541e Remove oracle redis lock (#137) 2019-07-08 18:06:57 +03:00
Przemyslaw Rzad
86fe89d3ec Dockerized molecule (#132)
* Dockerized molecule

* Moved testing.md to subfolder.

* Updated readme

* Readme.
2019-07-08 09:15:17 +02:00
Przemyslaw Rzad
47a0a7c0f5 UI deployment (#126)
* Introduced UI playbook

* added python3-pip

* Instructions.

* Added tokenbridge_ui service

* python3 interpreter

* tokenbridge-ui service

* Explicit python3 usage.
2019-07-05 14:39:37 +02:00
Alexander Kolotov
dcf83ffb55 List of available deployments in README (#125) 2019-07-03 23:12:51 +03:00
Przemyslaw Rzad
4c5df11fd3 E2E files linting (#117)
* Introduced linting for oracle-e2e.

* Fixed linting errors.

* Introduced linting for ui-e2e

* Fixed linting errors.

* Typo.
2019-07-02 15:12:57 +02:00
Przemyslaw Rzad
b254df7c25 Deployment testing specific branch (#122)
* Testing branch

* Updated readme.
2019-07-02 14:54:39 +02:00
Przemyslaw Rzad
11c1595dd6 Role rework plus deployment tests (#116)
* Role-rework

* Update readme.
2019-07-02 13:10:46 +02:00
Przemyslaw Rzad
59564bd600 Deployment structure and documentation (#113)
* Moved rollback and logs into main deployment readme

* Removed duplicated section.

* Removed subdir mention

* Merged dependencies and prerequisites

* Lint at bottom

* Added configuration.md and execution.md

* Moved configuration

* Update path

* Moved administrator configuration

* Update name

* Moved execution.

* Moved stuff to execution.md

* Moved dependencies and prerequisites to sub-mds

* Moved stuff out of oracle subfolder

* Whitespace

* Simplyfy readme

* Removed backticks

* Whitespace

* Update path.

* Update user info

* Update phrasing

* Phrasing
2019-06-28 11:31:57 +02:00
Przemyslaw Rzad
f1d24f0e2c Monitor - E2E (#112)
* Monitor in e2e

* Cleanup trap

* Exposing monitor port

* Cleanup script

* Exposing monitor port

* Test cases

* Silent curl

* Introduced monitor-e2e into CI

* only monitor

* machine executor

* Readme

* Echoing test cases

* Revert "only monitor"

bb6c8baf06

* Negated commands in a subshell
2019-06-27 09:57:45 +02:00
Alexander Kolotov
68a2b5be90 Update the procedure to reset block in the deployment README (#111)
* define more accurately the procedure to reset the block
2019-06-17 11:16:21 +03:00
Przemyslaw Rzad
1da7340fb9 Monitor in docker (#109)
* Monitor in docker

* Update readme.

* Update crontab.example

* Removed examples from readme

* Update readme.
2019-06-17 09:22:53 +02:00
Alexander Kolotov
26ff22ac7e Merge pull request #108 from poanetwork/fix-coef-for-gaslimit-in-oracle
Increase of EXTRA_GAS_PERCENTAGE
2019-06-14 20:45:46 +03:00
Alexander Kolotov
1737a1d6a2 Merge branch 'master' into fix-coef-for-gaslimit-in-oracle 2019-06-14 20:33:43 +03:00
Alexander Kolotov
8629aff80d Merge pull request #103 from poanetwork/#94-oracle-sender-retry
Improve sender retry strategy
2019-06-14 17:46:19 +03:00
Alexander Kolotov
091e80e5e9 Merge branch 'master' into #94-oracle-sender-retry 2019-06-14 17:19:43 +03:00
Przemyslaw Rzad
c5cad3c2d8 Removed command in docker compose if entrypoint is present (#106) 2019-06-14 16:18:57 +02:00
Alexander Kolotov
8597e13952 the coefficient increased as preventive fix to address the issue with failed cuncurrent transactions due to incorrect estimatGas call 2019-06-14 17:00:23 +03:00
Alexander Kolotov
c9ed138326 Merge branch 'master' into #94-oracle-sender-retry 2019-06-14 16:51:17 +03:00
Przemyslaw Rzad
8f47c93369 UI in docker (#102)
* Removed duplicate entry

* Started introducing ui dockerfile

* frozen lockfiles

* Removed unnecessary steps from Dockerfile.e2e

* Added start instruction

* Added docker-compose with instructions to UI

* Updated readme.

* Removed unnecessary command
2019-06-14 15:50:22 +02:00
Alexander Kolotov
14b5968efa Merge branch 'master' into #94-oracle-sender-retry 2019-06-14 16:35:44 +03:00
Przemyslaw Rzad
ca1cf80615 Removed obsole e2e deploy scripts (#104) 2019-06-14 14:48:52 +02:00
Alexander Kolotov
b1721881f5 Merge branch 'master' into #94-oracle-sender-retry 2019-06-14 15:34:43 +03:00
Gerardo Nardelli
ae6692abcd Add unit test for retry queue 2019-06-13 14:29:40 -03:00
Przemyslaw Rzad
3be812d55f Monorepo initialization (#101)
* Update postinstall script

* Add initialize script, simplify readme

* Unsafe perm

* Added initialize-root job

* Initialize-root only on master
2019-06-13 16:17:24 +02:00
Gerardo Nardelli
a466fe57dc Limit retry delay 2019-06-12 16:14:43 -03:00
Gerardo Nardelli
9e5f185bce Improve oracle sender retry strategy 2019-06-11 15:10:28 -03:00
Alexander Kolotov
81a936af45 Merge pull request #86 from poanetwork/e2e-commons
Introducing E2E Commons
2019-06-10 19:07:41 +03:00
rzadp
4cb2df32e3 Merge master into e2e-commons 2019-06-10 11:58:16 +02:00
Alexander Kolotov
2b3b2d41ce Merge pull request #99 from poanetwork/oracle-nonce-too-low
Handle 'nonce too low' error message on oracle sender
2019-06-07 23:28:25 +03:00
Gerardo Nardelli
2f30a42748 Add new nonce error message detection on oracle sender 2019-06-07 16:06:58 -03:00
Alexander Kolotov
a669ea622c Merge pull request #93 from poanetwork/ui-test-env
UI - New way of getting env variables
2019-06-07 17:54:49 +03:00
rzadp
404b1d4959 Removed env variables from CI 2019-06-07 13:19:36 +02:00
rzadp
9285ac534e Introduced new way of getting env variables 2019-06-07 13:19:12 +02:00
rzadp
1dba07623d Remove reduntant dotenv configs 2019-06-07 13:00:07 +02:00
rzadp
98e2dc9c0d Update readme. 2019-06-04 15:28:27 +02:00
rzadp
3a3ebf9747 Auto quit on command fail 2019-06-04 14:49:39 +02:00
rzadp
f8d8a2d55b Update config 2019-06-04 14:37:21 +02:00
rzadp
d7edbb2281 Fix 2019-06-04 14:15:14 +02:00
rzadp
03ab7b44b6 Common url and network ID 2019-06-04 14:04:40 +02:00
rzadp
c86e956fa0 Common rpc url 2019-06-04 13:52:06 +02:00
rzadp
fddeb6869f Common token and parity rpc 2019-06-04 13:43:53 +02:00
rzadp
ff20521cce Clean up utils 2019-06-04 13:30:37 +02:00
rzadp
c5b1aa1424 Removed unused contractsPath in ui-e2e 2019-06-04 13:30:31 +02:00
rzadp
22937a9b0e Common bridge addresses, common second user, renamed constants.json to config 2019-06-04 13:27:21 +02:00
rzadp
23d109b84c Common validator 2019-06-04 12:58:36 +02:00
rzadp
7b5b240735 Common user for ui-e2e. 2019-06-04 11:59:31 +02:00
rzadp
13d49de5c6 Moved constant user from oracle-e2e to e2e-common 2019-06-04 10:51:34 +02:00
rzadp
7e937bdefa Clean up deploy script 2019-06-04 10:43:27 +02:00
rzadp
7607a7fdb1 Readme 2019-06-04 10:28:12 +02:00
rzadp
07968c347f Common generateNewBlock 2019-06-04 10:28:11 +02:00
rzadp
25ff5888ba No down.sh in CI 2019-06-04 09:13:04 +02:00
rzadp
57a9417afc Removed commonized scripts.
Removed obsolete .envs
Removed duplicate licence
2019-06-04 09:11:56 +02:00
rzadp
c00139202d Readme. 2019-06-04 09:11:56 +02:00
rzadp
8480b4d499 Common mine blocks 2019-06-04 09:11:56 +02:00
rzadp
a11211d813 Common deploy 2019-06-04 09:11:56 +02:00
rzadp
cc10335d99 Trying to introduce common deploy 2019-06-04 09:11:56 +02:00
rzadp
505aa3f261 Common ui-e2e 2019-06-04 09:11:56 +02:00
rzadp
2159fc1a57 Fixed down. 2019-06-04 09:11:56 +02:00
rzadp
164f21d9eb Introducing common docker-compose 2019-06-04 09:11:56 +02:00
Przemyslaw Rzad
1013f69a8b CI performance impovements (#82)
* Moved selenium to ui-e2e dev dependencies

* Cosmetics

* Removed compiling contracts from build and from test

* Introduced initialize job; Moved cover job to the main workflow

* Build, lint, test and cover jobs using initialize cache

* Yarn install not needed for oracle-e2e. Enable docker caching. Frozen lockfile

* Use docker layer caching and yarn cache for ui-e2e

* Trying to save npm install log as artifact

* More caching.
2019-06-04 09:09:18 +02:00
Alexander Kolotov
563fbe5773 Merge pull request #83 from poanetwork/monitor-support-legacy-bridge
Add support v1 legacy contracts on monitor
2019-06-03 18:01:28 +03:00
Gerardo Nardelli
70dc09935c Merge branch 'monitor-support-legacy-bridge' of github.com:poanetwork/tokenbridge into monitor-support-legacy-bridge 2019-06-03 09:47:49 -03:00
Gerardo Nardelli
369b90a6d5 Expose stuckTransfer endpoint only if v1 bridge 2019-06-03 09:47:12 -03:00
Alexander Kolotov
e5df7ec37d Merge branch 'master' into monitor-support-legacy-bridge 2019-06-01 01:34:23 +03:00
Alexander Kolotov
0d047d49ef Merge pull request #81 from poanetwork/monitor-handle-errors
Fix error handling on monitor workers
2019-06-01 01:25:30 +03:00
Alexander Kolotov
822fa918e2 Merge branch 'master' into monitor-handle-errors 2019-06-01 01:07:24 +03:00
Gerardo Nardelli
baf65b7001 Merge branch 'master' into monitor-support-legacy-bridge
# Conflicts:
#	monitor/checkWorker3.js
#	monitor/stuckTransfers.js
2019-05-31 15:42:36 -03:00
Gerardo Nardelli
94a6a5ad74 Add support v1 legacy contracts on monitor 2019-05-31 15:35:50 -03:00
Gerardo Nardelli
5ab299089f Fix error handling on monitor workers 2019-05-30 15:05:36 -03:00
337 changed files with 13145 additions and 5468 deletions

View File

@@ -1,88 +1,289 @@
version: 2
version: 2.1
orbs:
tokenbridge-orb:
commands:
install-chrome:
steps:
- run:
name: Update dpkg
command: |
sudo apt-get clean
sudo apt-get update
sudo apt-get install dpkg
- run:
name: Install Chrome
command: |
wget -O chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i chrome.deb
install-node:
steps:
- run:
name: Install Node
command: |
export NVM_DIR="/opt/circleci/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install 10.16.3 && nvm alias default 10.16.3
echo 'export NVM_DIR="/opt/circleci/.nvm"' >> $BASH_ENV
echo ' [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV
install-yarn:
steps:
- run:
name: Install Yarn
command: |
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get -y install yarn
yarn-install-cached-on-machine:
steps:
- restore_cache:
name: Restore Machine Yarn Package Cache
keys:
- yarn-machine-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }}
- run:
name: Install npm dependencies using Yarn
command: nvm use default; yarn install --frozen-lockfile
- save_cache:
name: Save Machine Yarn Package Cache
key: yarn-machine-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
wait-for-oracle:
parameters:
redis-key:
type: string
steps:
- run:
name: Install redis tools
command: sudo apt-get install -y redis-tools
- run:
name: Wait for the Oracle to start
command: |
set +e
i=0
while [[ $(redis-cli GET << parameters.redis-key >> ) ]]; do
((i++))
if [ "$i" -gt 30 ]
then
exit -1
fi
echo "Sleeping..."
sleep 3
done
executors:
docker-node:
docker:
- image: circleci/node:10.15
machine-with-docker-caching:
machine:
image: circleci/classic:latest
docker_layer_caching: true
jobs:
build:
docker:
- image: circleci/node:10.15
initialize:
executor: tokenbridge-orb/docker-node
steps:
- checkout
- run: git submodule update --init
- run: yarn
- restore_cache:
name: Restore Yarn Package Cache
keys:
- yarn-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }}
- run: git submodule status > submodule.status
- restore_cache:
name: Restore contracts submodule with compiled contracts
keys:
- contracts-{{ checksum "submodule.status" }}
- run: yarn install --frozen-lockfile
- save_cache:
name: Save Yarn Package Cache
key: yarn-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
- run: touch install_deploy.log; test -d contracts/build/contracts || yarn install:deploy &> install_deploy.log
- store_artifacts:
path: install_deploy.log
- run: test -d contracts/build/contracts || yarn compile:contracts
- save_cache:
name: Save contracts submodule with compiled contracts
key: contracts-{{ checksum "submodule.status" }}
paths:
- contracts
- save_cache:
name: Save initialized project for subsequent jobs
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/project
initialize-root:
executor: tokenbridge-orb/docker-node
steps:
- checkout
- run: sudo su - -c 'export CI=true && cd /home/circleci/project && yarn initialize && yarn test'
build:
executor: tokenbridge-orb/docker-node
steps:
- restore_cache:
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn run build
lint:
docker:
- image: circleci/node:10.15
executor: tokenbridge-orb/docker-node
steps:
- checkout
- run: git submodule update --init
- run: yarn
- run: yarn compile:contracts
- restore_cache:
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn run lint
ansible-lint:
docker:
- image: particlekit/ansible-lint
steps:
- checkout
- run: ./deployment/lint.sh
test:
docker:
- image: circleci/node:10.15
environment:
HOME_RPC_URL: http://example.com
FOREIGN_RPC_URL: http://example.com
executor: tokenbridge-orb/docker-node
steps:
- checkout
- run: git submodule update --init
- run: yarn
- run: yarn compile:contracts
- restore_cache:
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn run test
oracle-e2e:
docker:
- image: circleci/node:10.15
executor: tokenbridge-orb/docker-node
steps:
- checkout
- run: git submodule update --init
- run: yarn
- setup_remote_docker
- setup_remote_docker:
docker_layer_caching: true
- run: yarn run oracle-e2e
ui-e2e:
machine:
image: circleci/classic:latest
executor: tokenbridge-orb/machine-with-docker-caching
steps:
- checkout
- run: |
echo 'export NVM_DIR="/opt/circleci/.nvm"' >> $BASH_ENV
echo ' [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV
- run: nvm install 11.4.0 && nvm alias default 11.4.0
- run: curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
- run: echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
- run: sudo apt-get update && sudo apt-get install yarn
- run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- run: sudo dpkg -i google-chrome-stable_current_amd64.deb
- tokenbridge-orb/install-node
- tokenbridge-orb/install-yarn
- tokenbridge-orb/install-chrome
- run: git submodule update --init
- run: yarn
- tokenbridge-orb/yarn-install-cached-on-machine
- run: yarn run ui-e2e
cover:
docker:
- image: circleci/node:10.15
monitor-e2e:
executor: tokenbridge-orb/machine-with-docker-caching
steps:
- checkout
- run: git submodule update --init
- run: yarn
- checkout
- run: git submodule update --init
- run: ./monitor-e2e/run-tests.sh
cover:
executor: tokenbridge-orb/docker-node
steps:
- restore_cache:
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn workspace ui run coverage
- run: yarn workspace ui run coveralls
deployment-oracle:
executor: tokenbridge-orb/machine-with-docker-caching
steps:
- checkout
- run: git submodule update --init
- run:
name: Run the scenario
command: deployment-e2e/molecule.sh oracle
no_output_timeout: 40m
deployment-ui:
executor: tokenbridge-orb/machine-with-docker-caching
steps:
- checkout
- run: git submodule update --init
- run:
name: Run the scenario
command: deployment-e2e/molecule.sh ui
no_output_timeout: 40m
deployment-monitor:
executor: tokenbridge-orb/machine-with-docker-caching
steps:
- checkout
- run: git submodule update --init
- run:
name: Run the scenario
command: deployment-e2e/molecule.sh monitor
no_output_timeout: 40m
deployment-repo:
executor: tokenbridge-orb/machine-with-docker-caching
steps:
- checkout
- run: git submodule update --init
- tokenbridge-orb/install-node
- tokenbridge-orb/install-yarn
- tokenbridge-orb/yarn-install-cached-on-machine
- run:
name: Run the scenario
command: deployment-e2e/molecule.sh repo
no_output_timeout: 40m
ultimate:
executor: tokenbridge-orb/machine-with-docker-caching
parameters:
scenario-name:
description: "Molecule scenario name used to create the infrastructure"
type: string
redis-key:
description: "Redis key checked for non-emptiness to assert if Oracle is running"
type: string
ui-e2e-grep:
description: "Mocha grep string used to run ui-e2e tests specific to given type of bridge"
type: string
steps:
- checkout
- run: git submodule update --init
- tokenbridge-orb/install-node
- tokenbridge-orb/install-chrome
- tokenbridge-orb/install-yarn
- tokenbridge-orb/yarn-install-cached-on-machine
- run:
name: Prepare the infrastructure
command: e2e-commons/up.sh deploy << parameters.scenario-name >>
no_output_timeout: 50m
- tokenbridge-orb/wait-for-oracle:
redis-key: << parameters.redis-key >>
- run:
name: Run the ui-e2e tests
command: |
nvm use default;
node ./e2e-commons/scripts/blocks.js &
cd ui-e2e; yarn mocha -g "<< parameters.ui-e2e-grep >>" -b ./test.js
workflows:
version: 2
coverage:
tokenbridge:
jobs:
- cover:
- initialize
- initialize-root:
filters:
branches:
only: master
- build:
requires:
- initialize
- lint:
requires:
- initialize
- test:
requires:
- initialize
- cover:
requires:
- initialize
filters:
branches:
only: master
tokenbridge:
jobs:
- build
- lint
- ansible-lint
- test
- oracle-e2e
- ui-e2e
- monitor-e2e
- deployment-oracle
- deployment-ui
- deployment-monitor
- deployment-repo
- ultimate:
name: "ultimate: native to erc"
scenario-name: native-to-erc
redis-key: native-erc-collected-signatures:lastProcessedBlock
ui-e2e-grep: "NATIVE TO ERC"
- ultimate:
name: "ultimate: erc to native"
scenario-name: erc-to-native
redis-key: erc-native-collected-signatures:lastProcessedBlock
ui-e2e-grep: "ERC TO NATIVE"
- ultimate:
name: "ultimate: erc to erc"
scenario-name: erc-to-erc
redis-key: erc-erc-collected-signatures:lastProcessedBlock
ui-e2e-grep: "ERC TO ERC"

2
.gitignore vendored
View File

@@ -43,6 +43,8 @@ hosts
Vagrantfile
vagrant-hosts.yml
.vagrant
deployment/venv
__pycache__
#monitor
monitor/responses/*

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "contracts"]
path = contracts
url = https://github.com/poanetwork/poa-bridge-contracts.git
url = https://github.com/poanetwork/tokenbridge-contracts.git

2
.nvmrc
View File

@@ -1 +1 @@
10.15
10.16

View File

@@ -1,5 +1,6 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 100
"printWidth": 120,
"bracketSpacing": true
}

71
CONFIGURATION.md Normal file
View File

@@ -0,0 +1,71 @@
# Configuration
## Common configuration
name | description | value
--- | --- | ---
COMMON_HOME_RPC_URL | The HTTPS URL(s) used to communicate to the RPC nodes in the Home network. Several URLs can be specified, delimited by spaces. If the connection to one of these nodes is lost the next URL is used for connection. | URL(s)
COMMON_FOREIGN_RPC_URL | The HTTPS URL(s) used to communicate to the RPC nodes in the Foreign network. Several URLs can be specified, delimited by spaces. If the connection to one of these nodes is lost the next URL is used for connection. | URL(s)
COMMON_HOME_BRIDGE_ADDRESS | The address of the bridge contract address in the Home network. It is used to listen to events from and send validators' transactions to the Home network. | hexidecimal beginning with "0x"
COMMON_FOREIGN_BRIDGE_ADDRESS | The address of the bridge contract address in the Foreign network. It is used to listen to events from and send validators' transactions to the Foreign network. | hexidecimal beginning with "0x"
COMMON_HOME_GAS_PRICE_SUPPLIER_URL | The URL used to get a JSON response from the gas price prediction oracle for the Home network. The gas price provided by the oracle is used to send the validator's transactions to the RPC node. Since it is assumed that the Home network has a predefined gas price (e.g. the gas price in the Core of POA.Network is `1 GWei`), the gas price oracle parameter can be omitted for such networks. | URL
COMMON_HOME_GAS_PRICE_SPEED_TYPE | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `COMMON_HOME_GAS_PRICE_SUPPLIER_URL` is not used. | `instant` / `fast` / `standard` / `slow`
COMMON_HOME_GAS_PRICE_FALLBACK | The gas price (in Wei) that is used if both the oracle and the fall back gas price specified in the Home Bridge contract are not available. | integer
COMMON_HOME_GAS_PRICE_FACTOR | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. | integer
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL | The URL used to get a JSON response from the gas price prediction oracle for the Foreign network. The provided gas price is used to send the validator's transactions to the RPC node. If the Foreign network is Ethereum Foundation mainnet, the oracle URL can be: https://gasprice.poa.network. Otherwise this parameter can be omitted. | URL
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL`is not used. | `instant` / `fast` / `standard` / `slow`
COMMON_FOREIGN_GAS_PRICE_FALLBACK | The gas price (in Wei) used if both the oracle and fall back gas price specified in the Foreign Bridge contract are not available. | integer
COMMON_FOREIGN_GAS_PRICE_FACTOR | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. | integer
## Oracle configuration
name | description | value
--- | --- | ---
ORACLE_BRIDGE_MODE | The bridge mode. The bridge starts listening to a different set of events based on this parameter. | NATIVE_TO_ERC / ERC_TO_ERC / ERC_TO_NATIVE
ORACLE_ALLOW_HTTP_FOR_RPC | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no`
ORACLE_HOME_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Home network for new blocks. The interval should match the average production time for a new block. | integer
ORACLE_FOREIGN_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Foreign network for new blocks. The interval should match the average production time for a new block. | integer
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL | An interval in milliseconds used to get the updated gas price value either from the oracle or from the Home Bridge contract. | integer
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL | The interval in milliseconds used to get the updated gas price value either from the oracle or from the Foreign Bridge contract. | integer
ORACLE_QUEUE_URL | RabbitMQ URL used by watchers and senders to communicate to the message queue. Typically set to: `amqp://127.0.0.1`. | local URL
ORACLE_REDIS_URL | Redis DB URL used by watchers and senders to communicate to the database. Typically set to: `redis://127.0.0.1:6379`. | local URL
ORACLE_HOME_START_BLOCK | The block number in the Home network used to start watching for events when the bridge instance is run for the first time. Usually this is the same block where the Home Bridge contract is deployed. If a new validator instance is being deployed for an existing set of validators, the block number could be the latest block in the chain. | integer
ORACLE_FOREIGN_START_BLOCK | The block number in the Foreign network used to start watching for events when the bridge instance runs for the first time. Usually this is the same block where the Foreign Bridge contract was deployed to. If a new validator instance is being deployed for an existing set of validators, the block number could be the latest block in the chain. | integer
ORACLE_LOG_LEVEL | Set the level of details in the logs. | `trace` / `debug` / `info` / `warn` / `error` / `fatal`
ORACLE_MAX_PROCESSING_TIME | The workers processes will be killed if this amount of time (in milliseconds) is elapsed before they finish processing. It is recommended to set this value to 4 times the value of the longest polling time (set with the `HOME_POLLING_INTERVAL` and `FOREIGN_POLLING_INTERVAL` variables). To disable this, set the time to 0. | integer
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY | The private key of the bridge validator used to sign confirmations before sending transactions to the bridge contracts. The validator account is calculated automatically from the private key. Every bridge instance (set of watchers and senders) must have its own unique private key. The specified private key is used to sign transactions on both sides of the bridge. | hexidecimal without "0x"
ORACLE_VALIDATOR_ADDRESS | The public address of the bridge validator | hexidecimal with "0x"
## UI configuration
name | description | value
--- | --- | ---
UI_TITLE | The title for the bridge UI page. `%c` will be replaced by the name of the network. | string
UI_DESCRIPTION | The meta description for the deployed bridge page. | string
UI_NATIVE_TOKEN_DISPLAY_NAME | name of the home native coin | string
UI_HOME_NETWORK_DISPLAY_NAME | name to be displayed for home network | string
UI_FOREIGN_NETWORK_DISPLAY_NAME | name to be displayed for foreign network | string
UI_HOME_WITHOUT_EVENTS | `true` if home network doesn't support events | true/false
UI_FOREIGN_WITHOUT_EVENTS | `true` if foreign network doesn't support events | true/false
UI_HOME_EXPLORER_TX_TEMPLATE | template link to transaction on home explorer. `%s` will be replaced by transaction hash | URL template
UI_FOREIGN_EXPLORER_TX_TEMPLATE | template link to transaction on foreign explorer. `%s` will be replaced by transaction hash | URL template
UI_HOME_EXPLORER_ADDRESS_TEMPLATE | template link to address on home explorer. `%s` will be replaced by address | URL template
UI_FOREIGN_EXPLORER_ADDRESS_TEMPLATE | template link to address on foreign explorer. `%s` will be replaced by address | URL template
UI_HOME_GAS_PRICE_UPDATE_INTERVAL | An interval in milliseconds used to get the updated gas price value either from the oracle or from the Home Bridge contract. | integer
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL | An interval in milliseconds used to get the updated gas price value either from the oracle or from the Foreign Bridge contract. | integer
UI_PORT | The port for the UI app. | integer
UI_STYLES | The set of styles to render the bridge UI page. Currently only `classic` is implemented | classic
## Monitor configuration
name | description | value
--- | --- | ---
MONITOR_HOME_START_BLOCK | The app will monitor transactions starting from this block. | integer
MONITOR_FOREIGN_START_BLOCK | The app will monitor transactions starting from this block. | integer
MONITOR_VALIDATOR_HOME_TX_LIMIT | Average gas usage of a transaction sent by a validator, it is used to estimate the number of transaction that can be paid by the validator. | integer
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT | Average gas usage of a transaction sent by a validator, it is used to estimate the number of transaction that can be paid by the validator. | integer
MONITOR_TX_NUMBER_THRESHOLD | If estimated number of transaction is equal to or below this value, the monitor will report that the validator has less funds than it is required. | integer
MONITOR_PORT | The port for the Monitor. | integer

View File

@@ -2,17 +2,12 @@ FROM node:10
WORKDIR /mono
COPY package.json .
COPY oracle/package.json ./oracle/
COPY oracle-e2e/package.json ./oracle-e2e/
COPY ui/package.json ./ui/
COPY ui/lib/web3-eth/index.js ./ui/lib/web3-eth/index.js
COPY ui-e2e/package.json ./ui-e2e/
COPY monitor/package.json ./monitor/
COPY monitor-e2e/package.json ./monitor-e2e/
COPY contracts/package.json ./contracts/
COPY ui/lib/web3-eth/index.js ./ui/lib/web3-eth/index.js
COPY yarn.lock .
RUN yarn install
RUN yarn install --frozen-lockfile
COPY ./contracts ./contracts
RUN yarn install:deploy
RUN yarn compile:contracts

View File

@@ -3,15 +3,15 @@
[![License: LGPL v3.0](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
# Tokenbridge
Welcome to the **POA Token Bridge** monorepository!
Welcome to the **POA TokenBridge** monorepository!
Please note that this repository as a **work in progress**.
## Overview
The POA Token Bridge allows users to transfer assets between two chains in the Ethereum ecosystem. It is composed of several elements which are contained within this monorepository.
The POA TokenBridge allows users to transfer assets between two chains in the Ethereum ecosystem. It is composed of several elements which are contained within this monorepository.
For a complete picture of the POA Token Bridge functionality, it is useful to explore each subrepository.
For a complete picture of the POA TokenBridge functionality, it is useful to explore each subrepository.
## Structure
@@ -24,9 +24,23 @@ Sub-repositories maintained within this monorepo are listed below.
| [Monitor](monitor/README.md) | Tool for checking balances and unprocessed events in bridged networks. |
| [Deployment](deployment/README.md) | Ansible playbooks for deploying cross-chain bridges. |
| [Oracle-E2E](oracle-e2e/README.md) | End to end tests for the Oracle |
| [Monitor-E2E](monitor-e2e/README.md) | End to end tests for the Monitor |
| [UI-E2E](ui-e2e/README.md) | End to end tests for the UI |
| [Deployment-E2E](deployment-e2e/README.md) | End to end tests for the Deployment |
| [Commons](commons/README.md) | Interfaces, constants and utilities shared between the sub-repositories |
| [E2E-Commons](e2e-commons/README.md) | Common utilities and configuration used in end to end tests |
Additionally there are [Smart Contracts](https://github.com/poanetwork/poa-bridge-contracts) used to manage bridge validators, collect signatures, and confirm asset relay and disposal.
Additionally there are [Smart Contracts](https://github.com/poanetwork/tokenbridge-contracts) used to manage bridge validators, collect signatures, and confirm asset relay and disposal.
## Available deployments
| **Launched by POA** | **Launched by 3rd parties** |
| ---------- | ---------- |
| [POA20 Bridge](https://bridge.poa.net/) | [Ocean TokenBridge](https://bridge.oceanprotocol.com/) |
| [xDai Bridge](https://dai-bridge.poa.network/) | [Thunder bridge](https://ui.stormdapps.com/) |
| [WETC Bridge](https://wetc.app/) | [Volta TokenBridge](https://vt.volta.bridge.eth.events/) & [DAI bridge to Volta Chain](https://dai.volta.bridge.eth.events/) |
| | [Artis Brige](https://bridge.artis.network/) |
| | [Tenda bridge](https://bridge-mainnet.tenda.network) & [xDai-to-Tenda bridge](https://bridge-xdai.tenda.network/) |
## Network Definitions
@@ -38,34 +52,23 @@ Additionally there are [Smart Contracts](https://github.com/poanetwork/poa-bridg
## Operational Modes
The POA TokenBridge provides three operational modes:
The POA TokenBridge provides four operational modes:
- [x] `Native-to-ERC20` **Coins** on a Home network can be converted to ERC20-compatible **tokens** on a Foreign network. Coins are locked on the Home side and the corresponding amount of ERC20 tokens are minted on the Foreign side. When the operation is reversed, tokens are burnt on the Foreign side and unlocked in the Home network. **More Information: [POA-to-POA20 Bridge](https://medium.com/poa-network/introducing-poa-bridge-and-poa20-55d8b78058ac)**
- [x] `ERC20-to-ERC20` ERC20-compatible tokens on the Foreign network are locked and minted as ERC20-compatible tokens (ERC677 tokens) on the Home network. When transferred from Home to Foreign, they are burnt on the Home side and unlocked in the Foreign network. This can be considered a form of atomic swap when a user swaps the token "X" in network "A" to the token "Y" in network "B". **More Information: [ERC20-to-ERC20](https://medium.com/poa-network/introducing-the-erc20-to-erc20-tokenbridge-ce266cc1a2d0)**
- [x] `ERC20-to-Native`: Pre-existing **tokens** in the Foreign network are locked and **coins** are minted in the `Home` network. In this mode, the Home network consensus engine invokes [Parity's Block Reward contract](https://wiki.parity.io/Block-Reward-Contract.html) to mint coins per the bridge contract request. **More Information: [xDai Chain](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a)**
- [x] `Arbitrary-Message`: Transfer arbitrary data between two networks as so the data could be interpreted as an arbitrary contract method invocation.
## Initializing the monorepository
Clone the repository with submodules:
Clone the repository:
```bash
git clone --recursive https://github.com/poanetwork/tokenbridge
# or initialize submodules if already cloned without --recursive option:
git submodule update --init
git clone https://github.com/poanetwork/tokenbridge
```
Install dependencies:
Initialize submodules, install dependencies, compile the Smart Contracts:
```
yarn install && yarn install:deploy
```
_**Note**: The installation should be performed with an unprivileged Linux account or with the following flag: `yarn install --unsafe-perm`. [More information](https://docs.npmjs.com/misc/scripts#user)_
Compile the Smart Contracts
```
yarn compile:contracts
yarn initialize
```
## Linting
@@ -76,14 +79,6 @@ Running linter for all JS projects:
yarn lint
```
Running linter for all Ansible playbooks:
- [ansible-lint](https://github.com/ansible/ansible-lint) is required
```
yarn ansible-lint
```
## Tests
Running tests for all projects:
@@ -92,10 +87,15 @@ Running tests for all projects:
yarn test
```
Additionaly there are end-to-end tests for [Oracle](oracle-e2e/README.md) and [UI](ui-e2e/README.md).
Additionally there are end-to-end tests for [Oracle](oracle-e2e/README.md) and [UI](ui-e2e/README.md).
For details on building, running and developing please refer to respective READMEs in sub-repositories.
## Building, running and deploying
Please refer to the instructions in sub-directories.
Configuration details are available [here](./CONFIGURATION.md).
## Contributing
See the [CONTRIBUTING](CONTRIBUTING.md) document for contribution, testing and pull request protocol.

13
commons/.eslintrc Normal file
View File

@@ -0,0 +1,13 @@
{
"extends": [
"airbnb-base",
"../.eslintrc"
],
"rules": {
"no-unused-expressions": "off",
"import/no-extraneous-dependencies": "off"
},
"env": {
"mocha": true
}
}

2
commons/README.md Normal file
View File

@@ -0,0 +1,2 @@
# POA TokenBridge / Commons
Interfaces, constants and utilities shared between the sub-repositories

96
commons/abis.js Normal file
View File

@@ -0,0 +1,96 @@
const HOME_NATIVE_TO_ERC_ABI = require('../contracts/build/contracts/HomeBridgeNativeToErc').abi
const FOREIGN_NATIVE_TO_ERC_ABI = require('../contracts/build/contracts/ForeignBridgeNativeToErc').abi
const HOME_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeBridgeErcToErc').abi
const FOREIGN_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignBridgeErc677ToErc677').abi
const HOME_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/HomeBridgeErcToNative').abi
const FOREIGN_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/ForeignBridgeErcToNative').abi
const ERC20_ABI = require('../contracts/build/contracts/ERC20').abi
const ERC677_ABI = require('../contracts/build/contracts/ERC677').abi
const ERC677_BRIDGE_TOKEN_ABI = require('../contracts/build/contracts/ERC677BridgeToken').abi
const BLOCK_REWARD_ABI = require('../contracts/build/contracts/IBlockReward').abi
const BRIDGE_VALIDATORS_ABI = require('../contracts/build/contracts/BridgeValidators').abi
const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/RewardableValidators').abi
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
const BOX_ABI = require('../contracts/build/contracts/Box').abi
const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis')
const { BRIDGE_MODES } = require('./constants')
const ERC20_BYTES32_ABI = [
{
constant: true,
inputs: [],
name: 'name',
outputs: [
{
name: '',
type: 'bytes32'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'symbol',
outputs: [
{
name: '',
type: 'bytes32'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
function getBridgeABIs(bridgeMode) {
let HOME_ABI = null
let FOREIGN_ABI = null
if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC) {
HOME_ABI = HOME_NATIVE_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_NATIVE_TO_ERC_ABI
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
HOME_ABI = HOME_ERC_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_ERC_TO_ERC_ABI
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
HOME_ABI = HOME_ERC_TO_NATIVE_ABI
FOREIGN_ABI = FOREIGN_ERC_TO_NATIVE_ABI
} else if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1) {
HOME_ABI = HOME_V1_ABI
FOREIGN_ABI = FOREIGN_V1_ABI
} else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
HOME_ABI = HOME_AMB_ABI
FOREIGN_ABI = FOREIGN_AMB_ABI
} else {
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
}
return { HOME_ABI, FOREIGN_ABI }
}
module.exports = {
getBridgeABIs,
HOME_NATIVE_TO_ERC_ABI,
FOREIGN_NATIVE_TO_ERC_ABI,
HOME_ERC_TO_ERC_ABI,
FOREIGN_ERC_TO_ERC_ABI,
HOME_ERC_TO_NATIVE_ABI,
FOREIGN_ERC_TO_NATIVE_ABI,
ERC20_ABI,
ERC677_ABI,
ERC677_BRIDGE_TOKEN_ABI,
BLOCK_REWARD_ABI,
BRIDGE_VALIDATORS_ABI,
REWARDABLE_VALIDATORS_ABI,
HOME_V1_ABI,
FOREIGN_V1_ABI,
ERC20_BYTES32_ABI,
HOME_AMB_ABI,
FOREIGN_AMB_ABI,
BOX_ABI
}

27
commons/constants.js Normal file
View File

@@ -0,0 +1,27 @@
const BRIDGE_MODES = {
NATIVE_TO_ERC: 'NATIVE_TO_ERC',
ERC_TO_ERC: 'ERC_TO_ERC',
ERC_TO_NATIVE: 'ERC_TO_NATIVE',
NATIVE_TO_ERC_V1: 'NATIVE_TO_ERC_V1',
ARBITRARY_MESSAGE: 'ARBITRARY_MESSAGE'
}
const ERC_TYPES = {
ERC20: 'ERC20',
ERC677: 'ERC677'
}
const FEE_MANAGER_MODE = {
ONE_DIRECTION: 'ONE_DIRECTION',
BOTH_DIRECTIONS: 'BOTH_DIRECTIONS',
UNDEFINED: 'UNDEFINED'
}
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
module.exports = {
BRIDGE_MODES,
ERC_TYPES,
FEE_MANAGER_MODE,
ZERO_ADDRESS
}

11
commons/index.js Normal file
View File

@@ -0,0 +1,11 @@
const constants = require('./constants')
const abis = require('./abis')
const utils = require('./utils')
const message = require('./message')
module.exports = {
...constants,
...abis,
...utils,
...message
}

27
commons/message.js Normal file
View File

@@ -0,0 +1,27 @@
function strip0x(input) {
return input.replace(/^0x/, '')
}
function addTxHashToData({ encodedData, transactionHash }) {
return encodedData.slice(0, 2) + strip0x(transactionHash) + encodedData.slice(2)
}
function parseAMBMessage(message) {
message = strip0x(message)
const txHash = `0x${message.slice(0, 64)}`
const sender = `0x${message.slice(64, 104)}`
const executor = `0x${message.slice(104, 144)}`
return {
sender,
executor,
txHash
}
}
module.exports = {
addTxHashToData,
parseAMBMessage,
strip0x
}

17
commons/package.json Normal file
View File

@@ -0,0 +1,17 @@
{
"name": "commons",
"version": "0.0.1",
"private": true,
"main": "index.js",
"scripts": {
"lint": "eslint . --ignore-path ../.eslintignore",
"test": "NODE_ENV=test mocha"
},
"dependencies": {
"web3-utils": "1.0.0-beta.34"
},
"devDependencies": {
"bn-chai": "^1.0.1",
"chai": "^4.2.0"
}
}

View File

@@ -0,0 +1,12 @@
const { expect } = require('chai')
const { BRIDGE_MODES, ERC_TYPES } = require('../constants')
describe('constants', () => {
it('should contain correct number of bridge types', () => {
expect(Object.keys(BRIDGE_MODES).length).to.be.equal(5)
})
it('should contain correct number of erc types', () => {
expect(Object.keys(ERC_TYPES).length).to.be.equal(2)
})
})

162
commons/test/gas.js Normal file
View File

@@ -0,0 +1,162 @@
const { expect } = require('chai')
const Web3Utils = require('web3-utils')
const { gasPriceWithinLimits, normalizeGasPrice } = require('..')
const GAS_PRICE_BOUNDARIES = {
MIN: 1,
MAX: 250
}
describe('gas', () => {
describe('normalizeGasPrice', () => {
it('should work with oracle gas price in gwei', () => {
// Given
const oracleGasPrice = 30
const factor = 1
// When
const result = normalizeGasPrice(oracleGasPrice, factor).toString()
// Then
expect(result).to.equal('30000000000')
})
it('should work with oracle gas price not in gwei', () => {
// Given
const oracleGasPrice = 300
const factor = 0.1
// When
const result = normalizeGasPrice(oracleGasPrice, factor).toString()
// Then
expect(result).to.equal('30000000000')
})
it('should increase gas price value from oracle', () => {
// Given
const oracleGasPrice = 20
const factor = 1.5
// When
const result = normalizeGasPrice(oracleGasPrice, factor).toString()
// Then
expect(result).to.equal('30000000000')
})
})
describe('gasPriceWithinLimits', () => {
it('should return gas price if gas price is between boundaries', () => {
// given
const minGasPrice = 1
const middleGasPrice = 10
const maxGasPrice = 250
// when
const minGasPriceWithinLimits = gasPriceWithinLimits(minGasPrice, GAS_PRICE_BOUNDARIES)
const middleGasPriceWithinLimits = gasPriceWithinLimits(middleGasPrice, GAS_PRICE_BOUNDARIES)
const maxGasPriceWithinLimits = gasPriceWithinLimits(maxGasPrice, GAS_PRICE_BOUNDARIES)
// then
expect(minGasPriceWithinLimits).to.equal(minGasPrice)
expect(middleGasPriceWithinLimits).to.equal(middleGasPrice)
expect(maxGasPriceWithinLimits).to.equal(maxGasPrice)
})
it('should return min limit if gas price is below min boundary', () => {
// Given
const initialGasPrice = 0.5
// When
const gasPrice = gasPriceWithinLimits(initialGasPrice, GAS_PRICE_BOUNDARIES)
// Then
expect(gasPrice).to.equal(GAS_PRICE_BOUNDARIES.MIN)
})
it('should return max limit if gas price is above max boundary', () => {
// Given
const initialGasPrice = 260
// When
const gasPrice = gasPriceWithinLimits(initialGasPrice, GAS_PRICE_BOUNDARIES)
// Then
expect(gasPrice).to.equal(GAS_PRICE_BOUNDARIES.MAX)
})
it('should return gas price if boundaries not provided', () => {
// Given
const initialGasPrice = 260
// When
const gasPrice = gasPriceWithinLimits(initialGasPrice)
// Then
expect(gasPrice).to.equal(initialGasPrice)
})
})
describe('normalizeGasPrice', () => {
it('should work with oracle gas price in gwei', () => {
// Given
const oracleGasPrice = 20
const factor = 1
// When
const result = normalizeGasPrice(oracleGasPrice, factor).toString()
// Then
expect(result).to.equal('20000000000')
})
it('should work with oracle gas price not in gwei', () => {
// Given
const oracleGasPrice = 200
const factor = 0.1
// When
const result = normalizeGasPrice(oracleGasPrice, factor).toString()
// Then
expect(result).to.equal('20000000000')
})
it('should increase gas price value from oracle', () => {
// Given
const oracleGasPrice = 20
const factor = 1.5
// When
const result = normalizeGasPrice(oracleGasPrice, factor).toString()
// Then
expect(result).to.equal('30000000000')
})
it('should respect gas price max limit', () => {
// Given
const oracleGasPrice = 200
const factor = 4
const maxInWei = Web3Utils.toWei(GAS_PRICE_BOUNDARIES.MAX.toString(), 'gwei')
// When
const result = normalizeGasPrice(oracleGasPrice, factor, GAS_PRICE_BOUNDARIES).toString()
// Then
expect(result).to.equal(maxInWei)
})
it('should respect gas price min limit', () => {
// Given
const oracleGasPrice = 1
const factor = 0.01
const minInWei = Web3Utils.toWei(GAS_PRICE_BOUNDARIES.MIN.toString(), 'gwei')
// When
const result = normalizeGasPrice(oracleGasPrice, factor, GAS_PRICE_BOUNDARIES).toString()
// Then
expect(result).to.equal(minInWei)
})
})
})

View File

@@ -0,0 +1,64 @@
const { expect } = require('chai')
const { getTokenType, ERC_TYPES } = require('..')
describe('getTokenType', () => {
it('should return ERC677 if bridgeContract is equal to bridgeAddress', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.resolve(bridgeAddress)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC677)
})
it('should return ERC20 if bridgeContract is not equal to bridgeAddress', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.resolve('0xBFCb120F7B1de491262CA4D9D8Eba70438b6896E')
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
it('should return ERC20 if bridgeContract is not present', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
})

View File

@@ -0,0 +1,69 @@
const { BN } = require('web3-utils')
const { expect } = require('chai').use(require('bn-chai')(BN))
const { parseAMBMessage, strip0x, addTxHashToData } = require('../message')
describe('strip0x', () => {
it('should remove 0x from input', () => {
// Given
const input = '0x12345'
// When
const result = strip0x(input)
// Then
expect(result).to.be.equal('12345')
})
it('should not modify input if 0x is not present', () => {
// Given
const input = '12345'
// When
const result = strip0x(input)
// Then
expect(result).to.be.equal(input)
})
})
describe('addTxHashToData', () => {
it('should add txHash to encoded data at position 2', () => {
// Given
const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e'
const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955'
const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705'
const msgDataType = '00'
const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03'
const encodedData = `0x${strip0x(msgSender)}${strip0x(msgExecutor)}${msgGasLimit}${msgDataType}${strip0x(msgData)}`
const transactionHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10'
const message = `0x${strip0x(transactionHash)}${strip0x(msgSender)}${strip0x(
msgExecutor
)}${msgGasLimit}${msgDataType}${strip0x(msgData)}`
// When
const result = addTxHashToData({ encodedData, transactionHash })
// Then
expect(result).to.be.equal(message)
})
})
describe('parseAMBMessage', () => {
it('should parse data type 00', () => {
const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e'
const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955'
const msgTxHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10'
const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705'
const msgDataType = '00'
const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03'
const message = `0x${strip0x(msgTxHash)}${strip0x(msgSender)}${strip0x(
msgExecutor
)}${msgGasLimit}${msgDataType}${strip0x(msgData)}`
// when
const { sender, executor, txHash } = parseAMBMessage(message)
// then
expect(sender).to.be.equal(msgSender)
expect(executor).to.be.equal(msgExecutor)
expect(txHash).to.be.equal(msgTxHash)
})
})

View File

@@ -1,4 +1,5 @@
import { processValidatorsEvents, parseValidatorEvent } from '../contract'
const { expect } = require('chai')
const { processValidatorsEvents, parseValidatorEvent } = require('..')
describe('parseValidatorEvent', () => {
it('should parse ValidatorAdded event from v1', () => {
@@ -14,8 +15,8 @@ describe('parseValidatorEvent', () => {
parseValidatorEvent(event)
// Then
expect(event.event).toBe('ValidatorAdded')
expect(event.returnValues.validator).toBe('0xcfef0c6bb765321529ffe81507f6d099693cd225')
expect(event.event).to.be.equal('ValidatorAdded')
expect(event.returnValues.validator).to.be.equal('0xcfef0c6bb765321529ffe81507f6d099693cd225')
})
it('should parse ValidatorAdded event', () => {
// Given
@@ -33,8 +34,8 @@ describe('parseValidatorEvent', () => {
parseValidatorEvent(event)
// Then
expect(event.event).toBe('ValidatorAdded')
expect(event.returnValues.validator).toBe('0xcfef0c6bb765321529ffe81507f6d099693cd225')
expect(event.event).to.be.equal('ValidatorAdded')
expect(event.returnValues.validator).to.be.equal('0xcfef0c6bb765321529ffe81507f6d099693cd225')
})
it('should parse ValidatorAdded event from rewardableValidators', () => {
// Given
@@ -52,8 +53,8 @@ describe('parseValidatorEvent', () => {
parseValidatorEvent(event)
// Then
expect(event.event).toBe('ValidatorAdded')
expect(event.returnValues.validator).toBe('0xcfef0c6bb765321529ffe81507f6d099693cd225')
expect(event.event).to.be.equal('ValidatorAdded')
expect(event.returnValues.validator).to.be.equal('0xcfef0c6bb765321529ffe81507f6d099693cd225')
})
it('should parse ValidatorRemoved event', () => {
// Given
@@ -71,8 +72,8 @@ describe('parseValidatorEvent', () => {
parseValidatorEvent(event)
// Then
expect(event.event).toBe('ValidatorRemoved')
expect(event.returnValues.validator).toBe('0xcfef0c6bb765321529ffe81507f6d099693cd225')
expect(event.event).to.be.equal('ValidatorRemoved')
expect(event.returnValues.validator).to.be.equal('0xcfef0c6bb765321529ffe81507f6d099693cd225')
})
it('should parse ValidatorRemoved event from v1', () => {
// Given
@@ -87,8 +88,8 @@ describe('parseValidatorEvent', () => {
parseValidatorEvent(event)
// Then
expect(event.event).toBe('ValidatorRemoved')
expect(event.returnValues.validator).toBe('0xcfef0c6bb765321529ffe81507f6d099693cd225')
expect(event.event).to.be.equal('ValidatorRemoved')
expect(event.returnValues.validator).to.be.equal('0xcfef0c6bb765321529ffe81507f6d099693cd225')
})
})
describe('processValidatorsEvents', () => {
@@ -169,9 +170,9 @@ describe('processValidatorsEvents', () => {
const validatorList = processValidatorsEvents(events)
// Then
expect(validatorList.length).toBe(3)
expect(validatorList[0]).toBe('0xCbd25A2a5708051747a052dBB1b291865Fc0e474')
expect(validatorList[1]).toBe('0xBac68A86Cf596E3b124781E0bdbC47bb458bec62')
expect(validatorList[2]).toBe('0xf4BEF13F9f4f2B203FAF0C3cBbaAbe1afE056955')
expect(validatorList.length).to.be.equal(3)
expect(validatorList[0]).to.be.equal('0xCbd25A2a5708051747a052dBB1b291865Fc0e474')
expect(validatorList[1]).to.be.equal('0xBac68A86Cf596E3b124781E0bdbC47bb458bec62')
expect(validatorList[2]).to.be.equal('0xf4BEF13F9f4f2B203FAF0C3cBbaAbe1afE056955')
})
})

264
commons/utils.js Normal file
View File

@@ -0,0 +1,264 @@
const { toWei, toBN } = require('web3-utils')
const { BRIDGE_MODES, FEE_MANAGER_MODE, ERC_TYPES } = require('./constants')
const { REWARDABLE_VALIDATORS_ABI } = require('./abis')
function decodeBridgeMode(bridgeModeHash) {
switch (bridgeModeHash) {
case '0x92a8d7fe':
return BRIDGE_MODES.NATIVE_TO_ERC
case '0xba4690f5':
return BRIDGE_MODES.ERC_TO_ERC
case '0x18762d46':
return BRIDGE_MODES.ERC_TO_NATIVE
case '0x2544fbb9':
return BRIDGE_MODES.ARBITRARY_MESSAGE
default:
throw new Error(`Unrecognized bridge mode hash: '${bridgeModeHash}'`)
}
}
const decodeFeeManagerMode = managerModeHash => {
switch (managerModeHash) {
case '0xf2aed8f7':
return FEE_MANAGER_MODE.ONE_DIRECTION
case '0xd7de965f':
return FEE_MANAGER_MODE.BOTH_DIRECTIONS
default:
throw new Error(`Unrecognized fee manager mode hash: '${managerModeHash}'`)
}
}
async function getBridgeMode(contract) {
try {
const bridgeModeHash = await contract.methods.getBridgeMode().call()
return decodeBridgeMode(bridgeModeHash)
} catch (e) {
return BRIDGE_MODES.NATIVE_TO_ERC_V1
}
}
const getTokenType = async (bridgeTokenContract, bridgeAddress) => {
try {
const resultBridgeAddress = await bridgeTokenContract.methods.bridgeContract().call()
if (resultBridgeAddress === bridgeAddress) {
return ERC_TYPES.ERC677
} else {
return ERC_TYPES.ERC20
}
} catch (e) {
return ERC_TYPES.ERC20
}
}
const getUnit = bridgeMode => {
let unitHome = null
let unitForeign = null
if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC) {
unitHome = 'Native coins'
unitForeign = 'Tokens'
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
unitHome = 'Tokens'
unitForeign = 'Tokens'
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
unitHome = 'Native coins'
unitForeign = 'Tokens'
} else {
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
}
return { unitHome, unitForeign }
}
const parseValidatorEvent = event => {
if (
event.event === undefined &&
event.raw &&
event.raw.topics &&
(event.raw.topics[0] === '0xe366c1c0452ed8eec96861e9e54141ebff23c9ec89fe27b996b45f5ec3884987' ||
event.raw.topics[0] === '0x8064a302796c89446a96d63470b5b036212da26bd2debe5bec73e0170a9a5e83')
) {
const rawAddress = event.raw.topics.length > 1 ? event.raw.topics[1] : event.raw.data
const address = '0x' + rawAddress.slice(26)
event.event = 'ValidatorAdded'
event.returnValues.validator = address
} else if (
event.event === undefined &&
event.raw &&
event.raw.topics &&
event.raw.topics[0] === '0xe1434e25d6611e0db941968fdc97811c982ac1602e951637d206f5fdda9dd8f1'
) {
const rawAddress = event.raw.data === '0x' ? event.raw.topics[1] : event.raw.data
const address = '0x' + rawAddress.slice(26)
event.event = 'ValidatorRemoved'
event.returnValues.validator = address
}
}
const processValidatorsEvents = events => {
const validatorList = new Set()
events.forEach(event => {
parseValidatorEvent(event)
if (event.event === 'ValidatorAdded') {
validatorList.add(event.returnValues.validator)
} else if (event.event === 'ValidatorRemoved') {
validatorList.delete(event.returnValues.validator)
}
})
return Array.from(validatorList)
}
const tryCall = async (method, fallbackValue) => {
try {
return await method.call()
} catch (e) {
return fallbackValue
}
}
const getDeployedAtBlock = async contract => tryCall(contract.methods.deployedAtBlock(), 0)
const getPastEvents = async (
contract,
{ event = 'allEvents', fromBlock = toBN(0), toBlock = 'latest', options = {} }
) => {
let events
try {
events = await contract.getPastEvents(event, {
...options,
fromBlock,
toBlock
})
} catch (e) {
if (e.message.includes('query returned more than') && toBlock !== 'latest') {
const middle = toBN(fromBlock)
.add(toBlock)
.divRound(toBN(2))
const middlePlusOne = middle.add(toBN(1))
const firstHalfEvents = await getPastEvents(contract, {
...options,
event,
fromBlock,
toBlock: middle
})
const secondHalfEvents = await getPastEvents(contract, {
...options,
event,
fromBlock: middlePlusOne,
toBlock
})
events = [...firstHalfEvents, ...secondHalfEvents]
} else {
throw new Error(e)
}
}
return events
}
const getValidatorList = async (address, eth, options) => {
options.logger && options.logger.debug && options.logger.debug('getting validatorList')
const validatorsContract = new eth.Contract(REWARDABLE_VALIDATORS_ABI, address) // in monitor, BRIDGE_VALIDATORS_ABI was used
const validators = await tryCall(validatorsContract.methods.validatorList(), [])
if (validators.length) {
return validators
}
options.logger && options.logger.debug && options.logger.debug('getting validatorsEvents')
const deployedAtBlock = await tryCall(validatorsContract.methods.deployedAtBlock(), 0)
const fromBlock = options.fromBlock || Number(deployedAtBlock) || 0
const toBlock = options.toBlock || 'latest'
const validatorsEvents = await getPastEvents(new eth.Contract([], address), {
event: 'allEvents',
fromBlock,
toBlock,
options: {}
})
return processValidatorsEvents(validatorsEvents)
}
const gasPriceWithinLimits = (gasPrice, limits) => {
if (!limits) {
return gasPrice
}
if (gasPrice < limits.MIN) {
return limits.MIN
} else if (gasPrice > limits.MAX) {
return limits.MAX
} else {
return gasPrice
}
}
const normalizeGasPrice = (oracleGasPrice, factor, limits = null) => {
let gasPrice = oracleGasPrice * factor
gasPrice = gasPriceWithinLimits(gasPrice, limits)
return toBN(toWei(gasPrice.toFixed(2).toString(), 'gwei'))
}
// fetchFn has to be supplied (instead of just url to oracle),
// because this utility function is shared between Browser and Node,
// we use built-in 'fetch' on browser side, and `node-fetch` package in Node.
const gasPriceFromSupplier = async (fetchFn, options = {}) => {
try {
const response = await fetchFn()
const json = await response.json()
const oracleGasPrice = json[options.speedType]
if (!oracleGasPrice) {
options.logger &&
options.logger.error &&
options.logger.error(`Response from Oracle didn't include gas price for ${options.speedType} type.`)
return null
}
const normalizedGasPrice = normalizeGasPrice(oracleGasPrice, options.factor, options.limits)
options.logger &&
options.logger.debug &&
options.logger.debug({ oracleGasPrice, normalizedGasPrice }, 'Gas price updated using the API')
return normalizedGasPrice
} catch (e) {
options.logger && options.logger.error && options.logger.error(`Gas Price API is not available. ${e.message}`)
}
return null
}
const gasPriceFromContract = async (bridgeContract, options = {}) => {
try {
const gasPrice = await bridgeContract.methods.gasPrice().call()
options.logger &&
options.logger.debug &&
options.logger.debug({ gasPrice }, 'Gas price updated using the contracts')
return gasPrice
} catch (e) {
options.logger &&
options.logger.error &&
options.logger.error(`There was a problem getting the gas price from the contract. ${e.message}`)
}
return null
}
module.exports = {
decodeBridgeMode,
decodeFeeManagerMode,
getBridgeMode,
getTokenType,
getUnit,
parseValidatorEvent,
processValidatorsEvents,
getValidatorList,
getPastEvents,
getDeployedAtBlock,
normalizeGasPrice,
gasPriceFromSupplier,
gasPriceFromContract,
gasPriceWithinLimits
}

163
commons/v1Abis.js Normal file
View File

@@ -0,0 +1,163 @@
const homeV1Abi = [
{
constant: true,
inputs: [],
name: 'validatorContract',
outputs: [
{
name: '',
type: 'address'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
}
],
name: 'Deposit',
type: 'event'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'transactionHash',
type: 'bytes32'
}
],
name: 'Withdraw',
type: 'event'
},
{
constant: true,
inputs: [],
name: 'deployedAtBlock',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
const foreignViAbi = [
{
constant: true,
inputs: [],
name: 'validatorContract',
outputs: [
{
name: '',
type: 'address'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'transactionHash',
type: 'bytes32'
}
],
name: 'Deposit',
type: 'event'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'homeGasPrice',
type: 'uint256'
}
],
name: 'Withdraw',
type: 'event'
},
{
constant: true,
inputs: [],
name: 'deployedAtBlock',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'erc677token',
outputs: [
{
name: '',
type: 'address'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
module.exports = {
HOME_V1_ABI: homeV1Abi,
FOREIGN_V1_ABI: foreignViAbi
}

View File

@@ -0,0 +1,4 @@
FROM python:3.7-stretch
RUN curl -fsSL https://get.docker.com | sh
RUN pip3 install docker molecule==2.22rc1 molecule[docker] flake8
WORKDIR mono/deployment-e2e

36
deployment-e2e/README.md Normal file
View File

@@ -0,0 +1,36 @@
# POA TokenBridge / Deployment Testing
The deployment playbooks are tested using [Molecule](https://molecule.readthedocs.io).
## Push remote branch
The deployment playbooks are cloning the monorepository on target hosts, using your current local git branch name. If the branch does not exists on remote, you need to push it.
```
git push
```
Alternatively, if there are no changes except the playbooks, you can use the `master` branch:
```
CIRCLE_BRANCH=master ./molecule.sh <scenario_name>
```
In this case `master` branch will be used as a codebase for Monitor, UI, Oracle and Contracts deployed by your local playbook.
## Run the tests
```
CIRCLE_BRANCH=master ./molecule.sh <scenario_name>
```
Available scenarios:
Scenario | Description
--- | ---
oracle | Deploys and checks standalone Oracle on Ubuntu host
ui | Deploys and checks standalone UI on Ubuntu host
## Ultimate E2E tests
For information on the Ultimate tests, please refer to [Ultimate](../e2e-commons/ULTIMATE.md).

View File

@@ -0,0 +1,12 @@
---
version: '3.0'
services:
molecule_runner:
build:
context: ..
dockerfile: deployment-e2e/Dockerfile
restart: 'no'
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ..:/mono

9
deployment-e2e/molecule.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
cd $(dirname $0)
set -e # exit when any command fails
while [ "$1" != "" ]; do
docker-compose build && docker-compose run molecule_runner /bin/bash -c "molecule test --scenario-name $1"
shift # Shift all the parameters down by one
done

View File

@@ -0,0 +1,14 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

View File

@@ -0,0 +1,55 @@
---
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
enabled: True
options:
config-data:
ignore: ../../hosts.yml
platforms:
- name: monitor-host
groups:
- example
children:
- monitor
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
lint:
name: ansible-lint
enabled: True
options:
r: ["bug"]
playbooks:
prepare: ../prepare.yml
converge: ../../../deployment/site.yml
inventory:
host_vars:
monitor-host:
syslog_server_port: "udp://127.0.0.1:514"
verifier:
name: testinfra
lint:
name: flake8
additional_files_or_dirs:
- ../../tests/*
scenario:
name: monitor
test_sequence:
- lint
- cleanup
- destroy
- dependency
- syntax
- create
- prepare
- converge
- verify
- destroy

View File

@@ -0,0 +1,54 @@
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('monitor')
@pytest.mark.parametrize("name", [
("monitor_monitor_1")
])
def test_docker_containers(host, name):
container = host.docker(name)
assert container.is_running
@pytest.mark.parametrize("service", [
("tokenbridge-monitor"),
("rsyslog")
])
def test_services(host, service):
assert host.service(service).is_enabled
assert host.service(service).is_running
@pytest.mark.parametrize("filename", [
("/etc/rsyslog.d/33-monitor-docker.conf"),
("/etc/rsyslog.d/38-monitor-remote-logging.conf")
])
def test_logging(host, filename):
assert host.file(filename).exists
assert host.file(filename).mode == 0o0644
def test_home_exists(host):
assert host.run_test(
'curl -s http://localhost:3003 | '
'grep -q -i "home"'
)
def test_foreign_exists(host):
assert host.run_test(
'curl -s http://localhost:3003 | '
'grep -q -i "foreign"'
)
def test_no_error(host):
assert host.run_expect(
[1],
'curl -s http://localhost:3003 | '
'grep -i -q "error"'
)

View File

@@ -0,0 +1,14 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

View File

@@ -0,0 +1,56 @@
---
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
enabled: True
options:
config-data:
ignore: ../../hosts.yml
platforms:
- name: oracle-host
groups:
- example
children:
- oracle
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
lint:
name: ansible-lint
enabled: True
options:
r: ["bug"]
playbooks:
prepare: ../prepare.yml
converge: ../../../deployment/site.yml
inventory:
host_vars:
oracle-host:
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
syslog_server_port: "udp://127.0.0.1:514"
verifier:
name: testinfra
lint:
name: flake8
additional_files_or_dirs:
- ../../tests/*
scenario:
name: oracle
test_sequence:
- lint
- cleanup
- destroy
- dependency
- syntax
- create
- prepare
- converge
- verify
- destroy

View File

@@ -0,0 +1,38 @@
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('oracle')
@pytest.mark.parametrize("name", [
("oracle_rabbit_1"),
("oracle_redis_1"),
("oracle_bridge_request_1"),
("oracle_bridge_collected_1"),
("oracle_bridge_affirmation_1"),
("oracle_bridge_senderhome_1"),
("oracle_bridge_senderforeign_1"),
])
def test_docker_containers(host, name):
container = host.docker(name)
assert container.is_running
@pytest.mark.parametrize("service", [
("poabridge"),
("rsyslog")
])
def test_services(host, service):
assert host.service(service).is_enabled
assert host.service(service).is_running
@pytest.mark.parametrize("filename", [
("/etc/rsyslog.d/31-oracle-docker.conf"),
("/etc/rsyslog.d/36-oracle-remote-logging.conf")
])
def test_logging(host, filename):
assert host.file(filename).exists
assert host.file(filename).mode == 0o0644

View File

@@ -0,0 +1,13 @@
---
- name: prepare
hosts: all
tasks:
- name: install apt packages
apt:
name: "{{ packages }}"
vars:
packages:
- apt-transport-https
- rsyslog
- shell: service rsyslog start
- shell: groupadd docker && chgrp docker /var/run/docker.sock

View File

@@ -0,0 +1,14 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

View File

@@ -0,0 +1,12 @@
---
- name: Install Repository
hosts: all
become: true
tasks:
- import_role:
name: ../../../deployment/roles/common
tasks_from: repo
# Test that running the task again works
- import_role:
name: ../../../deployment/roles/common
tasks_from: repo

View File

@@ -0,0 +1,30 @@
---
driver:
name: docker
platforms:
- name: repo-host
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
playbooks:
prepare: ../prepare.yml
converge: ./converge.yml
inventory:
host_vars:
repo-host:
bridge_repo_branch: master
verifier:
name: testinfra
scenario:
name: repo
test_sequence:
- destroy
- create
- prepare
- converge
- verify
- destroy

View File

@@ -0,0 +1,49 @@
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
@pytest.mark.parametrize("path", [
("/home/poadocker"),
("/home/poadocker/bridge"),
("/home/poadocker/bridge/commons"),
("/home/poadocker/bridge/e2e-commons"),
("/home/poadocker/bridge/deployment"),
("/home/poadocker/bridge/contracts"),
("/home/poadocker/bridge/oracle"),
("/home/poadocker/bridge/monitor"),
("/home/poadocker/bridge/ui"),
("/home/poadocker/bridge/parity")
])
def test_existing_folders(host, path):
assert host.file(path).exists
assert host.file(path).is_directory
@pytest.mark.parametrize("path", [
("/home/poadocker/bridge/package.json"),
("/home/poadocker/bridge/commons/package.json"),
("/home/poadocker/bridge/contracts/package.json"),
("/home/poadocker/bridge/oracle/package.json"),
("/home/poadocker/bridge/monitor/package.json"),
("/home/poadocker/bridge/ui/package.json")
])
def test_existing_package_json(host, path):
assert host.file(path).exists
assert host.file(path).is_file
@pytest.mark.parametrize("path", [
("/home/poadocker/bridge/Dockerfile.e2e"),
("/home/poadocker/bridge/contracts/Dockerfile"),
("/home/poadocker/bridge/parity/Dockerfile"),
("/home/poadocker/bridge/oracle/Dockerfile"),
("/home/poadocker/bridge/monitor/Dockerfile"),
("/home/poadocker/bridge/ui/Dockerfile")
])
def test_existing_docker_files(host, path):
assert host.file(path).exists
assert host.file(path).is_file

View File

@@ -0,0 +1,23 @@
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
@pytest.mark.parametrize("path", [
("/home/poadocker/bridge/node_modules"),
("/home/poadocker/bridge/ui/node_modules"),
("/home/poadocker/bridge/oracle/node_modules"),
("/home/poadocker/bridge/monitor/node_modules"),
("/home/poadocker/bridge/contracts/node_modules"),
])
def test_non_existing_node_modules(host, path):
assert not host.file(path).exists
@pytest.mark.parametrize("path", [
("/home/poadocker/bridge/.git")
])
def test_non_existing_git(host, path):
assert not host.file(path).exists

View File

@@ -0,0 +1,34 @@
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
def test_repo(host):
assert host.file('/home/poadocker/bridge').exists
assert host.file('/home/poadocker/bridge').is_directory
assert host.file('/home/poadocker/bridge/package.json').exists
def test_docker_group(host):
assert host.group('docker').exists
def test_user(host):
assert host.user('poadocker').exists
assert 'docker' in host.user('poadocker').groups
@pytest.mark.parametrize("filename", [
("/etc/rsyslog.d/30-docker.conf"),
("/etc/rsyslog.d/35-docker-remote-logging.conf")
])
def test_logging(host, filename):
assert host.file(filename).exists
assert host.file(filename).mode == 0o0644
def test_docker_config(host):
assert host.file('/etc/docker/daemon.json').exists

View File

@@ -0,0 +1,14 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

View File

@@ -0,0 +1,55 @@
---
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
enabled: True
options:
config-data:
ignore: ../../hosts.yml
platforms:
- name: ui-host
groups:
- example
children:
- ui
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
lint:
name: ansible-lint
enabled: True
options:
r: ["bug"]
playbooks:
prepare: ../prepare.yml
converge: ../../../deployment/site.yml
inventory:
host_vars:
ui-host:
syslog_server_port: "udp://127.0.0.1:514"
verifier:
name: testinfra
lint:
name: flake8
additional_files_or_dirs:
- ../../tests/*
scenario:
name: ui
test_sequence:
- lint
- cleanup
- destroy
- dependency
- syntax
- create
- prepare
- converge
- verify
- destroy

View File

@@ -0,0 +1,48 @@
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('ui')
@pytest.mark.parametrize("name", [
("ui_ui_1")
])
def test_docker_containers(host, name):
container = host.docker(name)
assert container.is_running
@pytest.mark.parametrize("service", [
("tokenbridge-ui"),
("rsyslog")
])
def test_services(host, service):
assert host.service(service).is_enabled
assert host.service(service).is_running
@pytest.mark.parametrize("filename", [
("/etc/rsyslog.d/32-ui-docker.conf"),
("/etc/rsyslog.d/37-ui-remote-logging.conf")
])
def test_logging(host, filename):
assert host.file(filename).exists
assert host.file(filename).mode == 0o0644
def test_index_page_title(host):
assert host.run_test(
'curl -s http://localhost:3001 | '
'grep "<title>" | '
'grep -q "TokenBridge UI app"'
)
def test_index_page_error(host):
assert host.run_expect(
[1],
'curl -s http://localhost:3001 | '
'grep -i -q "error"'
)

View File

@@ -0,0 +1,5 @@
---
- import_playbook: ../../../deployment/site.yml
# The docker-compose files have to be modified, in order to join the docker containers over network with the parity containers
- import_playbook: ./oracle-docker-compose.yml
- import_playbook: ./ui-docker-compose.yml

View File

@@ -0,0 +1,62 @@
---
- name: Overwrite Oracle the docker-compose
hosts: oracle
become: true
tasks:
- name: stop the service
shell: service poabridge stop
- name: Slurp docker compose file
slurp:
src: "/home/poadocker/bridge/oracle/docker-compose.yml"
register: docker_compose_slurp
- name: Parse docker compose file
set_fact:
docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}"
- name: Add the external network used to connect to Parity nodes
set_fact:
docker_compose_parsed: "{{ docker_compose_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}"
- name: Add all Oracle containers to the network
set_fact:
docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {item: {'networks': docker_compose_parsed.services[item].networks | union(['ultimate'])}}}, recursive=True) }}"
with_items: "{{ docker_compose_parsed.services }}"
- name: Expose Redis port to allow connecting from redis-cli
set_fact:
docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {'redis': {'ports': ['6379:6379']}}}, recursive=True) }}"
- name: Write new docker-compose file
copy:
content: "{{ docker_compose_parsed | to_yaml }}"
dest: "/home/poadocker/bridge/oracle/docker-compose.yml"
- name: Slurp docker compose extended file
slurp:
src: "/home/poadocker/bridge/oracle/docker-compose-transfer.yml"
register: docker_compose_extended_slurp
- name: Parse docker compose file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_slurp['content'] | b64decode | from_yaml }}"
- name: Add the external network used to connect to Parity nodes in compose extended file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}"
- name: Add all Oracle containers to the network in compose extended file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed | combine({'services': {item: {'networks': docker_compose_extended_parsed.services[item].networks | union(['ultimate'])}}}, recursive=True) }}"
with_items: "{{ docker_compose_extended_parsed.services }}"
- name: Expose Redis port to allow connecting from redis-cli in compose extended file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed | combine({'services': {'redis': {'ports': ['6379:6379']}}}, recursive=True) }}"
- name: Write new docker-compose extended file
copy:
content: "{{ docker_compose_extended_parsed | to_yaml }}"
dest: "/home/poadocker/bridge/oracle/docker-compose-transfer.yml"
- name: start the service
shell: service poabridge start

View File

@@ -0,0 +1,32 @@
---
- name: Overwrite UI the docker-compose
hosts: ui
become: true
tasks:
- name: stop the service
shell: service tokenbridge-ui stop
- name: Slurp docker compose file
slurp:
src: "/home/poadocker/bridge/ui/docker-compose.yml"
register: docker_compose_slurp
- name: Parse docker compose file
set_fact:
docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}"
- name: Add the external network used to connect to Parity nodes
set_fact:
docker_compose_parsed: "{{ docker_compose_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}"
- name: Add all UI containers to the network
set_fact:
docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {item: {'networks': ['ultimate']}}}, recursive=True) }}"
with_items: "{{ docker_compose_parsed.services }}"
- name: Write new docker-compose file
copy:
content: "{{ docker_compose_parsed | to_yaml }}"
dest: "/home/poadocker/bridge/ui/docker-compose.yml"
- name: start the service
shell: service tokenbridge-ui start

View File

@@ -0,0 +1,14 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

View File

@@ -0,0 +1,54 @@
---
driver:
name: docker
platforms:
- name: oracle-erc-to-erc-host
groups:
- ultimate
- erc-to-erc
children:
- oracle
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- name: ui-erc-to-erc-host
groups:
- ultimate
- erc-to-erc
children:
- ui
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
playbooks:
prepare: ../prepare.yml
converge: ../ultimate-commons/converge.yml
inventory:
host_vars:
oracle-erc-to-erc-host:
COMMON_HOME_RPC_URL: "http://parity1:8545"
COMMON_FOREIGN_RPC_URL: "http://parity2:8545"
ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
ui-erc-to-erc-host:
COMMON_HOME_RPC_URL: "http://localhost:8541"
COMMON_FOREIGN_RPC_URL: "http://localhost:8542"
verifier:
name: testinfra
lint:
name: flake8
scenario:
name: ultimate-erc-to-erc
test_sequence:
- cleanup
- destroy
- syntax
- create
- prepare
- converge

View File

@@ -0,0 +1,14 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

View File

@@ -0,0 +1,56 @@
---
driver:
name: docker
platforms:
- name: oracle-erc-to-native-host
groups:
- ultimate
- erc-to-native
children:
- oracle
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- name: ui-erc-to-native-host
groups:
- ultimate
- erc-to-native
children:
- ui
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
playbooks:
prepare: ../prepare.yml
converge: ../ultimate-commons/converge.yml
inventory:
host_vars:
oracle-erc-to-native-host:
COMMON_HOME_RPC_URL: "http://parity1:8545"
COMMON_FOREIGN_RPC_URL: "http://parity2:8545"
ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
ORACLE_HOME_START_BLOCK: 1
ORACLE_FOREIGN_START_BLOCK: 1
ui-erc-to-native-host:
COMMON_HOME_RPC_URL: "http://localhost:8541"
COMMON_FOREIGN_RPC_URL: "http://localhost:8542"
verifier:
name: testinfra
lint:
name: flake8
scenario:
name: ultimate-erc-to-native
test_sequence:
- cleanup
- destroy
- syntax
- create
- prepare
- converge

View File

@@ -0,0 +1,14 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

View File

@@ -0,0 +1,54 @@
---
driver:
name: docker
platforms:
- name: oracle-native-to-erc-host
groups:
- ultimate
- native-to-erc
children:
- oracle
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- name: ui-native-to-erc-host
groups:
- ultimate
- native-to-erc
children:
- ui
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
playbooks:
prepare: ../prepare.yml
converge: ../ultimate-commons/converge.yml
inventory:
host_vars:
oracle-native-to-erc-host:
COMMON_HOME_RPC_URL: "http://parity1:8545"
COMMON_FOREIGN_RPC_URL: "http://parity2:8545"
ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
ui-native-to-erc-host:
COMMON_HOME_RPC_URL: "http://localhost:8541"
COMMON_FOREIGN_RPC_URL: "http://localhost:8542"
verifier:
name: testinfra
lint:
name: flake8
scenario:
name: ultimate-native-to-erc
test_sequence:
- cleanup
- destroy
- syntax
- create
- prepare
- converge

11
deployment/.yamllint Normal file
View File

@@ -0,0 +1,11 @@
extends: default
rules:
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
line-length: disable
truthy: disable

View File

@@ -0,0 +1,96 @@
# POA TokenBridge / Deployment Configuration
Please see the [Configuration](../CONFIGURATION.md) for additional configuration and execution details.
## Prerequisites
A functional Ubuntu 16.04 server launched using a trusted hosting provider. For more information, see our tutorials on [setting up a validator node on AWS](https://github.com/poanetwork/wiki/wiki/Validator-Node-on-AWS) or [setting up on non-AWS](https://github.com/poanetwork/wiki/wiki/Validator-Node-Non-AWS).
* Record the IP address (required for file setup).
* Setup ssh access to your node via public+private keys (using passwords is less secure).
* When creating the node, set a meaningful `hostname` that can identify you (e.g. `validator-0x...`).
## Initialization
1. Clone this repository and go to the `deployment` folder
```
git clone --recursive https://github.com/poanetwork/tokenbridge
cd tokenbridge/deployment
```
2. Create the file `hosts.yml` from `hosts.yml.example`
```
cp hosts.yml.example hosts.yml
```
`hosts.yml` should have the following structure:
```yaml
<bridge_name>:
children:
oracle:
hosts:
<host_ip_A>:
ansible_user: <user>
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "<private_key>"
#syslog_server_port: "<protocol>://<ip>:<port>" # When this parameter is set all bridge logs will be redirected to <ip>:<port> address.
<host_ip_B>:
# (...)
ui:
hosts:
<host_ip_B>:
ansible_user: <user>
#syslog_server_port: "<protocol>://<ip>:<port>"
<host_ip_C>:
ansible_user: <user>
#syslog_server_port: "<protocol>://<ip>:<port>"
monitor:
hosts:
<host_ip_B>:
ansible_user: <user>
#syslog_server_port: "<protocol>://<ip>:<port>"
#monitor_cron_schedule: "*/4 * * * *" # When this parameter is set, it will overwrite default schedule for performing checks
```
The config above would install the Oracle on `<host_ip_A>`, UI on `<host_ip_C>`, and both Oracle, UI and Monitor on `<host_ip_B>`.
Example config for installing only UI:
```yaml
<bridge_name>:
children:
oracle:
hosts:
ui:
hosts:
<host_ip>:
ansible_user: <user>
```
| Value | Description |
|:------------------------------------------------|:----------------------------------------------------------------------------------------------------------|
| `<bridge_name>` | The bridge name which tells Ansible which file to use. This is located in `group_vars/<bridge_name>.yml`. |
| `<host_ip>` | Remote server IP address. |
| ansible_user: `<user>` | User that will ssh into the node. This is typically `ubuntu` or `root`. |
| ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: `"<private_key>"` | The private key for the specified validator address. |
| syslog_server_port: `"<protocol>://<ip>:<port>"` | Optional port specification for bridge logs. This value will be provided by an administrator if required. |
`hosts.yml` can contain multiple bridge configurations at once.
3. Copy the bridge name(s) to the hosts.yml file.
1. Go to the group_vars folder.
`cd group_vars`
2. Note the <bridge_name> and add it to the hosts.yml configuration. For example, if a bridge file is named sokol-kovan.yml, you would change the <bridge_name> value in hosts.yml to sokol-kovan.
## Administrator Configurations
1. The `group_vars/<bridge_name>.yml` file contains the public bridge parameters. This file is prepared by administrators for each bridge. The validator only needs to add the required bridge name in the hosts.yml file to tell Ansible which file to use.
`group_vars/example.yml` shows an example configuration for the POA/Sokol - POA/Sokol bridge. Parameter values should match values from the .env file for the Oracle. See [Configuration parameters](../../oracle/README.md#configuration-parameters) for details.
2. You can also add the following parameters in the `group_vars` to change the default behavior of the playbooks:
2.1 `compose_service_user` - specifies the user created by the playbooks. This user runs the TokenBridge Oracle.
2.4 `bridge_path` sets the path where the TokenBridge Oracle is installed. By default, it points. to the home folder of `compose_service_user`
2.5 `docker_compose_version` - specifies a version of docker-compose to be installed.
2.6 `ALLOW_HTTP` (`no` by default) can be set to `yes` to allow bridge insecure connections to the network.

128
deployment/EXECUTION.md Normal file
View File

@@ -0,0 +1,128 @@
# POA TokenBridge / Deployment Execution
Please refer to the [Configuration](./CONFIGURATION.md) first.
## Dependencies
On your local machine install:
* Python 2 (v2.6-v2.7)/Python3 (v3.5+)
* [Ansible v2.3+](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)
* Git
The playbook will automatically install `Docker`, `docker-compose`, `Python`, `Git` and it dependencies (such as `curl`, `ca-certificates`, `apt-transport-https`, etc.) to the node. Also this playbooks creates an additional non-sudo docker user to run service as.
## Running the playbook
```yaml
ansible-playbook -i hosts.yml site.yml
```
## Useful arguments
To be used with the ansible-playbook command, for example:
```yaml
ansible-playbook -i hosts.yml site.yml --ask-become-pass
```
* `--ask-pass` - ask for the password used to connect to the bridge VM.
* `--ask-become-pass` - ask for the `become` password used to execute some commands (such as Docker installation) with root privileges.
* `-i <file>` - use specified file as a `hosts.yml` file.
* `-e "<variable>=<value>"` - override default variable.
* `--private-key=<file_name>` - if private keyfile is required to connect to the ubuntu instance.
* `--user=<username>` - connect as this username
## Service commands
The deployed components have the following services:
Component | Service Name
--- | ---
Oracle | poabridge
UI | tokenbridge-ui
Monitor | tokenbridge-monitor
Use the default `SysVinit` commands to `start`, `stop`, `restart`, and `rebuild` the service and to check the `status` of the service.
Commands format:
```bash
sudo service <service_name> [start|stop|restart|status|rebuild]
```
## Rollback the Last Processed Block in Redis
If the bridge does not handle an event properly (i.e. a transaction stalls due to a low gas price), the Redis DB can be rolled back. You must identify which watcher needs to re-run. For example, if the validator signatures were collected but the transaction with signatures was not sent to the Foreign network, the `collected-signatures` watcher must look at the block where the corresponding `CollectedSignatures` event was raised.
Execute the `reset-lastBlock.sh` script in the bridge root directory. For example, if you've installed your bridge with this deployment script and all the default parameters, use the following set of commands:
```shell
$ sudo su poadocker
$ cd ~/bridge
$ docker-compose stop bridge_affirmation bridge_request bridge_collected
$ docker-compose exec bridge_senderhome bash ./reset-lastBlock.sh <watcher> <block num>
$ exit
$ sudo service poabridge restart
```
where the _<watcher>_ could be one of the following:
- `signature-request`
- `collected-signatures`
- `affirmation-request`
## Reset nonce counters
In case some tx from your bridge validator account were done outside the bridge, you might need to update nonce counters.
1. ssh to your bridge node and run:
```
$ sudo su poadocker
$ cd ~/bridge
```
1. stop running docker containers using the nonce by running:
```
$ docker-compose stop bridge_senderhome bridge_senderforeign
```
1. Connect to the redis container:
```
$ docker-compose exec redis /bin/bash
```
you should get a shell prompt from inside the docker container, similar to this:
```
root@redis:/data#
```
1. connect to redis database by running `redis-cli`, prompt should change once again to
```
127.0.0.1:6379>
```
1. list existing keys by running `keys *`, output should look like this:
```
127.0.0.1:6379> keys *
1) "erc-native-affirmation-request:lastProcessedBlock"
2) "erc-native-collected-signatures:lastProcessedBlock"
3) "erc-native-signature-request:lastProcessedBlock"
4) "home:nonce"
5) "foreign:nonce"
```
1. delete keys containing last used nonces on both networks
```
127.0.0.1:6379> del "home:nonce" "foreign:nonce"
```
1. exit from redis container by running `exit` twice
1. start the rest of bridge containers:
```
$ docker-compose start bridge_senderhome bridge_senderforeign
```
## Logs
If the `syslog_server_port` option in the hosts.yml file is not set, all logs will be stored in `/var/log/docker/` folder in the set of folders with the `bridge_` prefix.
If the `syslog_server_port` is set, logs will be redirected to the specified server and cannot be accessed on the bridge machine.
```yaml
syslog_server_port: "<protocol>://<ip>:<port>" # When this parameter is set all bridge logs will be redirected to the <ip>:<port> address.
```

View File

@@ -1,33 +1,22 @@
# POA Token Bridge / Deployment
# POA TokenBridge / Deployment
Ansible playbooks for deploying cross-chain bridges.
## Overview
Please refer to the [POA Token Bridge](../README.md) overview first of all.
Please refer to the [POA TokenBridge](../README.md) overview first of all.
These playbooks are designed to automate the deployment process for cross-chain bridges on bridge validator nodes. This process installs the bridge as a service and sets .env configurations on a remote server. Playbooks for the current Token Bridge Oracle deployment are located in the [Oracle](oracle) folder.
## Dependencies
The playbooks automatically install `Docker`, `docker-compose`, `Python`, `Git`and it dependencies (such as `curl`, `ca-certificates`, `apt-transport-https`, etc.). Install [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) to launch playbooks.
## Linting
- [ansible-lint](https://github.com/ansible/ansible-lint) is required
`yarn ansible-lint`
These playbooks are designed to automate the deployment process for cross-chain bridges on bridge validator nodes. This process installs the bridge as a service and sets .env configurations on a remote server.
## Configuration
Please see the [Oracle](../oracle/README.md) for configuration and execution details.
Please refer to [Configuration](./CONFIGURATION.md).
## Bridge service commands
## Execution
The Bridge service is named `poabridge`. Use the default `SysVinit` commands to `start`, `stop`, `restart`, and `rebuild` the service and to check the `status` of the service.
Please refer to [Execution](./EXECUTION.md).
Commands format:
```bash
sudo service poabridge [start|stop|restart|status|rebuild]
```
## Testing
Please refer to [Deployment-E2E](../deployment-e2e/README.md).
## Contributing

View File

@@ -0,0 +1,50 @@
---
## General settings
ORACLE_BRIDGE_MODE: "ERC_TO_NATIVE"
UI_NATIVE_TOKEN_DISPLAY_NAME: "xDai"
## Home contract
COMMON_HOME_RPC_URL: "https://dai.poa.network"
UI_HOME_NETWORK_DISPLAY_NAME: "xDai chain"
UI_HOME_WITHOUT_EVENTS: false
COMMON_HOME_BRIDGE_ADDRESS: "0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6"
ORACLE_HOME_RPC_POLLING_INTERVAL: 5000
## Foreign contract
COMMON_FOREIGN_RPC_URL: "https://mainnet.infura.io"
UI_FOREIGN_NETWORK_DISPLAY_NAME: "Ethereum Mainnet"
UI_FOREIGN_WITHOUT_EVENTS: false
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x4aa42145Aa6Ebf72e164C9bBC74fbD3788045016"
ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 5000
## Home Gasprice
# COMMON_HOME_GAS_PRICE_SUPPLIER_URL: "https://localhost:8888/"
COMMON_HOME_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_HOME_GAS_PRICE_FALLBACK: 0
COMMON_HOME_GAS_PRICE_FACTOR: 600000
## Foreign Gasprice
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_FOREIGN_GAS_PRICE_FALLBACK: 10000000000
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
COMMON_FOREIGN_GAS_PRICE_FACTOR: 1
## UI
UI_TITLE: "TokenBridge UI app - %c"
UI_DESCRIPTION: "The TokenBridge serves as a method of transferring MakerDAO stable tokens between the Ethereum network to xDai chain in a quick and cost-efficient manner."
UI_PORT: 3001
UI_HOME_EXPLORER_TX_TEMPLATE: https://blockscout.com/poa/dai/tx/%s
UI_FOREIGN_EXPLORER_TX_TEMPLATE: https://blockscout.com/eth/mainnet/tx/%s
UI_HOME_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/poa/dai/address/%s
UI_FOREIGN_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/eth/mainnet/address/%s
UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
## Monitor
MONITOR_PORT: 3003
MONITOR_HOME_START_BLOCK: 759
MONITOR_FOREIGN_START_BLOCK: 6478417
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
MONITOR_TX_NUMBER_THRESHOLD: 100

View File

@@ -0,0 +1,6 @@
---
ORACLE_BRIDGE_MODE: "ERC_TO_ERC"
COMMON_HOME_BRIDGE_ADDRESS: "0x1feB40aD9420b186F019A717c37f5546165d411E"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127"
UI_PORT: 3001
MONITOR_PORT: 3011

View File

@@ -0,0 +1,6 @@
---
ORACLE_BRIDGE_MODE: "ERC_TO_NATIVE"
COMMON_HOME_BRIDGE_ADDRESS: "0x488Af810997eD1730cB3a3918cD83b3216E6eAda"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x488Af810997eD1730cB3a3918cD83b3216E6eAda"
UI_PORT: 3002
MONITOR_PORT: 3012

View File

@@ -0,0 +1,52 @@
---
## General settings
ORACLE_BRIDGE_MODE: "NATIVE_TO_ERC"
ORACLE_LOG_LEVEL: debug
UI_NATIVE_TOKEN_DISPLAY_NAME: "POA"
## Home contract
COMMON_HOME_RPC_URL: "https://sokol.poa.network"
UI_HOME_NETWORK_DISPLAY_NAME: "POA Sokol"
UI_HOME_WITHOUT_EVENTS: false
COMMON_HOME_BRIDGE_ADDRESS: "0x98aFdE294f1C46aA0a27Cc4049ED337F879d8976"
ORACLE_HOME_RPC_POLLING_INTERVAL: 5000
## Foreign contract
COMMON_FOREIGN_RPC_URL: "https://sokol.poa.network"
UI_FOREIGN_NETWORK_DISPLAY_NAME: "Kovan"
UI_FOREIGN_WITHOUT_EVENTS: false
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x5a584f4C30B36f282848dAc9a2b20E7BEF481981"
ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 1000
## Home Gasprice
COMMON_HOME_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
COMMON_HOME_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_HOME_GAS_PRICE_FALLBACK: 1000000000 # in wei
COMMON_HOME_GAS_PRICE_FACTOR: 1
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
## Foreign Gasprice
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_FOREIGN_GAS_PRICE_FALLBACK: 1000000000 # in wei
COMMON_FOREIGN_GAS_PRICE_FACTOR: 1
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
## UI
UI_TITLE: "TokenBridge UI app - %c"
UI_DESCRIPTION: "The POA cross-chain bridge serves as a method of transferring POA native tokens from the POA Network to the Ethereum network in a quick and cost-efficient manner."
UI_PORT: 3001
UI_HOME_EXPLORER_TX_TEMPLATE: https://blockscout.com/poa/sokol/tx/%s
UI_FOREIGN_EXPLORER_TX_TEMPLATE: https://blockscout.com/eth/kovan/tx/%s
UI_HOME_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/poa/sokol/address/%s
UI_FOREIGN_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/eth/kovan/address/%s
UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
## Monitor
MONITOR_PORT: 3003
MONITOR_HOME_START_BLOCK: 0
MONITOR_FOREIGN_START_BLOCK: 0
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
MONITOR_LEFT_TX_THRESHOLD: 100

View File

@@ -0,0 +1,6 @@
---
ORACLE_BRIDGE_MODE: "NATIVE_TO_ERC"
COMMON_HOME_BRIDGE_ADDRESS: "0x32198D570fffC7033641F8A9094FFDCaAEF42624"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x2B6871b9B02F73fa24F4864322CdC78604207769"
UI_PORT: 3000
MONITOR_PORT: 3010

View File

@@ -0,0 +1,49 @@
---
## General settings
UI_NATIVE_TOKEN_DISPLAY_NAME: "POA"
ORACLE_ALLOW_HTTP_FOR_RPC: yes
ORACLE_LOG_LEVEL: debug
## Home contract
COMMON_HOME_RPC_URL: "https://sokol.poa.network"
UI_HOME_NETWORK_DISPLAY_NAME: "POA Sokol"
UI_HOME_WITHOUT_EVENTS: false
ORACLE_HOME_RPC_POLLING_INTERVAL: 5000
## Foreign contract
COMMON_FOREIGN_RPC_URL: "https://sokol.poa.network"
UI_FOREIGN_NETWORK_DISPLAY_NAME: "Kovan"
UI_FOREIGN_WITHOUT_EVENTS: false
ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 1000
## Home Gasprice
COMMON_HOME_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
COMMON_HOME_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_HOME_GAS_PRICE_FALLBACK: 1000000000 # in wei
COMMON_HOME_GAS_PRICE_FACTOR: 1
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
## Foreign Gasprice
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_FOREIGN_GAS_PRICE_FALLBACK: 1000000000 # in wei
COMMON_FOREIGN_GAS_PRICE_FACTOR: 1
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
#ui
UI_TITLE: "TokenBridge UI app - %c"
UI_DESCRIPTION: "The POA cross-chain bridge serves as a method of transferring POA native tokens from the POA Network to the Ethereum network in a quick and cost-efficient manner."
UI_HOME_EXPLORER_TX_TEMPLATE: https://blockscout.com/poa/sokol/tx/%s
UI_FOREIGN_EXPLORER_TX_TEMPLATE: https://blockscout.com/eth/kovan/tx/%s
UI_HOME_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/poa/sokol/address/%s
UI_FOREIGN_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/eth/kovan/address/%s
UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
#montior
MONITOR_HOME_START_BLOCK: 0
MONITOR_FOREIGN_START_BLOCK: 0
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
MONITOR_LEFT_TX_THRESHOLD: 100

View File

@@ -0,0 +1,51 @@
---
## General settings
ORACLE_BRIDGE_MODE: "NATIVE_TO_ERC"
UI_NATIVE_TOKEN_DISPLAY_NAME: "ETC"
## Home contract
COMMON_HOME_RPC_URL: "https://ethereumclassic.network"
UI_HOME_NETWORK_DISPLAY_NAME: "Ethereum Classic"
UI_HOME_WITHOUT_EVENTS: false
COMMON_HOME_BRIDGE_ADDRESS: "0x073081832B4Ecdce79d4D6753565c85Ba4b3BeA9"
ORACLE_HOME_RPC_POLLING_INTERVAL: 7000
## Foreign contract
COMMON_FOREIGN_RPC_URL: "https://mainnet.infura.io/"
UI_FOREIGN_NETWORK_DISPLAY_NAME: "Ethereum Mainnet"
UI_FOREIGN_WITHOUT_EVENTS: false
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x0cB781EE62F815bdD9CD4c2210aE8600d43e7040"
ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 7000
## Home Gasprice
COMMON_HOME_GAS_PRICE_SUPPLIER_URL: "https://gasprice-etc.poa.network/"
COMMON_HOME_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_HOME_GAS_PRICE_FALLBACK: 15000000000 # in wei
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
COMMON_HOME_GAS_PRICE_FACTOR: 1
## Foreign Gasprice
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_FOREIGN_GAS_PRICE_FALLBACK: 10000000000 # in wei
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
COMMON_FOREIGN_GAS_PRICE_FACTOR: 1
## UI
UI_TITLE: "TokenBridge UI app - %c"
UI_DESCRIPTION: "The TokenBridge serves as a method of transferring native tokens from the Ethereum Classic Network to the Ethereum network in a quick and cost-efficient manner."
UI_PORT: 3001
UI_HOME_EXPLORER_TX_TEMPLATE: https://blockscout.com/etc/mainnet/tx/%s
UI_FOREIGN_EXPLORER_TX_TEMPLATE: https://blockscout.com/eth/mainnet/tx/%s
UI_HOME_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/etc/mainnet/address/%s
UI_FOREIGN_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/eth/mainnet/address/%s
UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
## Monitor
MONITOR_PORT: 3003
MONITOR_HOME_START_BLOCK: 7703292
MONITOR_FOREIGN_START_BLOCK: 7412459
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
MONITOR_TX_NUMBER_THRESHOLD: 100

View File

@@ -0,0 +1,20 @@
---
sokol-kovan:
children:
oracle:
hosts:
127.0.0.1:
ansible_user: ubuntu
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#syslog_server_port: "udp://127.0.0.1:514"
ui:
hosts:
127.0.0.1:
ansible_user: ubuntu
#syslog_server_port: "udp://127.0.0.1:514"
monitor:
hosts:
127.0.0.1:
ansible_user: ubuntu
#syslog_server_port: "<protocol>://<ip>:<port>"
#monitor_cron_schedule: "*/4 * * * *"

View File

@@ -1,3 +0,0 @@
#!/bin/bash
cd $(dirname $0)
ansible-lint -v -t bug ./oracle/roles/**

View File

@@ -1,138 +0,0 @@
### Prerequisites
1. A functional Ubuntu 16.04 server launched using a trusted hosting provider. For more information, see our tutorials on [setting up a validator node on AWS](https://github.com/poanetwork/wiki/wiki/Validator-Node-on-AWS) or [setting up on non-AWS](https://github.com/poanetwork/wiki/wiki/Validator-Node-Non-AWS).
* Record the IP address (required for file setup).
* Setup ssh access to your node via public+private keys (using passwords is less secure).
* When creating the node, set a meaningful `hostname` that can identify you (e.g. `validator-0x...`).
2. On your local machine install:
* Python 2 (v2.6-v2.7)/Python3 (v3.5+)
* Ansible v2.3+
* Git
### Configuration
1. Clone this repository and go to the `deployment/oracle` folder
```
git clone --recursive https://github.com/poanetwork/tokenbridge
cd tokenbridge/deployment/oracle
```
2. Create the file `hosts.yml` from `hosts.yml.example`
```
cp hosts.yml.example hosts.yml
```
`hosts.yml` should have the following structure:
```yaml
<bridge_name>:
hosts:
<host_ip>:
ansible_user: <user>
VALIDATOR_ADDRESS_PRIVATE_KEY: "<private_key>"
#syslog_server_port: "<protocol>://<ip>:<port>" # When this parameter is set all bridge logs will be redirected to <ip>:<port> address.
```
| Value | Description |
|:------------------------------------------------|:----------------------------------------------------------------------------------------------------------|
| `<bridge_name>` | The bridge name which tells Ansible which file to use. This is located in `group_vars/<bridge_name>.yml`. |
| `<host_ip>` | Remote server IP address. |
| ansible_user: `<user>` | User that will ssh into the node. This is typically `ubuntu` or `root`. |
| VALIDATOR_ADDRESS_PRIVATE_KEY: `"<private_key>"` | The private key for the specified validator address. |
| syslog_server_port: `"<protocol>://<ip>:<port>"` | Optional port specification for bridge logs. This value will be provided by an administrator if required. |
`hosts.yml` can contain multiple hosts and bridge configurations (groups) at once.
3. Copy the bridge name(s) to the hosts.yml file.
1. Go to the group_vars folder.
`cd group_vars`
2. Note the <bridge_name> and add it to the hosts.yml configuration. For example, if a bridge file is named sokol-kovan.yml, you would change the <bridge_name> value in hosts.yml to sokol-kovan.
#### Administrator Configurations
1. The `group_vars/<bridge_name>.yml` file contains the public bridge parameters. This file is prepared by administrators for each bridge. The validator only needs to add the required bridge name in the hosts.yml file to tell Ansible which file to use.
`group_vars/example.yml` shows an example configuration for the POA/Sokol - POA/Sokol bridge. Parameter values should match values from the .env file for the Oracle. See [Configuration parameters](../../oracle/README.md#configuration-parameters) for details.
2. You can also add the following parameters in the `group_vars` to change the default behavior of `deployment-bridge` playbooks:
2.1 `compose_service_user` - specifies users to be created by playbooks. This user will be used to run Token Bridge Oracle.
2.2 `bridge_repo` contains address of Token Bridge Oracle repository. The default value is https://github.com/poanetwork/tokenbridge.
2.3 `bridge_repo_branch` points to the specific branch or commit to use with the `bridge_repo`. If `bridge_repo_branch` is not specified, the default (`master`) branch is used.
2.4 `bridge_path` set the path where Token Bridge Oracle would be installed. By default it point to the home folder of `compose_service_user`
2.5 `docker_compose_version` - specifies a version of docker-compose to be installed.
2.6 `ALLOW_HTTP` (`no` by default) can be set to `yes` to allow bridge insecure connections to the network.
## Execution
The playbook can be executed once [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) is installed and all configuration variables are set.
It will automatically install `Docker`, `docker-compose`, `Python`, `Git` and it dependencies (such as `curl`, `ca-certificates`, `apt-transport-https`, etc.) to the node. Also this playbooks creates an additional non-sudo docker user to run service as.
```yaml
ansible-playbook -i hosts.yml site.yml
```
**Useful arguments:**
To be used with the ansible-playbook command, for example:
```yaml
`ansible-playbook -i hosts.yml site.yml --ask-become-pass`
```
* `--ask-pass` - ask for the password used to connect to the bridge VM.
* `--ask-become-pass` - ask for the `become` password used to execute some commands (such as Docker installation) with root privileges.
* `-i <file>` - use specified file as a `hosts.yml` file.
* `-e "<variable>=<value>"` - override default variable.
* `--private-key=<file_name>` - if private keyfile is required to connect to the ubuntu instance.
* `--user=<username>` - connect as this username
## Bridge service commands
The Bridge service is named `poabridge`. Use the default `SysVinit` commands to `start`, `stop`, `restart`, and `rebuild` the service and to check the `status` of the service.
Commands format:
```bash
sudo service poabridge [start|stop|restart|status|rebuild]
```
## Rollback the Last Processed Block in Redis
If the bridge does not handle an event properly (i.e. a transaction stalls due to a low gas price), the Redis DB can be rolled back. You must identify which watcher needs to re-run. For example, if the validator signatures were collected but the transaction with signatures was not sent to the Foreign network, the `collected-signatures` watcher must look at the block where the corresponding `CollectedSignatures` event was raised.
Execute the `reset-lastBlock.sh` script in the bridge root directory. For example, if you've installed your bridge with this deployment script and all the default parameters, use the following set of commands:
```shell
$ sudo su poadocker
$ cd ~/bridge
$ docker-compose exec bridge_affirmation bash ./reset-lastBlock.sh <watcher> <block num>
$ exit
$ sudo service poabridge restart
```
where the _<watcher>_ could be one of the following:
- `signature-request`
- `collected-signatures`
- `affirmation-request`
## Logs
If the `syslog_server_port` option in the hosts.yml file is not set, all logs will be stored in `/var/log/docker/` folder in the set of folders with the `bridge_` prefix.
If the `syslog_server_port` is set, logs will be redirected to the specified server and cannot be accessed on the bridge machine.
```yaml
syslog_server_port: "<protocol>://<ip>:<port>" # When this parameter is set all bridge logs will be redirected to the <ip>:<port> address.
```

View File

@@ -1,24 +0,0 @@
## General settings
BRIDGE_MODE: "ERC_TO_NATIVE"
## Home contract
HOME_RPC_URL: "https://dai.poa.network"
HOME_BRIDGE_ADDRESS: "0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6"
HOME_POLLING_INTERVAL: 5000
## Foreign contract
FOREIGN_RPC_URL: "https://mainnet.infura.io"
FOREIGN_BRIDGE_ADDRESS: "0x4aa42145Aa6Ebf72e164C9bBC74fbD3788045016"
ERC20_TOKEN_ADDRESS: "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"
FOREIGN_POLLING_INTERVAL: 5000
## Gasprice
#HOME_GAS_PRICE_ORACLE_URL: "https://localhost:8888/"
HOME_GAS_PRICE_SPEED_TYPE: "standard"
HOME_GAS_PRICE_FALLBACK: 0
HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
FOREIGN_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/"
FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
FOREIGN_GAS_PRICE_FALLBACK: 10000000000
FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000

View File

@@ -1,24 +0,0 @@
## General settings
BRIDGE_MODE: "NATIVE_TO_ERC"
## Home contract
HOME_RPC_URL: "https://sokol.poa.network"
HOME_BRIDGE_ADDRESS: "0x98aFdE294f1C46aA0a27Cc4049ED337F879d8976"
HOME_POLLING_INTERVAL: 5000
## Foreign contract
FOREIGN_RPC_URL: "https://sokol.poa.network"
FOREIGN_BRIDGE_ADDRESS: "0x5a584f4C30B36f282848dAc9a2b20E7BEF481981"
ERC20_TOKEN_ADDRESS: "0x6ef22442D600E1865AD8A8c254d6befCe7f4e6e4"
FOREIGN_POLLING_INTERVAL: 1000
## Gasprice
HOME_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/"
HOME_GAS_PRICE_SPEED_TYPE: "standard"
HOME_GAS_PRICE_FALLBACK: 1000000000 # in wei
HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
FOREIGN_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/"
FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
FOREIGN_GAS_PRICE_FALLBACK: 1000000000 # in wei
FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000

View File

@@ -1,24 +0,0 @@
## General settings
BRIDGE_MODE: "NATIVE_TO_ERC"
## Home contract
HOME_RPC_URL: "https://ethereumclassic.network"
HOME_BRIDGE_ADDRESS: "0x073081832B4Ecdce79d4D6753565c85Ba4b3BeA9"
HOME_POLLING_INTERVAL: 7000
## Foreign contract
FOREIGN_RPC_URL: "https://mainnet.infura.io/"
FOREIGN_BRIDGE_ADDRESS: "0x0cB781EE62F815bdD9CD4c2210aE8600d43e7040"
ERC20_TOKEN_ADDRESS: "0x86aaBCc646f290b9Fc9Bd05CE17C3858d1511Da1"
FOREIGN_POLLING_INTERVAL: 7000
## Gasprice
HOME_GAS_PRICE_ORACLE_URL: "https://gasprice-etc.poa.network/"
HOME_GAS_PRICE_SPEED_TYPE: "standard"
HOME_GAS_PRICE_FALLBACK: 15000000000 # in wei
HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
FOREIGN_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/"
FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
FOREIGN_GAS_PRICE_FALLBACK: 10000000000 # in wei
FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000

View File

@@ -1,6 +0,0 @@
sokol-kovan:
hosts:
127.0.0.1:
ansible_user: ubuntu
VALIDATOR_ADDRESS_PRIVATE_KEY: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#syslog_server_port: "udp://127.0.0.1:514"

View File

@@ -1,17 +0,0 @@
This role installs required dependencies:
* apt-transport-https
* ca-certificates
* curl
* software-properties-common
* docker-ce (+python library)
* docker-compose (+python library)
* git
* python-pip

View File

@@ -1,2 +0,0 @@
docker_compose_version: 1.22.0
compose_service_user: poadocker

View File

@@ -1 +0,0 @@
This role brings up a docker container using docker-compose.

View File

@@ -1 +0,0 @@
bridge_path: "/home/{{ compose_service_user }}/bridge"

View File

@@ -1,4 +0,0 @@
- name: Launch container
shell: docker-compose up -d
args:
chdir: "{{ bridge_path }}/oracle"

View File

@@ -1 +0,0 @@
This role sets up remote logging for services.

View File

@@ -1,2 +0,0 @@
bridge_path: "/home/{{ compose_service_user }}/bridge"
syslog_server_port: udp://127.0.0.1:514

View File

@@ -1 +0,0 @@
This role gets the start blocks for both home and foreign networks.

View File

@@ -1 +0,0 @@
bridge_path: "/home/{{ compose_service_user }}/bridge"

View File

@@ -1,33 +0,0 @@
- name: Get blocks
become_user: "{{ compose_service_user }}"
shell: docker-compose run --entrypoint "node scripts/getValidatorStartBlocks.js" bridge_affirmation
args:
chdir: "{{ bridge_path }}/oracle"
register: BLOCKS
- name: Write blocks
blockinfile:
path: "{{ bridge_path }}/oracle/.env"
marker: "## {mark} Calculated by scripts/getValidatorStartBlocks.js"
block: |
HOME_START_BLOCK={{ (BLOCKS.stdout | from_json).homeStartBlock }}
FOREIGN_START_BLOCK={{ (BLOCKS.stdout | from_json).foreignStartBlock }}
- name: Get validator address
become_user: "{{ compose_service_user }}"
shell: docker-compose run -e VALIDATOR_ADDRESS_PRIVATE_KEY="{{ VALIDATOR_ADDRESS_PRIVATE_KEY }}" --entrypoint "node scripts/privateKeyToAddress.js" bridge_affirmation
args:
chdir: "{{ bridge_path }}/oracle"
register: VADDRESS
- name: Set VALIDATOR_ADDRESS variable
set_fact:
VALIDATOR_ADDRESS: "{{ VADDRESS.stdout }}"
- name: Install .key config
template:
src: key.j2
dest: "/root/.key"
owner: root
group: root
mode: 0600

View File

@@ -1 +0,0 @@
This role sets the .env config (excluding starting blocks).

View File

@@ -1,6 +0,0 @@
bridge_path: "/home/{{ compose_service_user }}/bridge"
ALLOW_HTTP: no
QUEUE_URL: amqp://rabbit
REDIS_URL: redis://redis
REDIS_LOCK_TTL: 1000

View File

@@ -1,42 +0,0 @@
## General settings
BRIDGE_MODE={{ BRIDGE_MODE }}
## Home contract
HOME_RPC_URL={{ HOME_RPC_URL }}
HOME_BRIDGE_ADDRESS={{ HOME_BRIDGE_ADDRESS }}
HOME_POLLING_INTERVAL={{ HOME_POLLING_INTERVAL }}
## Foreign contract
FOREIGN_RPC_URL={{ FOREIGN_RPC_URL }}
FOREIGN_BRIDGE_ADDRESS={{ FOREIGN_BRIDGE_ADDRESS }}
ERC20_TOKEN_ADDRESS={{ ERC20_TOKEN_ADDRESS }}
FOREIGN_POLLING_INTERVAL={{ FOREIGN_POLLING_INTERVAL }}
## Gasprice
{% if HOME_GAS_PRICE_ORACLE_URL | default('') != '' %}
HOME_GAS_PRICE_ORACLE_URL={{ HOME_GAS_PRICE_ORACLE_URL }}
{% endif %}
{% if HOME_GAS_PRICE_SPEED_TYPE | default('') != '' %}
HOME_GAS_PRICE_SPEED_TYPE={{ HOME_GAS_PRICE_SPEED_TYPE }}
{% endif %}
HOME_GAS_PRICE_FALLBACK={{ HOME_GAS_PRICE_FALLBACK }}
{% if HOME_GAS_PRICE_UPDATE_INTERVAL | default('') != '' %}
HOME_GAS_PRICE_UPDATE_INTERVAL={{ HOME_GAS_PRICE_UPDATE_INTERVAL }}
{% endif %}
{% if FOREIGN_GAS_PRICE_ORACLE_URL | default('') != '' %}
FOREIGN_GAS_PRICE_ORACLE_URL={{ FOREIGN_GAS_PRICE_ORACLE_URL }}
{% endif %}
{% if FOREIGN_GAS_PRICE_SPEED_TYPE | default('') != '' %}
FOREIGN_GAS_PRICE_SPEED_TYPE={{ FOREIGN_GAS_PRICE_SPEED_TYPE }}
{% endif %}
FOREIGN_GAS_PRICE_FALLBACK={{ FOREIGN_GAS_PRICE_FALLBACK }}
{% if FOREIGN_GAS_PRICE_UPDATE_INTERVAL | default('') != '' %}
FOREIGN_GAS_PRICE_UPDATE_INTERVAL={{ FOREIGN_GAS_PRICE_UPDATE_INTERVAL }}
{% endif %}
## Transport configuration
ALLOW_HTTP={{ "yes" if ALLOW_HTTP else "no" }}
QUEUE_URL={{ QUEUE_URL }}
REDIS_URL={{ REDIS_URL }}
REDIS_LOCK_TTL={{ REDIS_LOCK_TTL }}

View File

@@ -1 +0,0 @@
This role clones the repo from a specified URL.

View File

@@ -1,3 +0,0 @@
bridge_path: "/home/{{ compose_service_user }}/bridge"
bridge_repo: https://github.com/poanetwork/tokenbridge.git
bridge_repo_branch: master

View File

@@ -1,6 +0,0 @@
- name: Get bridge repo
git:
repo: "{{ bridge_repo }}"
dest: "{{ bridge_path }}"
force: yes
version: "{{ bridge_repo_branch }}"

View File

@@ -1,5 +0,0 @@
This role creates a poabridge service which is designed to manage docker-compose bridge deployment.
/etc/init.d/poabridge start, status, stop, restart - does what the services usually do in such cases.
/etc/init.d/poabridge rebuild - builds a new bridge deployment from scratch.

View File

@@ -1,4 +0,0 @@
---
# defaults
bridge_path: "/home/{{ compose_service_user }}/bridge"
keyfile_path: "/root/.key"

View File

@@ -1,14 +0,0 @@
---
- name: "Set poabridge service"
template:
src: poabridge.j2
dest: "/etc/init.d/poabridge"
owner: root
mode: 755
- name: "Start/Enable poabridge service"
service:
name: "poabridge"
state: started
enabled: yes
use: service

View File

@@ -1,19 +0,0 @@
- name: Install python if necessary
hosts: all
gather_facts: false
become: true
tasks:
- name: Install python
raw: "test -e {{ ansible_python_interpreter | default ('/usr/bin/python') }} || (sudo apt -y update && sudo apt install -y python-minimal)"
tags: install_dependencies
- name: Install bridge
hosts: all
roles:
- { role: dependencies, tags: install_dependencies, become: true }
- { role: repo, tags: clone_repo, become: true }
- { role: pre_config, tags: pre_config, become: true }
- { role: jumpbox, tags: launch_jumpbox, become: true }
- { role: post_config, tags: post_config, become: true }
- { role: logging, tags: set_logging, become: true}
- { role: servinstall, tags: install_service, become: true }

View File

@@ -0,0 +1,4 @@
# pre-release because it contains "CI Fixes for ansible 2.8"
molecule==2.22rc1
docker
flake8

View File

@@ -0,0 +1,4 @@
---
docker_compose_version: 1.23.2
compose_service_user: poadocker
bridge_path: "/home/{{ compose_service_user }}/bridge"

View File

@@ -1,5 +1,4 @@
{
"disable-legacy-registry": true,
"live-restore": true,
"no-new-privileges": true
}

View File

@@ -1,3 +1,4 @@
---
- name: restart rsyslog
service:
name: rsyslog

View File

@@ -1,8 +1,9 @@
---
- name: Install the gpg key for docker
apt_key:
url: "https://download.docker.com/linux/ubuntu/gpg"
state: present
- name: Install the docker repos
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
@@ -19,7 +20,8 @@
- software-properties-common
- docker-ce
- git
- "{{ (ansible_python_interpreter | default ('python')).split('/')[-1] }}-pip"
- python3
- python3-pip
- name: Install Docker Compose
get_url:
@@ -29,13 +31,9 @@
owner: "root"
group: "root"
mode: "0755"
- name: Install python docker library
pip:
name: "{{ item }}"
with_items:
- docker
- docker-compose
shell: pip3 install docker docker-compose setuptools
- name: Add user to run docker-compose
user:
@@ -52,7 +50,7 @@
- name: Configure auditd
blockinfile:
path: /etc/audit/audit.rules
block: |
block: |
-w /usr/bin/docker -p wa
-w /var/lib/docker -p wa
-w /etc/docker -p wa
@@ -61,13 +59,13 @@
-w /etc/default/docker -p wa
-w /etc/docker/daemon.json -p wa
-w /usr/bin/docker-containerd -p wa
-w /usr/bin/docker-runc -p wa
-w /usr/bin/docker-runc -p wa
notify: restart auditd
- name: Configure docker engine
copy:
src: daemon.json
dest: /etc/docker/daemon.json
dest: /etc/docker/
owner: root
group: root
mode: 0640

View File

@@ -0,0 +1,30 @@
---
- name: Set the local docker logs configuration file
template:
src: 30-docker.conf.j2
dest: /etc/rsyslog.d/30-docker.conf
owner: root
group: root
mode: 0644
- name: Set the log configuration file to send docker logs to remote server
template:
src: 35-docker-remote-logging.conf.j2
dest: /etc/rsyslog.d/35-docker-remote-logging.conf
owner: root
group: root
mode: 0644
when: syslog_server_port is defined
- name: Set the logrotate config file
template:
src: docker-logs.j2
dest: /etc/logrotate.d/docker-logs
owner: root
group: root
mode: 0644
- name: restart rsyslog
service:
name: rsyslog
state: restarted

View File

@@ -0,0 +1,4 @@
---
- include_tasks: dependencies.yml
- include_tasks: repo.yml
- include_tasks: logging.yml

View File

@@ -0,0 +1,34 @@
---
- name: Create archives of the monorepository
shell: |
(git ls-tree -r HEAD --name-only | sed '/^contracts$/d') | xargs tar zcfv monorepo.tar.gz --files-from -
cd contracts; (git ls-tree -r HEAD --name-only) | xargs tar zcfv ../contracts.tar.gz --files-from -
delegate_to: 127.0.0.1
become: false
args:
chdir: "{{ lookup('env', 'PWD') }}/.."
- name: Copy the archives
copy:
src: ../../../../{{ item }}
dest: "{{ bridge_path }}/"
with_items:
- monorepo.tar.gz
- contracts.tar.gz
- name: Untar the archives
shell: |
tar zxfv monorepo.tar.gz && rm monorepo.tar.gz
mkdir -p contracts && tar zxfv contracts.tar.gz -C ./contracts && rm contracts.tar.gz
args:
chdir: "{{ bridge_path }}"
- name: Remove local archives
shell: rm {{ item }}
delegate_to: 127.0.0.1
become: false
args:
chdir: "{{ lookup('env', 'PWD') }}/.."
with_items:
- monorepo.tar.gz
- contracts.tar.gz

Some files were not shown because too many files have changed in this diff Show More